本文介绍了如何在运行时动态更改实例的基类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一个片段,显示 __ bases __ 动态更改某些Python代码的继承层次结构,方法是将类添加到它继承的类的现有类集合中。好的,这很难读,代码可能更清晰:

This article has a snippet showing usage of __bases__ to dynamically change the inheritance hierarchy of some Python code, by adding a class to an existing classes collection of classes from which it inherits. Ok, that's hard to read, code is probably clearer:

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

class Person: pass

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

不从源级别的 Friendly 继承,而是在运行时通过修改 __ bases __ Friendly Person 更改为新样式类(通过继承自object),您将获得以下内容:错误:

That is, Person doesn't inherit from Friendly at the source level, but rather this inheritance relation is added dynamically at runtime by modification of the __bases__attribute of the Person class. However, if you change Friendly and Person to be new style classes (by inheriting from object), you get the following error:

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

Google上的一些谷歌搜索似乎。

A bit of Googling on this seems to indicate some incompatibilities between new-style and old style classes in regards to changing the inheritance hierarchy at runtime. Specifically: "New-style class objects don't support assignment to their bases attribute".

我的问题是,是否可以使用Python 2.7中的新式类使上述Friendly / Person示例工作+,可能使用 __ mro __ 属性?

My question, is it possible to make the above Friendly/Person example work using new-style classes in Python 2.7+, possibly by use of the __mro__ attribute?

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

Disclaimer: I fully realise that this is obscure code. I fully realize that in real production code tricks like this tend to border on unreadable, this is purely a thought experiment, and for funzies to learn something about how Python deals with issues related to multiple inheritance.

推荐答案

好的,这不是您通常应该做的事情,这仅供参考。

Ok, again, this is not something you should normally do, this is for informational purposes only.

Python在实例对象上查找方法的方法取决于类的 __ mro __ 属性,该属性定义了object( M ethod R esolution O rder属性)。因此,如果我们可以修改 __ mro __ ,我们就会得到所需的行为。类似于:

Where Python looks for a method on an instance object is determined by the __mro__ attribute of the class which defines that object (the M ethod R esolution O rder attribute). Thus, if we could modify the __mro__ of Person, we'd get the desired behaviour. Something like:

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

问题是 __ mro __ 是一个只读属性,因此setattr赢了'工作。也许如果你是一个Python大师,有一种解决方法,但显然我没有达到大师的地位,因为我想不到一个。

The problem is that __mro__ is a readonly attribute, and thus setattr won't work. Maybe if you're a Python guru there's a way around that, but clearly I fall short of guru status as I cannot think of one.

一个可能的解决方法是简单地重新定义类:

A possible workaround is to simply redefine the class:

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!

这不做的是修改以前创建的任何具有 hello()方法的实例。例如(只修改 main()):

What this doesn't do is modify any previously created Person instances to have the hello() method. For example (just modifying main()):

def main():
    oldperson = Person()
    ModifyPersonToBeFriendly()
    p = Person()
    p.hello()
    # works!  But:
    oldperson.hello()
    # does not

如果详情的类型调用不清楚,然后阅读。

If the details of the type call aren't clear, then read e-satis' excellent answer on 'What is a metaclass in Python?'.

这篇关于如何在运行时动态更改实例的基类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-07 18:39