为什么python描述符中的__get__方法接受所有者类作为它的第三个参数?你能给出一个使用它的例子吗?
第一个参数(self)是不言而喻的,第二个(instances)在通常显示的描述符模式的上下文中是有意义的(如下所示),但我从未真正看到owner使用过的第三个().有人可以解释用例是什么吗?
仅仅通过参考和促进答案,这是我见过的描述符的典型用法:
class Container(object):
class ExampleDescriptor(object):
def __get__(self, instance, owner):
return instance._name
def __set__(self, instance, value):
instance._name = value
managed_attr = ExampleDescriptor()
Run Code Online (Sandbox Code Playgroud)
鉴于instance.__class__可用,我能想到的是显式传递类与直接从类而不是实例(ex Container.managed_attr)访问描述符有关.即便如此,我还不清楚__get__在这种情况下会做些什么.
如此处所述:
https://docs.python.org/3/reference/datamodel.html#object.__get__
传递给 __get__ 方法的两个参数('self' 除外)分别是对象和访问属性的类。第二个论点不是多余的吗?此外,当“类”也是对象时,为什么需要区分对象和类访问?
所以,在我看来,有两种可能性:
在我看来,如果只使用一个参数(例如instance)可以实现相同的功能,该参数将始终保存原始对象,无论它是否是“类”。如果确实需要该信息,则可以使用isinstance(instance, type).
那么,为什么需要两个参数呢?
我正在尝试在Python中使用Javascript等效项:
a.new_func = function(arg1, arg2) {
var diff = arg1 - arg2;
return diff * diff;
}
Run Code Online (Sandbox Code Playgroud)
现在,我这样做的方法是首先定义方法,然后分配它,但我的问题是Python是否允许速记在同一行中进行赋值和定义部分.像这样的东西:
a.new_func = def new_func(arg1, arg2):
diff = arg1 - arg2
return diff * diff
Run Code Online (Sandbox Code Playgroud)
而不是这个:
def new_func(arg1, arg2):
diff = arg1 - arg2
return diff * diff
a.new_func = new_func
Run Code Online (Sandbox Code Playgroud)
我意识到差异不大,但我仍然有兴趣知道它是否可能.
来自 Python数据模型文档:
object.__get__(self, instance, owner=None)调用以获取所有者类的属性(类属性访问)或该类的实例的属性(实例属性访问)。可选
owner参数是所有者类,而instance属性是通过其访问的实例,或者None是通过owner.此方法应返回计算出的属性值或引发
AttributeError异常。PEP 252 指定可以
__get__()使用一个或两个参数调用。Python 自己的内置描述符支持这个规范;但是,某些第三方工具可能具有需要两个参数的描述符。__getattribute__()无论是否需要,Python 自己的实现总是传入这两个参数。
object.__set__(self, instance, value)调用以将
instance所有者类的实例上的属性设置为新值 value。请注意,将描述符的种类添加
__set__()或__delete__()更改为“数据描述符”。有关更多详细信息,请参阅调用描述符。
object.__delete__(self, instance)调用以删除
instance所有者类的实例上的属性。
为什么__get__需要一段owner时间__set__而__delete__没有?
这是否意味着当描述符同时提供__get__和时__set__,
我的问题实际上是这个问题的一部分。
默认情况下,插槽是可写的:
>>> class A: __slots__ = ('x',)
...
>>> list(vars(A))
['__module__', '__slots__', 'x', '__doc__']
>>> vars(A)['x']
<member 'x' of 'A' objects>
>>> a = A()
>>> a.x = 'foo'
>>> del a.x
Run Code Online (Sandbox Code Playgroud)
如何创建只读插槽,像插槽'__thisclass__','__self__'和'__self_class__'之类的super?
>>> list(vars(super))
['__repr__', '__getattribute__', '__get__', '__init__', '__new__',
'__thisclass__', '__self__', '__self_class__', '__doc__']
>>> vars(super)['__thisclass__']
<member '__thisclass__' of 'super' objects>
>>> s = super(int, 123)
>>> s.__thisclass__ = float
Traceback (most recent call last):
File "<stdin>", line …Run Code Online (Sandbox Code Playgroud)