【问题标题】:__slots__ of `property` type`property` 类型的 __slots__
【发布时间】:2016-02-04 13:03:52
【问题描述】:

那么pythonproperty类型是怎么回事呢?它没有__slots____dict__。但是property 类型的__dict__ 显示槽引用。

In [28]: p = property(lambda: 5)

In [29]: hasattr(p, '__slots__')
Out[29]: False

In [30]: hasattr(p, '__dict__')
Out[30]: False

In [31]: type(p).__dict__
Out[31]: 
<dictproxy {'__delete__': <slot wrapper '__delete__' of 'property' objects>,
 '__doc__': <member '__doc__' of 'property' objects>,
 '__get__': <slot wrapper '__get__' of 'property' objects>,
 '__getattribute__': <slot wrapper '__getattribute__' of 'property' objects>,
 '__init__': <slot wrapper '__init__' of 'property' objects>,
 '__new__': <function __new__>,
 '__set__': <slot wrapper '__set__' of 'property' objects>,
 'deleter': <method 'deleter' of 'property' objects>,
 'fdel': <member 'fdel' of 'property' objects>,
 'fget': <member 'fget' of 'property' objects>,
 'fset': <member 'fset' of 'property' objects>,
 'getter': <method 'getter' of 'property' objects>,
 'setter': <method 'setter' of 'property' objects>}>

另外我尝试从属性继承来添加额外的属性,但明显的方法搞砸了。

In [37]: property_ = type('property_', (property, ), dict(__slots__=('prop', )))

In [38]: p_ = property_(lambda: 5)
---------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-38-06c5a90565ef> in <module>()
----> 1 p_ = property_(lambda: 5)

AttributeError: 'property_' object attribute '__doc__' is read-only

如果property 没有实现__slots__ 功能,为什么我不能将属性分配给property 实例?

In [45]: p = property(lambda: 'prop')

In [46]: p.attr = 'attr'
--------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-46-71284e3de202> in <module>()
----> 1 p.attr = 'attr'

AttributeError: 'property' object has no attribute 'attr'

【问题讨论】:

  • property 在 C 中实现,其行为与在 C 中实现的许多其他类型非常相似(objectsetlist、...)。你看到的那些槽是 C 槽。

标签: python python-2.7 properties python-internals


【解决方案1】:

__slots__ 机制向 Python 类型公开了一个已用于 C 类型的特性property 上名称中带有slot 的对象并不意味着它使用__slots__ 功能。它们只是使用 C 类型特性的对象。

property 对象可以在不使用__slots__ 的情况下进行子类化:

>>> class Foo(property):
...     prop = 'bar'
...
>>> def test(self): return 'success'
...
>>> Foo(test).__get__(object())
'success'
>>> Foo(test).prop
'bar'

子类为该子类的实例添加__dict__。或者您可以通过实现descriptor protocol 轻松创建相同的功能。

【讨论】:

  • 如果它不使用__slots__ 功能,为什么我不能为现有属性分配属性?
  • @GeningD.: 因为它没有__dict__ 属性。这就是使用__slots__ 来创建没有__dict__ 的自定义Python 类的原因。 C 类型没有这个限制,类型的负载不允许属性。以object() 为例。
  • 对不起,我看错了你的答案。因此,用 C 编写的类可能不实现 __slots____dict__,而是直接从 C 中强制严格输入?
  • @GeningD.: __slots__ 是纯 Python 独有的功能;它做了两件事:删除__dict__ 插槽,并为您的属性插入专用描述符。 __dict__ 是纯 Python 实例始终获得的插槽,除非您使用 __slots__ 禁用它。 C 类型必须显式添加它;以function object definition 为例。
  • @GeningD.:这些功能都与严格类型无关。
猜你喜欢
  • 2017-05-21
  • 1970-01-01
  • 2018-02-02
  • 2021-05-07
  • 2015-06-29
  • 2015-09-12
  • 2017-11-13
  • 2022-08-17
  • 2016-07-16
相关资源
最近更新 更多