This article的代码片段显示了__bases__的用法,该方法是通过将一个类添加到从其继承的现有类集合中来动态更改某些Python代码的继承层次结构。好的,这很难看懂,代码可能更清晰:

class Friendly:
    def hello(self):
        print 'Hello'

class Person: pass

p = Person()
Person.__bases__ = (Friendly,)
p.hello()  # prints "Hello"

也就是说,Person不在源级别上从Friendly继承,而是通过修改Person类的__bases__属性在运行时动态添加此继承关系。但是,如果将FriendlyPerson更改为新的样式类(通过从object继承),则会出现以下错误:

TypeError: __bases__ assignment: 'Friendly' deallocator differs from 'object'

对于在运行时更改继承层次结构,新样式类和旧样式类之间的ogt_a有点类似。具体来说:indicate some incompatibilities

我的问题是,是否有可能通过使用__mro__属性在Python 2.7+中使用新型类来使上面的Friendly/Person示例工作?

免责声明:我完全意识到这是晦涩的代码。我完全意识到,在实际的生产代码中,这样的技巧往往难以理解,这纯粹是一个思想实验,并且使人们可以从中学习一些有关Python如何处理与多重继承相关的问题的知识。

最佳答案

好的,同样,这不是您通常应该执行的操作,仅用于提供信息。

Python在实例对象上查找方法的位置由定义该对象的类的__mro__属性确定( M 方法 R esolution O rder属性)。因此,如果我们可以修改__mro__Person,我们将获得所需的行为。就像是:

setattr(Person, '__mro__', (Person, Friendly, object))

问题在于__mro__是只读属性,因此setattr将不起作用。也许如果您是Python专家,那么可以采取一些措施,但是显然我没有达到专家地位,因为我想不到。

一个可能的解决方法是简单地重新定义该类:
def modify_Person_to_be_friendly():
    # so that we're modifying the global identifier 'Person'
    global Person

    # now just redefine the class using type(), specifying that the new
    # class should inherit from Friendly and have all attributes from
    # our old Person class
    Person = type('Person', (Friendly,), dict(Person.__dict__))

def main():
    modify_Person_to_be_friendly()
    p = Person()
    p.hello()  # works!

这不做的是修改任何以前创建的Person实例,使其具有hello()方法。例如(仅修改main()):
def main():
    oldperson = Person()
    ModifyPersonToBeFriendly()
    p = Person()
    p.hello()
    # works!  But:
    oldperson.hello()
    # does not

如果type调用的详细信息不清楚,请阅读e-satis' excellent answer on 'What is a metaclass in Python?'

关于python - 如何在运行时动态更改实例的基类?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9539052/

10-12 21:44
查看更多