把这个问题的答案和related question 放在一起,我想强调一下这个问题的解决方案:
您可以某种修改__slots__,方法是创建一个具有相同名称的子类,然后用其子类替换父类。请注意,您可以为在任何模块中声明和使用的类执行此操作,而不仅仅是您的!
考虑以下声明了一些类的模块:
module.py:
class A(object):
# some class a user should import
__slots__ = ('x', 'b')
def __init__(self):
self.b = B()
class B(object):
# let's suppose we can't use it directly,
# it's returned as a part of another class
__slots__ = ('z',)
以下是向这些类添加属性的方法:
>>> import module
>>> from module import A
>>>
>>> # for classes imported into your module:
>>> A = type('A', (A,), {'__slots__': ('foo',)})
>>> # for classes which will be instantiated by the `module` itself:
>>> module.B = type('B', (module.B,), {'__slots__': ('bar',)})
>>>
>>> a = A()
>>> a.x = 1
>>> a.foo = 2
>>>
>>> b = a.b
>>> b.z = 3
>>> b.bar = 4
>>>
但是,如果您使用 module 从某个第三方模块接收类实例怎么办?
module_3rd_party.py:
from module import A
def get_instance():
return A()
没问题,它也可以!唯一的区别是您可能需要在导入第三方模块之前对它们进行修补(以防它从module 导入类):
>>> import module
>>>
>>> module.A = type('A', (module.A,), {'__slots__': ('foo',)})
>>> module.B = type('B', (module.B,), {'__slots__': ('bar',)})
>>>
>>> # note that we import `module_3rd_party` AFTER we patch the `module`
>>> from module_3rd_party import get_instance
>>>
>>> a = get_instance()
>>> a.x = 1
>>> a.foo = 2
>>>
>>> b = a.b
>>> b.z = 3
>>> b.bar = 4
>>>
之所以有效,是因为 Python 只导入一次模块,然后在所有其他模块之间共享它们,因此您对模块所做的更改会影响沿您的模块运行的所有代码。