首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >元类和__slots__?

元类和__slots__?
EN

Stack Overflow用户
提问于 2012-03-11 10:23:17
回答 3查看 3.9K关注 0票数 16

因此,我正在阅读一些关于Python中的元类,以及如何使用type()的三参数更改-自我来动态创建类,然而,第三个参数通常是初始化拟创建类的__dict__变量的dict

如果我想要基于使用__slots__而不是__dict__的元类动态创建类,我该如何做呢?type()是否仍以某种方式与重写__new__()一起使用?

作为一个FYI,我知道__slots__的适当用途,在创建大量类时节省内存,而不是滥用类来执行类型安全。

设置__metaclass__并使用__dict__的普通类(新样式)的示例

代码语言:javascript
复制
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.__new__(),第四个参数(在实际使用时成为第三个参数)在Foo中创建了一个__dict__。但是,如果我想修改Meta以包括__slots__,那么我就没有字典可以传递给type()__new__()函数(据我所知,我还没有测试过这些功能,只是仔细考虑并试图找到某种用例场景)。

编辑:--一个快速但未经测试的猜测,是将要放入__slots__变量中的值块,并将其传递给type.__new__()。然后将一个__init__()添加到Meta中,以填充dict中的__slots__变量。虽然,我不确定这个dict将如何到达__init__(),因为__slots__的声明阻止创建__dict__,除非在__slots__中定义了__dict__ .

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-11 10:39:12

不能创建具有非空__slots__属性的类型。您可以做的是在新类的dict中插入一个__slots__属性,如下所示:

代码语言:javascript
复制
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有了时隙属性:

代码语言:javascript
复制
foo = Foo() 
foo.y = 1

抛出

代码语言:javascript
复制
 AttributeError: 'Foo' object has no attribute 'y'
票数 25
EN

Stack Overflow用户

发布于 2012-03-11 10:38:38

元类示例中的dctn是类字典,而不是实例字典。__slots__替换实例字典。如果创建两个示例:

代码语言:javascript
复制
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']

然后:

代码语言:javascript
复制
>>> f1 = Foo1()
>>> f2 = Foo2()
>>> f1.__dict__ is Foo1.__dict__
False
>>> f2.__dict__
Traceback (most recent call last):
    ...
AttributeError: 'Foo2' object has no attribute '__dict__'
票数 6
EN

Stack Overflow用户

发布于 2015-12-23 10:05:47

更多关于在元类中定义的插槽的信息。

如果type的子类定义了非空__slots__,Python会因为某些复杂的实现相关的东西抛出一个TypeError

代码语言:javascript
复制
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'

另一方面,空__slots__不会产生任何错误,但是seam不会产生任何影响。

代码语言:javascript
复制
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__'
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9654133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档