python - 如果一个对象没有 `__dict__` ,它的类必须有一个 `__slots__` 属性吗?

标签 python python-3.x

来自 https://stackoverflow.com/a/1529099/156458

To support arbitrary attribute assignment, an object needs a __dict__: a dict associated with the object, where arbitrary attributes can be stored. Otherwise, there's nowhere to put new attributes.

An instance of object does not carry around a __dict__ -- if it did, before the horrible circular dependence problem (since __dict__, like most everything else, inherits from object;-), this would saddle every object in Python with a dict, which would mean an overhead of many bytes per object that currently doesn't have or need a dict (essentially, all objects that don't have arbitrarily assignable attributes don't have or need a dict).

...

When the class has the __slots__ special attribute (a sequence of strings), then the class statement (more precisely, the default metaclass, type) does not equip every instance of that class with a __dict__ (and therefore the ability to have arbitrary attributes), just a finite, rigid set of "slots" (basically places which can each hold one reference to some object) with the given names.

如果一个对象没有__dict__,它的类必须有一个__slots__属性吗?

例如,object 的实例没有 __dict__:

>>> object().__dict__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute '__dict__'

但它也没有__slots__:

>>> object.__slots__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'object' has no attribute '__slots__'

object 实例有任何属性吗?

有多少种可能性:

  • 一个对象有 __dict__,它的类有 __dict__ 但没有 __slots__
  • 一个对象没有__dict__,它的类有__slots__
  • 一个对象没有__dict__,它的类没有__slots__ ?

是否可以判断一个对象是否具有来自其类的 __dict__

  • 如果它的类有 __slots__,那么它没有 __dict__,对吗?

  • 如果它的类没有__slots__,我怎么知道它是否有__dict__

最佳答案

对于用户定义的类(在常规 Python 代码中使用 class 关键字定义),类将始终在类上具有 __slots____dict__ 在实例上,或两者(如果定义的插槽之一是 '__dict__',或者继承链中的用户定义类之一定义了 __slots__ 而另一个定义了不是,隐式创建 __dict__)。因此,这是用户定义类涵盖的四种可能性中的三种。

编辑:更正:从技术上讲,用户定义的类 could have neither ;该类将使用 __slots__ 定义,但在定义时间后将其删除(设置类型的机制不需要 __slots__ 在类定义完成后继续存在) .任何理智的人都不应该这样做,并且它可能会产生不良的副作用(未经测试的完整行为),但这是可能的。

对于内置类型,至少在 CPython 引用解释器中,它们不太可能有 __slots__(如果有,那将是模拟一个用户定义的类,定义它实际上任何有用的事情)。内置类型通常将其属性存储为 C 级结构上的原始 C 级值和指针,可选择使用显式创建的描述符或访问器方法,这消除了 __slots__ 的目的,这只是一个方便的用户定义类的此类结构游戏的有限用途等价物。 __dict__ 是选择加入内置类型,默认情况下不启用(尽管选择加入过程相当简单;您需要在某处放置一个 PyObject* 条目结构并在类型定义中为其提供偏移量)。

需要明确的是,__dict__ 不必出现在 中,它也会出现在它的实例 中; __slots__是类级别的,可以抑制instance上的__dict__,但对类本身是否有__dict__没有影响;用户定义的总是有__dict__,但如果您小心地适当使用__slots__,它们的实例就不会。

简而言之:

(Sane) 用户定义的类至少具有 __dict__(在实例上)或 __slots__(在类上)之一,并且可以同时具有两者。疯狂的用户定义类可能两者都没有,但只有精神错乱的开发人员才会这样做。

内置类通常两者都没有,可能提供__dict__,并且几乎从不提供__slots__,因为这对它们毫无意义。

例子:

# Class has __slots__, instances don't have __dict__
class DictLess:
    __slots__ = ()

# Instances have __dict__, class lacks __slots__
class DictOnly:
    pass

# Class has __slots__, instances have __dict__ because __slots__ declares it
class SlottedDict:
    __slots__ = '__dict__',

# Class has __slots__ without __dict__ slot, instances have it anyway from unslotted parent
class DictFromParent(DictOnly):
    __slots__ = ()

# Complete insanity: __slots__ takes effect at class definition time, but can
# be deleted later, without changing the class behavior:
class NoSlotNoDict:
    __slots__ = ()
del NoSlotNoDict.__slots__
# Instances have no __dict__, class has no __slots__ but acts like it does
# (the machinery to make it slotted isn't undone by deleting __slots__)
# Please, please don't actually do this

# Built-in type without instance __dict__ or class defined __slots__:
int().__dict__  # Raises AttributeError
int.__slots__   # Also raises AttributeError

# Built-in type that opts in to __dict__ on instances:
import functools
functools.partial(int).__dict__ # Works fine
functools.partial.__slots__ # Raises AttributeError

关于python - 如果一个对象没有 `__dict__` ,它的类必须有一个 `__slots__` 属性吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46575174/

相关文章:

Python 请求库 : use of json. 转储

python-3.x - 从字符串导入lib.reload模块?

python - 字符串比较无法识别匹配

python - 使用openCV在python中进行Canny检测

python - shell命令运行带有args的python脚本,args是一个列表

python-3.x - 通过 pip 安装 librosa 失败

python - 为什么在无服务器 python 应用程序中使用 zappa/chalice?

python - 尝试使用 Vispy 在 3d 中旋转四边形

python - 如何使用shell命令通过应用程序名称查找PID

python - 在 Python 中按属性分隔列表元素