在 Python 中即时向 class 添加方法(角色)——有危险吗?

Adding methods (roles) to a class on the fly in Python - dangers?

我正在学习 python,并且与 class 一起玩得很开心。由于我习惯于在其他情况下使用 roles or traits 并发现它们非常有用,因此我正在研究同一类事情 - 将 class 添加到另一个 class' 继承链。像这样:

class A():
    def foo(self):
        print('foo')


class B():
    def bar(self):
        print('bar')


a = A()
b = B()

a.foo()
b.bar()

class C(A, B):
    pass


class Z():
    def baz(self):
        print('baz')

C = type("C", (C, Z), {})

c = C()

c.foo()
c.bar()
c.baz()

在现实生活中 C 可能已经在别处定义了,不一定由我定义。

似是而非:有没有我可能没有意识到的隐患?显然:重新定​​义现有方法 - 但还有别的吗?

这只是正常的继承。您似乎误解了这一点,因为您将 subclass 命名为其基础 class 之一,即 C.

但是

C = type("C", (C, Z), {})

等同于:

class C(C, Z):
    pass

注意,很重要,如果存在原C的实例:

>>> class A():
...     def foo(self):
...         print('foo')
...
>>>
>>> class B():
...     def bar(self):
...         print('bar')
...
>>> class C(A, B):
...     pass
...
>>> old_c_instance = C()

它不会被认为是新 C:

的一个实例
>>> class Z():
...     def baz(self):
...         print('baz')
...
>>> C = type("C", (C, Z), {})
>>> isinstance(old_c_instance, C)
False

注意,旧的C是可以恢复的,它将是方法解析顺序中的第二个class(基础的第一个):

>>> OldC = C.mro()[1]
>>> OldC
<class '__main__.C'>
>>> C
<class '__main__.C'>
>>> isinstance(old_c_instance, OldC)
True

所以这只是一个容易混淆的命名子示例class。

注意,这里的模式是“Mixin模式”。如 wiki-link 中所述,特征基本上类似于混合,但它们通常不携带实例状态。好吧,你可以 从你的 mixin 中省略 ,现在你基本上有一个特征......使用继承。

请注意,您 可以 实际上在 Python 中动态添加方法:

class A():
    def foo(self):
        print('foo')

class B():
    def bar(self):
        print('bar')

class C(A, B):
    pass

然后,像这样:

def baz(self):
    print('baz')

def qux(self):
    print('qux')

for func in [baz, qux]:
    setattr(C, func.__name__, func)

C().baz()
C().qux()

这避免了继承和创建新的 class。 Python.

中的许多元编程都非常普通