`vars(self)` 的响应缺少属性
response of `vars(self)` is missing attributes
我定义了一个class,需要把它的大部分属性交给函数处理。所以我想与其制造一团糟并给它们全部命名,不如 processSomething(vars(self))
并交出一本包含所有属性和值的漂亮字典。
但是我发现几乎所有的属性都缺失了。
我已停止调试器中的代码并运行进行了一些测试:
>>> vars(self).keys()
dict_keys(['date_expire', 'tokenUrl', 'settings', 'requestSession', 'ttlDays'])
这些是 5 个。虽然我期望有大约 20 个属性,但根据我的 class 此处的 __slots__
定义:
__slots__ = (
'token', # the invitation-token to load the username with
'request', # the http-request which is currently being serviced
'inhibit',
#... many lines deleted
'templateObj', # an instance of myMail.template.Template
'emailBody', # what will be sent via SMTP
'warningsAr', # messages for the client
)
我可以在调试器中看到属性 window 并且可以直接访问它们。我已阅读 manual of vars(),但找不到任何开关。有趣的是,dir(self)
显示所有属性名称,但没有值。所以我不能使用它。但我认为 vars 和 dir 应该显示相同?
我想我会构建一个解决方法,但我真的很想了解这里发生了什么。你能帮忙吗?
vars()
return您是实例的 __dict__
名称space。但是 __slots__
属性 未存储在 __dict__
名称中 space。这就是他们的全部观点。
相反,Python 在实例内存结构中为每个值创建专用指针槽,并在 class 对象上使用 描述符 来检索这些值.所以 inst.attr
被翻译成 type(inst).attr.__get__(inst)
到 return 这个值。
The __slots__
declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because __dict__
is not created for each instance.
[...]
__slots__
are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name.
请注意,拥有 __dict__
无论如何 通常是您忘记为子 class 使用 __slots__
属性的标志,或者您继承自未使用 __slots__
本身的基础 Python class。正确使用 __slots__
应该会导致没有 __dict__
namespace 的实例;他们的目标是通过避免字典所需的稀疏散列 table 来减少内存(这会浪费 space)。
再次来自文档:
- When inheriting from a class without
__slots__
, the __dict__
attribute of that class will always be accessible, so a __slots__
definition in the subclass is meaningless.
[...]
- The action of a
__slots__
declaration is limited to the class where it is defined. As a result, subclasses will have a __dict__
unless they also define __slots__
(which must only contain names of any additional slots).
如果您想列出所有可用的实例字段,您必须包括 class 中的 __slots__
枚举,而不仅仅是查看 vars()
:
from itertools import chain
def slots_for_instance(inst):
def _slots_for_class(c):
slots = getattr(c, '__slots__', ())
if isinstance(slots, str):
# __slots__ can be a string naming a single attribute
slots = (slots,)
return set(chain.from_iterable(
getattr(_slots_for_class(c) for c in type(inst).__mro__))
我定义了一个class,需要把它的大部分属性交给函数处理。所以我想与其制造一团糟并给它们全部命名,不如 processSomething(vars(self))
并交出一本包含所有属性和值的漂亮字典。
但是我发现几乎所有的属性都缺失了。
我已停止调试器中的代码并运行进行了一些测试:
>>> vars(self).keys()
dict_keys(['date_expire', 'tokenUrl', 'settings', 'requestSession', 'ttlDays'])
这些是 5 个。虽然我期望有大约 20 个属性,但根据我的 class 此处的 __slots__
定义:
__slots__ = (
'token', # the invitation-token to load the username with
'request', # the http-request which is currently being serviced
'inhibit',
#... many lines deleted
'templateObj', # an instance of myMail.template.Template
'emailBody', # what will be sent via SMTP
'warningsAr', # messages for the client
)
我可以在调试器中看到属性 window 并且可以直接访问它们。我已阅读 manual of vars(),但找不到任何开关。有趣的是,dir(self)
显示所有属性名称,但没有值。所以我不能使用它。但我认为 vars 和 dir 应该显示相同?
我想我会构建一个解决方法,但我真的很想了解这里发生了什么。你能帮忙吗?
vars()
return您是实例的 __dict__
名称space。但是 __slots__
属性 未存储在 __dict__
名称中 space。这就是他们的全部观点。
相反,Python 在实例内存结构中为每个值创建专用指针槽,并在 class 对象上使用 描述符 来检索这些值.所以 inst.attr
被翻译成 type(inst).attr.__get__(inst)
到 return 这个值。
The
__slots__
declaration takes a sequence of instance variables and reserves just enough space in each instance to hold a value for each variable. Space is saved because__dict__
is not created for each instance.[...]
__slots__
are implemented at the class level by creating descriptors (Implementing Descriptors) for each variable name.
请注意,拥有 __dict__
无论如何 通常是您忘记为子 class 使用 __slots__
属性的标志,或者您继承自未使用 __slots__
本身的基础 Python class。正确使用 __slots__
应该会导致没有 __dict__
namespace 的实例;他们的目标是通过避免字典所需的稀疏散列 table 来减少内存(这会浪费 space)。
再次来自文档:
- When inheriting from a class without
__slots__
, the__dict__
attribute of that class will always be accessible, so a__slots__
definition in the subclass is meaningless.[...]
- The action of a
__slots__
declaration is limited to the class where it is defined. As a result, subclasses will have a__dict__
unless they also define__slots__
(which must only contain names of any additional slots).
如果您想列出所有可用的实例字段,您必须包括 class 中的 __slots__
枚举,而不仅仅是查看 vars()
:
from itertools import chain
def slots_for_instance(inst):
def _slots_for_class(c):
slots = getattr(c, '__slots__', ())
if isinstance(slots, str):
# __slots__ can be a string naming a single attribute
slots = (slots,)
return set(chain.from_iterable(
getattr(_slots_for_class(c) for c in type(inst).__mro__))