如何自定义Python的方法解析顺序(mro)?
How to customize the method resolution order (mro) of Python?
我想自定义调用我继承的方法。
这是一个示例代码:
class First(object):
def get(self):
print('getting from first')
def set(self):
print('setting to first')
class Second(object):
def get(self):
print('getting from second')
def set(self):
print('setting to second')
class Third(First, Second):
def get(self):
super(Third, self).get()
def set(self):
super(Third, self).set()
现在我想要的行为是:
third = Third()
third.get() # -> should print 'getting from first'
third.set() # -> should print 'setting to second'
现在 mro 显示:
Third.__mro__ -> (__main__.Third, __main__.First, __main__.Second, object)
我们可以看到 main.First 中的方法总是先被调用。虽然我想要的是 main.Second 在执行 set() 方法期间首先被调用。
这是我解决这个问题的尝试,尝试修改 Third 的 MRO class:
思路是把两个class的两个位置互换一下,看看能不能行得通。
首先,一个 swap()
辅助函数。
def swap(index1, index2, mro_tuple):
l = list(mro_tuple)
temp = l[index1]
l[index1] = l[index2]
l[index2] = temp
return tuple(l)
然后在 set()
方法的实现过程中,我尝试修改底层 class 的 mro .
class Third(First, Second):
def get(self):
super(Third, self).get()
def set(self):
self.__class__.__mro__ = swap(1, 2, self.__class__.__mro__) # swap here..
super(Third, self).set() # then call method**
In [43]: third = Third()
In [44]: third.get()
getting from first
In [45]: third.set()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-53-c82ac1a0d5bc> in <module>
----> 1 third.set()
<ipython-input-50-00c9baff0d57> in set(self)
4
5 def set(self):
----> 6 self.__class__.__mro__ = swap(1, 2, self.__class__.__mro__) # swap here..
7 super(Third, self).set() # then call method
8
AttributeError: readonly attribute
说明无法重置__mro__
属性
有没有一种方便的方式来实现这种行为?
您最好的选择可能是 Third
明确使用 Second
实现:
class Third(First, Second):
set = Second.set
虽然您问这个问题是一个警告信号,表明您可能选择了错误的 class 层次结构。
我想自定义调用我继承的方法。
这是一个示例代码:
class First(object):
def get(self):
print('getting from first')
def set(self):
print('setting to first')
class Second(object):
def get(self):
print('getting from second')
def set(self):
print('setting to second')
class Third(First, Second):
def get(self):
super(Third, self).get()
def set(self):
super(Third, self).set()
现在我想要的行为是:
third = Third()
third.get() # -> should print 'getting from first'
third.set() # -> should print 'setting to second'
现在 mro 显示:
Third.__mro__ -> (__main__.Third, __main__.First, __main__.Second, object)
我们可以看到 main.First 中的方法总是先被调用。虽然我想要的是 main.Second 在执行 set() 方法期间首先被调用。
这是我解决这个问题的尝试,尝试修改 Third 的 MRO class:
思路是把两个class的两个位置互换一下,看看能不能行得通。
首先,一个 swap()
辅助函数。
def swap(index1, index2, mro_tuple):
l = list(mro_tuple)
temp = l[index1]
l[index1] = l[index2]
l[index2] = temp
return tuple(l)
然后在 set()
方法的实现过程中,我尝试修改底层 class 的 mro .
class Third(First, Second):
def get(self):
super(Third, self).get()
def set(self):
self.__class__.__mro__ = swap(1, 2, self.__class__.__mro__) # swap here..
super(Third, self).set() # then call method**
In [43]: third = Third()
In [44]: third.get()
getting from first
In [45]: third.set()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-53-c82ac1a0d5bc> in <module>
----> 1 third.set()
<ipython-input-50-00c9baff0d57> in set(self)
4
5 def set(self):
----> 6 self.__class__.__mro__ = swap(1, 2, self.__class__.__mro__) # swap here..
7 super(Third, self).set() # then call method
8
AttributeError: readonly attribute
说明无法重置__mro__
属性
有没有一种方便的方式来实现这种行为?
您最好的选择可能是 Third
明确使用 Second
实现:
class Third(First, Second):
set = Second.set
虽然您问这个问题是一个警告信号,表明您可能选择了错误的 class 层次结构。