为什么这个 class 描述符 __get__ 方法 return 自我?
Why does this class descriptor __get__ method return self?
我正在研究 O Reilley Python 食谱,我对以下代码有疑问:
class Typed:
def __init__(self, name, expected_type):
self.name = name
self.expected_type = expected_type
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError('Expected ' + str(self.expected_type))
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]
# Class decorator that applies it to selected attributes
def typeassert(**kwargs):
def decorate(cls):
for name, expected_type in kwargs.items():
# Attach a Typed descriptor to the class
setattr(cls, name, Typed(name, expected_type))
return cls
return decorate
# Example use
@typeassert(name=str, shares=int, price=float)
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
if __name__ == '__main__':
s = Stock('ACME', 100, 490.1)
print(s.name, s.shares, s.price)
s.shares = 50
try:
s.shares = 'a lot'
except TypeError as e:
print(e)
我对这部分感到困惑:
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
如果未设置实例(即 None),那么它会显示 return 'self',因为 self 代表 class 描述符 returned?
then it says return 'self', given that self represents the class
descriptor what exactly is returned?
您刚刚回答了您自己的问题:它 returns 描述符对象本身。
因此,当在 class 上访问描述符时,instance
将是 None
,在这种情况下它只是 returns 描述符。考虑 Descriptor HOWTO 中 Python 中重新实现的 property
示例:
In [5]: class Property(object):
...: "Emulate PyProperty_Type() in Objects/descrobject.c"
...:
...: def __init__(self, fget=None, fset=None, fdel=None, doc=None):
...: self.fget = fget
...: self.fset = fset
...: self.fdel = fdel
...: if doc is None and fget is not None:
...: doc = fget.__doc__
...: self.__doc__ = doc
...:
...: def __get__(self, obj, objtype=None):
...: if obj is None:
...: print('obj is None in Property.__get__')
...: return self
...: if self.fget is None:
...: raise AttributeError("unreadable attribute")
...: return self.fget(obj)
...:
...: def __set__(self, obj, value):
...: if self.fset is None:
...: raise AttributeError("can't set attribute")
...: self.fset(obj, value)
...:
...: def __delete__(self, obj):
...: if self.fdel is None:
...: raise AttributeError("can't delete attribute")
...: self.fdel(obj)
...:
...: def getter(self, fget):
...: return type(self)(fget, self.fset, self.fdel, self.__doc__)
...:
...: def setter(self, fset):
...: return type(self)(self.fget, fset, self.fdel, self.__doc__)
...:
...: def deleter(self, fdel):
...: return type(self)(self.fget, self.fset, fdel, self.__doc__)
...:
然后:
In [6]: class Foo:
...: @Property
...: def bar(self):
...: return 42
...:
In [7]: Foo.bar
obj is None in Property.__get__
Out[7]: <__main__.Property at 0x1044d02b0>
In [8]: Foo().bar
Out[8]: 42
是的,它 returns 描述符实例。
__get__
的第二个参数(self
之后的第一个参数)是查找描述符的实例 - 或者 None
如果它是在 class.
因此,在给定的情况下,它是 returns 描述符,以防您在 class 上查找描述符。
只是为了说明:
class Descriptor:
def __get__(self, instance, owner):
if instance is None:
return self
return 10
class Test:
test = Descriptor()
>>> Test.test
<__main__.Descriptor at 0x2769b7d44c8>
>>> Test.__dict__['test']
<__main__.Descriptor at 0x2769b7d44c8>
现在,如果它不使用 return self
,它将看起来像这样:
class Descriptor:
def __get__(self, instance, owner):
return 10
class Test:
test = Descriptor()
>>> Test.test
10
>>> Test.__dict__['test']
<__main__.Descriptor at 0x2769b7de208>
这个 return self
经常这样做的原因是因为它允许获取描述符实例而不必在 __dict__
中搜索(可能在所有 superclasses 中)。在大多数情况下,当在 class 上查找 属性 时,做任何事情都是没有意义的,因此返回实例是个好主意。
这也是内置 property
所做的(以及函数描述符):
class A:
@property
def testproperty(self):
return 10
def testmethod(self):
return 10
>>> A.testproperty
<property at 0x2769b7db9a8>
>>> A.testproperty.__get__(None, A)
<property at 0x2769b7db9a8>
>>> A.testmethod
<function __main__.A.testmethod(self)>
>>> A.testmethod.__get__(None, A)
<function __main__.A.testmethod(self)>
在 class(例如内置 staticmethod
和 classmethod
描述符)上查找属性时应该发生一些有意义的事情的情况下,那当然是different and self
不应该返回那里!
我正在研究 O Reilley Python 食谱,我对以下代码有疑问:
class Typed:
def __init__(self, name, expected_type):
self.name = name
self.expected_type = expected_type
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
if not isinstance(value, self.expected_type):
raise TypeError('Expected ' + str(self.expected_type))
instance.__dict__[self.name] = value
def __delete__(self, instance):
del instance.__dict__[self.name]
# Class decorator that applies it to selected attributes
def typeassert(**kwargs):
def decorate(cls):
for name, expected_type in kwargs.items():
# Attach a Typed descriptor to the class
setattr(cls, name, Typed(name, expected_type))
return cls
return decorate
# Example use
@typeassert(name=str, shares=int, price=float)
class Stock:
def __init__(self, name, shares, price):
self.name = name
self.shares = shares
self.price = price
if __name__ == '__main__':
s = Stock('ACME', 100, 490.1)
print(s.name, s.shares, s.price)
s.shares = 50
try:
s.shares = 'a lot'
except TypeError as e:
print(e)
我对这部分感到困惑:
def __get__(self, instance, cls):
if instance is None:
return self
else:
return instance.__dict__[self.name]
如果未设置实例(即 None),那么它会显示 return 'self',因为 self 代表 class 描述符 returned?
then it says return 'self', given that self represents the class descriptor what exactly is returned?
您刚刚回答了您自己的问题:它 returns 描述符对象本身。
因此,当在 class 上访问描述符时,instance
将是 None
,在这种情况下它只是 returns 描述符。考虑 Descriptor HOWTO 中 Python 中重新实现的 property
示例:
In [5]: class Property(object):
...: "Emulate PyProperty_Type() in Objects/descrobject.c"
...:
...: def __init__(self, fget=None, fset=None, fdel=None, doc=None):
...: self.fget = fget
...: self.fset = fset
...: self.fdel = fdel
...: if doc is None and fget is not None:
...: doc = fget.__doc__
...: self.__doc__ = doc
...:
...: def __get__(self, obj, objtype=None):
...: if obj is None:
...: print('obj is None in Property.__get__')
...: return self
...: if self.fget is None:
...: raise AttributeError("unreadable attribute")
...: return self.fget(obj)
...:
...: def __set__(self, obj, value):
...: if self.fset is None:
...: raise AttributeError("can't set attribute")
...: self.fset(obj, value)
...:
...: def __delete__(self, obj):
...: if self.fdel is None:
...: raise AttributeError("can't delete attribute")
...: self.fdel(obj)
...:
...: def getter(self, fget):
...: return type(self)(fget, self.fset, self.fdel, self.__doc__)
...:
...: def setter(self, fset):
...: return type(self)(self.fget, fset, self.fdel, self.__doc__)
...:
...: def deleter(self, fdel):
...: return type(self)(self.fget, self.fset, fdel, self.__doc__)
...:
然后:
In [6]: class Foo:
...: @Property
...: def bar(self):
...: return 42
...:
In [7]: Foo.bar
obj is None in Property.__get__
Out[7]: <__main__.Property at 0x1044d02b0>
In [8]: Foo().bar
Out[8]: 42
是的,它 returns 描述符实例。
__get__
的第二个参数(self
之后的第一个参数)是查找描述符的实例 - 或者 None
如果它是在 class.
因此,在给定的情况下,它是 returns 描述符,以防您在 class 上查找描述符。
只是为了说明:
class Descriptor:
def __get__(self, instance, owner):
if instance is None:
return self
return 10
class Test:
test = Descriptor()
>>> Test.test
<__main__.Descriptor at 0x2769b7d44c8>
>>> Test.__dict__['test']
<__main__.Descriptor at 0x2769b7d44c8>
现在,如果它不使用 return self
,它将看起来像这样:
class Descriptor:
def __get__(self, instance, owner):
return 10
class Test:
test = Descriptor()
>>> Test.test
10
>>> Test.__dict__['test']
<__main__.Descriptor at 0x2769b7de208>
这个 return self
经常这样做的原因是因为它允许获取描述符实例而不必在 __dict__
中搜索(可能在所有 superclasses 中)。在大多数情况下,当在 class 上查找 属性 时,做任何事情都是没有意义的,因此返回实例是个好主意。
这也是内置 property
所做的(以及函数描述符):
class A:
@property
def testproperty(self):
return 10
def testmethod(self):
return 10
>>> A.testproperty
<property at 0x2769b7db9a8>
>>> A.testproperty.__get__(None, A)
<property at 0x2769b7db9a8>
>>> A.testmethod
<function __main__.A.testmethod(self)>
>>> A.testmethod.__get__(None, A)
<function __main__.A.testmethod(self)>
在 class(例如内置 staticmethod
和 classmethod
描述符)上查找属性时应该发生一些有意义的事情的情况下,那当然是different and self
不应该返回那里!