请问python描述符property中的self.fget(instance)怎么理解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了请问python描述符property中的self.fget(instance)怎么理解相关的知识,希望对你有一定的参考价值。
class Myproperty:
def __init__(self,fget=None,fset=None,fdel=None):
self.fget=fget
self.fset=fset
self.fdel=fdel
def __get__(self,instance,owner):
return self.fget(instance)
self.fget是属性,为什么后面会能加括号,我无法理解
==================看这下面=================================
class C:
def __init__(self):
self._x = None
def getX(self):
return self._x
def setX(self, value):
self._x = value
def delX(self):
del self._x
x = MyProperty(getX, setX, delX)
执行上面的语句后self.fget就等于类C里的getX
self.fget(instance)等价于调用C里的getX(instance)方法
===========我是新手刚看到这如有兴趣可共同学习================ 参考技术A 说明fget是一个方法嘛追问
没有定义fget()方法,为什么能用,还是fget()是python内置本来就有的函数?
追答是构造函数的一个参数,你看怎么调用的嘛
Python的特性(Property)和描述符
特性(Property)
特性是对类的一个特定属性进行拦截,在操作这个属性时,执行特定的函数,对属性的操作进行拦截。
特性的实现
特性使用property类来实现,也可以使用property装饰器实现,二者本质是一样的。
property类的__init__函数接收4个参数,来实现属性的获取、赋值、删除及文档。
def __init__(self, fget=None, fset=None, fdel=None, doc=None): # known special case of property.__init__ """ property(fget=None, fset=None, fdel=None, doc=None) -> property attribute fget is a function to be used for getting an attribute value, and likewise fset is a function for setting, and fdel a function for del‘ing, an attribute. Typical use is to define a managed attribute x: class C(object): def getx(self): return self._x def setx(self, value): self._x = value def delx(self): del self._x x = property(getx, setx, delx, "I‘m the ‘x‘ property.") Decorators make defining new properties or modifying existing ones easy: class C(object): @property def x(self): "I am the ‘x‘ property." return self._x @x.setter def x(self, value): self._x = value @x.deleter def x(self): del self._x # (copied from class doc) """ pass
从代码上看,4个参数都不是必须的,如果没有传入对应的操作函数,则取默认值None,则对应的操作不受支持,试图调用默认值None时,会引发异常。
测试代码:
class Man(object): def __init__(self, age): self._age = age @property def age(self): return self._age @age.getter def age(self): return self._age if __name__ == ‘__main__‘: tom = Man(22) print(tom.age) tom.age = 23 print(tom.age)
因为缺少setter的函数方法,所以试图给age赋值时,会引发异常。
AttributeError: can‘t set attribute
age()方法上增加@property装饰器,实际上等同于age = property(),将age赋值为property的实例。
经过测试,把
@property def age(self): pass
修改为
age = property()
不影响代码的执行,所以@age.setter装饰器就很好理解了,因为age是property类的实例,property类有setter的方法,age继承了property类的setter方法,所以可以使用@age.setter装饰器。其他的setter、getter、deleter也是同理。
特性的继承
类的实例和子类都会继承类的特性,测试代码:
class Person(object):
def __init__(self, age): self._age = age @property def age(self): return self._age @age.setter def age(self, value): self._age = value * 2 @age.getter def age(self): return self._age class Man(Person): pass if __name__ == ‘__main__‘: tom = Man(22) print(tom.age) tom.age = 23 print(tom.age)
在age的setter方法中,将age的值乘以2,从运行结果上看,子类及其实例都是继承property的
22 46
描述符
任何带有如下方法的类都可以作为描述符
def __get__(self, instance, owner): ... def __set__(self, instance, value): ... def __delete__(self, instance): ....
__get__方法接收三个参数:self为描述符实例自身; instance指访问属性所属的实例,当访问的属性为类属性时,instance为None;owner指描述符实例附加到的类。
测试代码:
class Descriptor: def __init__(self): pass def __get__(self, instance, owner): print(self, instance, owner) def __set__(self, instance, value): print(self, instance, value) def __delete__(self, instance): print(self, instance) class ClassA(object): a = Descriptor() if __name__ == ‘__main__‘: ClassA.a x = ClassA() x.a
从运行结果可以看出,当访问类属性时,instance为None;当访问实例属性时,instance为属性所属的的实例。
instance属性为None时,描述符对象会直接访问所附加到的类的类属性。当instance属性不为None时,描述符会直接访问实例属性。
<__main__.Descriptor object at 0x1081413c8> None <class ‘__main__.ClassA‘> <__main__.Descriptor object at 0x1081413c8> <__main__.ClassA object at 0x108141358> <class ‘__main__.ClassA‘>
__set__方法的第三个参数value为需要赋值的属性,__delete__方法的两个参数与__get__方法的前两个参数相同。
以上是关于请问python描述符property中的self.fget(instance)怎么理解的主要内容,如果未能解决你的问题,请参考以下文章
Python3 魔法方法:描述符(property的实现原理)