gpt4 book ai didi

python - 描述符作为python中的实例属性

转载 作者:IT老高 更新时间:2023-10-28 20:40:32 26 4
gpt4 key购买 nike

问题:

Why can't descriptors be instance attributes?

它是 answered那:

descriptor objects needs to live in the class, not in the instance

因为这就是 __getattribute__ 的实现方式。

一个简单的例子。考虑一个描述符:

class Prop(object):

def __get__(self, obj, objtype=None):
if obj is None:
return self
return obj._value * obj._multiplier

def __set__(self, obj, value):
if obj is None:
return self
obj._value = value

class Obj(object):

val = Prop()

def __init__(self):
self._value = 1
self._multiplier = 0

考虑每个 obj 有多个 Prop 的情况:我需要使用唯一的名称来标识值和乘数(例如 here 。拥有每个实例描述符对象将允许存储 _multiplier(和 _value)在描述符本身中,简化了一些事情。

要实现每个实例的描述符属性,您需要:

  1. 为每个实例创建一个类 See here
  2. 覆盖 __getattribute__ See here

我知道之前有人提出过类似的问题,但我没有找到真正的解释:

  1. 为什么 Python 是这样设计的?
  2. 存储描述符需要但每个实例的信息的建议方法是什么?

最佳答案

这个确切的问题是 raised on Python-list今年早些时候。我只是引用 Ian G. Kelly's response :

The behavior is by design. First, keeping object behavior in the class definition simplifies the implementation and also makes instance checks more meaningful. To borrow your Register example, if the "M" descriptor is defined by some instances rather than by the class, then knowing that the object "reg" is an instance of Register does not tell me anything about whether "reg.M" is a valid attribute or an error. As a result, I'll need to guard virtually every access of "reg.M" with a try-except construct just in case "reg" is the wrong kind of register.

Second, the separation of class from instance also helps you keep object behavior separate from object data. Consider the following class:

class ObjectHolder(object):
def __init__(self, obj):
self.obj = obj

Don't worry about what this class might be useful for. Just know that it's meant to hold and provide unrestricted access to arbitrary Python objects:

>>> holder = ObjectHolder(42)
>>> print(holder.obj) 42
>>> holder.obj = range(5)
>>> print(holder.obj) [0, 1, 2, 3, 4]

Since the class is meant to hold arbitrary objects, it's even valid that somebody might want to store a descriptor object there:

>>> holder.obj = property(lambda x: x.foo)
>>> print(holder.obj) <property object at 0x02415AE0>

Now suppose that Python invoked the descriptor protocol for descriptors stored in instance attributes:

>>> holder = ObjectHolder(None)
>>> holder.obj = property(lambda x: x.foo)
>>> print(holder.obj)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'ObjectHolder' object has no attribute 'foo'

In this case, the ObjectHolder would fail to simply hold the property object as data. The mere act of assigning the property object, a descriptor, to an instance attribute would change the behavior of the ObjectHolder. Instead of treating "holder.obj" as a simple data attribute, it would start invoking the descriptor protocol on accesses to "holder.obj" and ultimately redirect them to the non-existent and meaningless "holder.foo" attribute, which is certainly not what the author of the class intended.

如果您希望能够支持一个描述符的多个实例,只需让该描述符的构造函数接受一个名称参数(前缀),并在添加的属性前面加上该名称。您甚至可以在类实例中创建一个命名空间对象(字典)来保存所有新的属性实例。

关于python - 描述符作为python中的实例属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12599972/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com