如何创建没有 __dict__ 的类对象

5 投票
2 回答
2276 浏览
提问于 2025-04-18 16:40
class B(type):
    __slots__ = ()

class A(metaclass=B):
    pass

A.test = "test"

"A" 是元类 "B" 的一个实例,而 "B" 定义了 __slots__ - 那为什么在类 A 中还有 __dict__ 呢?我该如何创建一个没有 __dict__ 的类对象呢?

2 个回答

2

__slots__ 这个东西并不能阻止你给一个类设置属性,如果你想要做到这一点,你需要重写 __setattr__ 方法。你可以像下面这样做:

class B(type):
    def __new__(cls, clsname, bases, dct):
        dct['__slots__']  = ('x',)
        return type.__new__(cls, clsname, bases, dct)
    def __setattr__(cls, attr, val):
        if attr not in cls.__slots__:
            raise AttributeError('Can\'t set {!r}'.format(attr))
        else:
            type.__setattr__(cls, attr, val)

class A(metaclass=B):
    pass

示例:

>>> A.x = 1
>>> A.y = 2
Traceback (most recent call last):
  File "<pyshell#2>", line 1, in <module>
    A.y = 2
  File "C:\Python27\so.py", line 7, in __setattr__
    raise AttributeError('Can\'t set {!r}'.format(attr))
AttributeError: Can't set 'y'
5

你不能这样做;类总是会有一个__dict__

你只能在上使用__slots__来创建没有__dict__的实例,而不能在元类上使用。通常你只会创建几个类,所以在元类上支持__slots__其实意义不大。

不要用__slots__来阻止属性被设置。要做到这一点,应该使用__setattr__

class NoAttributesClassMeta(type):
    def __setattr__(cls, name, value):
        if name not in cls.__dict__:
            raise AttributeError("Cannot set attributes")
        type.__setattr__(cls, name, value)

撰写回答