Python __slots__ 元类问题
Python __slots__ metaclass issue
我目前正在使用 type()
:
实现开槽元类
type(i, (), {'__slots__': tuple(data)
我当然会理想地保留插槽,因为我有一个用例,可以受益于它们更小的内存占用和更高的访问速度。
当我这样做时:
dir(slotted_class)
>>>['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'slotted_attribute1',
'slotted_attribute2',
'slotted_attribute3',
'slotted_attribute4']
然而当我运行:
slottedclass.slotted_attribute1
我收到以下错误:
>>> AttributeError Traceback (most recent call last)
<ipython-input-58-88291109fa74> in <module>()
----> 1 slotted_class.slotted_attribute1
AttributeError: slotted_attribute1
编辑:更多信息和更多困惑:
如果我不使用元类直接实现一个等价物:
class slottedclass_non_meta(object):
__slots__ = ['slotted_attribute1', 'slotted_attribute2', 'slotted_attribute3', 'slotted_attribute4']
def __init__(self, slotted_attribute1, slotted_attribute2, slotted_attribute3, slotted_attribute4):
self.slotted_attribute1, self.slotted_attribute2, self.slotted_attribute3, self.slotted_attribute4 = slotted_attribute1, slotted_attribute2, slotted_attribute3, slotted_attribute4
然后做这个对比
目录(开槽类)== 目录(slottedclass_non_meta)
>>> True
这可能只是您的 data
变量的一些错误。制作
确保它是可迭代的或字符串序列。
在我的交互式环境中尝试这个完美无缺:
In [162]: m = type("m", (), {"__slots__": ("test1",)})
In [163]: m.test1
Out[163]: <member 'test1' of 'm' objects>
In [164]: n = m()
In [165]: n.test1 = 10
In [166]: n.test1
Out[166]: 10
其他注意事项:
- 为此您不需要说您是 "using metaclasses"(尽管从技术上讲您是)- 只需说您正在通过调用
type
动态创建 classes。在阅读问题标题时,大多数人会认为您正在尝试专门化 type
本身并在其中包含 __slots__
。
- 在您粘贴的示例代码中,您没有用于动态创建的 class 的
__init__
方法:因此您显然无法在 [=34= 上传递名称参数] 创建并在实例上自动设置它们,就像您在显式 class. 上所做的那样
如果第二个主题是你的问题,我建议不要继承 object
(暗示但他是空的 - () - 要调用的第二个参数),创建一个具有泛型的 baseclass __init__
将 kwargs 设置为属性的方法:
class Base:
__slots__ = ()
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
slotted_class = type("slotted_class", (Base,), {"__slots__": ...})
我目前正在使用 type()
:
type(i, (), {'__slots__': tuple(data)
我当然会理想地保留插槽,因为我有一个用例,可以受益于它们更小的内存占用和更高的访问速度。
当我这样做时:
dir(slotted_class)
>>>['__class__',
'__delattr__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__slots__',
'__str__',
'__subclasshook__',
'slotted_attribute1',
'slotted_attribute2',
'slotted_attribute3',
'slotted_attribute4']
然而当我运行:
slottedclass.slotted_attribute1
我收到以下错误:
>>> AttributeError Traceback (most recent call last)
<ipython-input-58-88291109fa74> in <module>()
----> 1 slotted_class.slotted_attribute1
AttributeError: slotted_attribute1
编辑:更多信息和更多困惑: 如果我不使用元类直接实现一个等价物:
class slottedclass_non_meta(object):
__slots__ = ['slotted_attribute1', 'slotted_attribute2', 'slotted_attribute3', 'slotted_attribute4']
def __init__(self, slotted_attribute1, slotted_attribute2, slotted_attribute3, slotted_attribute4):
self.slotted_attribute1, self.slotted_attribute2, self.slotted_attribute3, self.slotted_attribute4 = slotted_attribute1, slotted_attribute2, slotted_attribute3, slotted_attribute4
然后做这个对比 目录(开槽类)== 目录(slottedclass_non_meta)
>>> True
这可能只是您的 data
变量的一些错误。制作
确保它是可迭代的或字符串序列。
在我的交互式环境中尝试这个完美无缺:
In [162]: m = type("m", (), {"__slots__": ("test1",)})
In [163]: m.test1
Out[163]: <member 'test1' of 'm' objects>
In [164]: n = m()
In [165]: n.test1 = 10
In [166]: n.test1
Out[166]: 10
其他注意事项:
- 为此您不需要说您是 "using metaclasses"(尽管从技术上讲您是)- 只需说您正在通过调用
type
动态创建 classes。在阅读问题标题时,大多数人会认为您正在尝试专门化type
本身并在其中包含__slots__
。 - 在您粘贴的示例代码中,您没有用于动态创建的 class 的
__init__
方法:因此您显然无法在 [=34= 上传递名称参数] 创建并在实例上自动设置它们,就像您在显式 class. 上所做的那样
如果第二个主题是你的问题,我建议不要继承 object
(暗示但他是空的 - () - 要调用的第二个参数),创建一个具有泛型的 baseclass __init__
将 kwargs 设置为属性的方法:
class Base:
__slots__ = ()
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
slotted_class = type("slotted_class", (Base,), {"__slots__": ...})