有一件非常重要的事情需要注意——如果这些属性留在类中,那么__slots__
生成将是无用的……好吧,也许不是无用的——它会使类属性变为只读;这可能不是你想要的。
简单的方法是说,“好的,我会将它们初始化为None,然后让它们消失。”太棒了!以下是一种实现方式:
class B(object):
three = None
four = None
temp = vars()
__slots__ = temp.keys()
__slots__.remove('temp')
__slots__.remove('__module__')
for name in __slots__:
del temp[name]
del temp
如果你想保留那些初始值,需要更多的工作...这里有一个可能的解决方案:
class B(object):
three = 3
four = 4
def __init__(self):
for key, value in self.__init__.defaults.items():
setattr(self, key, value)
temp = vars()
__slots__ = temp.keys()
__slots__.remove('temp')
__slots__.remove('__module__')
__slots__.remove('__init__')
__init__.defaults = dict()
for name in __slots__:
__init__.defaults[name] = temp[name]
del temp[name]
del temp
正如您所看到的,即使没有元类,也可以做到这一点--但是谁想要所有那些样板文件呢?元类肯定可以帮助我们整理好这个问题:
class MakeSlots(type):
def __new__(cls, name, bases, attrs):
new_attrs = {}
new_attrs['__slots__'] = slots = attrs.keys()
slots.remove('__module__')
slots.remove('__metaclass__')
new_attrs['__weakref__'] = None
new_attrs['__init__'] = init = new_init
init.defaults = dict()
for name in slots:
init.defaults[name] = attrs[name]
return super(MakeSlots, cls).__new__(cls, name, bases, new_attrs)
def new_init(self):
for key, value in self.__init__.defaults.items():
setattr(self, key, value)
class A(object):
__metaclass__ = MakeSlots
one = 1
two = 2
class B(object):
__metaclass__ = MakeSlots
three = 3
four = 4
现在所有的繁琐都被保留在元类中,而实际的类易于阅读和(希望!)理解。
如果除了属性之外,您需要在这些类中添加任何其他内容,我强烈建议您将它们放入混合类中--直接将它们放在最终类中会使元类变得更加复杂。
__module__
等)。你能否澄清你的问题,或者接受我的答案,它确实可以做到你所要求的? - Ethan Furman