简体   繁体   English

Python __slots__元类问题

[英]Python __slots__ metaclass issue

I'm currently implementing slotted metaclasses using type() : 我目前正在使用type()实现开槽元类:

type(i, (), {'__slots__': tuple(data)

I would of course ideally keep with slots as I have a usecase that would benefit from their smaller memory footprint and improved access speed. 当然,理想情况下,我会保留插槽,因为我有一个用例,可以从其较小的内存占用量和提高的访问速度中受益。

when I do: 当我做:

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']

however when I run: 但是当我运行时:

slottedclass.slotted_attribute1

I get the following error: 我收到以下错误:

    >>> AttributeError                            Traceback (most recent call last)
<ipython-input-58-88291109fa74> in <module>()
----> 1 slotted_class.slotted_attribute1

AttributeError: slotted_attribute1

EDIT: For further information and even more confusion: If I implement an equivalent directly without the use of metaclasses: 编辑:有关更多信息和更多困惑:如果我直接实现等效项而不使用元类:

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

Then make this comparison dir(slottedclass) == dir(slottedclass_non_meta) 然后进行此比较dir(slottedclass)== dir(slottedclass_non_meta)

>>> True

It is probably just some error on your data variable. 这可能只是您的data变量出现了一些错误。 Make sure it is an iterable or sequence of strings. 确保它是可迭代的或字符串序列。

Trying this on my interactive environment worked flawlessly: 在我的交互式环境中尝试这一点是完美的:

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

Other considerations there: 那里的其他注意事项:

  • You don't need to talk you are "using metaclasses" for this (though, technically you are) - just say you are creating classes dynamically by calling type . 您无需为此而说自己在“使用元类”(尽管从技术上讲,您是在使用)-只需说您正在通过调用type动态创建类。 On reading the question title most people will think you are trying to specialize type itself and include __slots__ in it. 在阅读问题标题时,大多数人会认为您正在尝试对type本身进行专门化处理,并在其中包含__slots__
  • On the example code you pasted, you have no __init__ method fo your dynamically created classes: so you obviusly won't be able to pass the name parameters on class creation and have them set automatically on the instance, as you do on your explicit class. 在您粘贴的示例代码上,动态创建的类没有__init__方法:因此,您显然将无法像在显式类上那样在类创建时传递名称参数并将其自动设置在实例上。

If the second topic is your problem, I recomend instead of inheriting of object (implied but he empty - () - second parameter to call), create a baseclass with a generic __init__ method to setup the kwargs as attributes: 如果第二个问题是您的问题,我建议您而不是继承object (暗示,但他为空-()-要调用的第二个参数),创建一个具有通用__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__": ...})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM