Python 元类和插槽?
因此,我正在阅读一些关于Python中元类的内容,以及如何使用Python 元类和插槽?,python,Python,因此,我正在阅读一些关于Python中元类的内容,以及如何使用type()的三个参数alterego动态创建类。但是,第三个参数通常是初始化要创建的类的\uuu dict\uu变量的dict 如果我想基于使用\uuuuu slots\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?type()是否仍以某种方式与重写\uuuuuuuuuuuuuu()一起使用 仅供参
type()
的三个参数alterego动态创建类。但是,第三个参数通常是初始化要创建的类的\uuu dict\uu
变量的dict
如果我想基于使用\uuuuu slots\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?type()
是否仍以某种方式与重写\uuuuuuuuuuuuuu()
一起使用
仅供参考,我知道在创建大量类时,如何正确使用\uuuuu slots\uuuu
,以节省内存,而不是滥用它来强制执行某种类型的安全性
设置\uuuuuuu元类并使用\uuuuu dict\uuuuuuuu
的普通(新型)类示例:
class Meta(type):
def __new__(cls, name, bases, dctn):
# Do something unique ...
return type.__new__(cls, name, bases, dctn)
class Foo(object):
__metaclass__ = Meta
def __init__(self):
pass
在上面的中,将调用type.\uuuuuu new\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。但是,如果我想修改Meta
以包含\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu slots\uuuuuuuuuuuu
,那么我就没有字典可以传递给type()
的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
编辑:一个快速但未经测试的猜测是将要放入\uuuuuuuuuuuuuuuuuuuuuuuu
变量的值记录下来,并将其传递给类型。\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。然后将一个\uuuu init\uuuuuuuuuuuuuu()
添加到Meta
,该Meta将填充来自dict的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu>变量。尽管我不确定dict将如何到达\uuuuuuuuuuuuuuuuuuuu,因为\uuuuuuuuuuuuuuuuuuuuu
的声明会阻止创建\uuuuuuuuuuuuuuuuuuuuuuuuu
,除非中定义了\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
。在元类示例中,dctn<代码>替换实例字典。如果创建两个示例:
class Meta(type):
def __new__(cls, name, bases, dctn):
return type.__new__(cls, name, bases, dctn)
class Foo1(object):
__metaclass__ = Meta
class Foo2(object):
__metaclass__ = Meta
__slots__ = ['a', 'b']
然后:
无法创建具有非空_____;属性的类型。您可以做的是在新类的dict中插入一个_uuslots _uuu属性,如下所示:
class Meta(type):
def __new__(cls, name, bases, dctn):
dctn['__slots__'] = ( 'x', )
return type.__new__(cls, name, bases, dctn)
class Foo(object):
__metaclass__ = Meta
def __init__(self):
pass
现在,Foo具有时隙属性:
foo = Foo()
foo.y = 1
投掷
AttributeError: 'Foo' object has no attribute 'y'
更多关于元类中定义的插槽的信息。
如果type
的子类定义了非空的\uuuuuuuuuuuuuuuuuuuuu
,Python会抛出TypeError
好的,我还在这里学习Python的诀窍,并开始学习Python的咒语“一切都是对象”(类似于UNIX的“一切都是文件”)。不可能在元类中定义\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
并将其传播到从元类创建的类中吗?或者这是基类变得更有用的地方?或者,我想结合这两个概念吗?好问题。当然,只需添加到dctn
,就可以在元类中定义\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。然而,从基类生成子类通常是更好的方法。一般来说,如果你不确定你是否需要一个元类,那么你就不需要了。这就是为什么我要更多地学习元类,这样我才能确定我是否真的需要它们。请注意,我来自.NET的背景,在那里我必须处理泛型、接口和单一继承,并且从未接受过OOP的正式培训(只有一些关于旧C的课程)。试图理解Python的独特差异有时被证明是非常有趣的。就像一个人找到了一种方法,把一个孢子转化成一个投石机,在晚餐时把布鲁塞尔芽放在桌子上。这看起来很有趣。我会在几分钟后试试。我从来没有试过这个,但我认为这从技术上回答了这个问题。总有一天我会弄明白的。刚刚登录到SO in ages;这个答案最终奏效了。谢谢
AttributeError: 'Foo' object has no attribute 'y'
In [1]:
class Meta(type):
__slots__ = ('x')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-38-1b16edef8eca> in <module>()
----> 1 class Meta(type):
2 __slots__ = ('x')
TypeError: nonempty __slots__ not supported for subtype of 'type'
In [2]:
class Meta(type):
__slots__ = ()
class Foo(metaclass=Meta):
pass
type(Foo)
Out [2]:
__main__.Meta
In [3]:
Foo.y = 42
Foo.y
Out [3]:
42
In [4]:
Foo.__dict__
Out [4]:
mappingproxy({'y': 42, '__dict__': <attribute '__dict__' of 'Foo' objects>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__module__': '__main__'})
In [5]:
foo = Meta('foo', (), {})
type(foo).__slots__
Out [5]:
()
In [6]:
foo.x = 42
foo.x
Out [6]:
42
In [7]:
foo.__dict__
Out [7]:
mappingproxy({'__dict__': <attribute '__dict__' of 'foo' objects>, 'x': 42, '__module__': '__main__', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'foo' objects>})
In [8]:
# Testing on non-metaclasses. Just in case.
class Bar:
__slots__ = ()
b = Bar()
b.__dict__
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-54-843730c66f3f> in <module>()
3
4 b = Bar()
----> 5 b.__dict__
AttributeError: 'Bar' object has no attribute '__dict__'