标签:please 简洁 lse 框架 ase 出现 ext 代码 行操作
原文:https://zhuanlan.zhihu.com/p/32764345
# 类似函数的形式
class A:
def __init__(self, name, score):
self.name = name # 普通属性
self.score = score
def getscore(self):
return self._score
def setscore(self, value):
print(‘setting score here‘)
if isinstance(value, int):
self._score = value
else:
print(‘please input an int‘)
score = property(getscore, setscore)
a = A(‘Bob‘,90)
a.name # ‘Bob‘
a.score # 90
a.score = ‘bob‘ # please input an int
分析上述调用score的过程
property(getscore, setscore)
对象,因为后者中定义了__get__
与__set__
方法,因此是一个资料描述器,具有比属性更高的优先级,所以这里就访问了描述器__set__
方法__set__
中对fset
属性进行检查,这里即传入的setscore
,不是None
,所以调用了fset
即setscore
方法,这就实现了设置属性时使用自定义函数进行检查的目的__get__
也是一样,查询score时,调用__get__
方法,触发了getscore
方法下面是另一种使用property的方法
# 装饰器形式,即引言中的形式
class A:
def __init__(self, name, score):
self.name = name # 普通属性
self.score = score
@property
def score(self):
print(‘getting score here‘)
return self._score
@score.setter
def score(self, value):
print(‘setting score here‘)
if isinstance(value, int):
self._score = value
else:
print(‘please input an int‘)
a = A(‘Bob‘,90)
# a.name # ‘Bob‘
# a.score # 90
# a.score = ‘bob‘ # please input an int
下面进行分析
score
时,加上装饰器变成访问property(score)
这个描述器,这个score
也作为fget
参数传入__get__
中指定调用时的操作setter
等方法的定义property
和setter
装饰器的两个方法的命名都还是score,一般同名的方法后面的会覆盖前面的,所以调用时调用的是后面的setter
装饰器处理过的score
,是以如果两个装饰器定义的位置调换,将无法进行属性赋值操作。setter
装饰器的score
时,面临一个问题,装饰器score.setter
是什么呢?是score
的setter
方法,而score
是什么呢,不是下面定义的这个score
,因为那个score
只相当于参数传入。自动向其他位置寻找有没有现成的score
,发现了一个,是property
修饰过的score
,这是个描述器,根据property
的定义,里面确实有一个setter
方法,返回的是property
类传入fset
后的结果,还是一个描述器,这个描述器传入了fget
和fset
,这就是最新的score
了,以后实例只要调用或修改score
,使用的都是这个描述器del
则装饰器中的score
找到的是setter
处理过的score
,最新的score
就会是三个函数都传入的score
score
的调用及赋值删除都跟前面一样了property
的原理就讲到这里,从它的定义我们可以知道它其实就是将我们设置的检查等函数传入get set
等方法中,让我们可以自由对属性进行操作。它是一个框架,让我们可以方便传入其他操作,当很多对象都要进行相同操作的话,重复就是难免的。如果想要避免重复,只有自己写一个类似property
的框架,这个框架不是传入我们希望的操作了,而是就把这些操作放在框架里面,这个框架因为只能实现一种操作而不具有普适性,但是却能大大减少当前问题代码重复问题
下面使用描述器定义了Checkint类之后,会发现A类简洁了非常多
class Checkint:
def __init__(self, name):
self.name = name
def __get__(self, instance, owner):
if instance is None:
return self
else:
return instance.__dict__[self.name]
def __set__(self, instance, value):
if isinstance(value, int):
instance.__dict__[self.name] = value
else:
print(‘please input an integer‘)
# 类似函数的形式
class A:
score = Checkint(‘score‘)
age = Checkint(‘age‘)
def __init__(self, name, score, age):
self.name = name # 普通属性
self.score = score
self.age = age
a = A(‘Bob‘, 90, 30)
a.name # ‘Bob‘
a.score # 90
# a.score = ‘bob‘ # please input an int
# a.age=‘a‘ # please input an integer
因为我本人也刚刚学描述器不久,对它的应用还不是非常了解,下面只列举我现在能想到的它有什么用,以后如果想到其他的再补充
__get__
方法中,在判断语句下,obj.__dict__[self.name] = value
。这样每次再调用这个方法都会从这个字典中取得值,而不是重新运行这个方法。(例子来源最后的那个例子)参考网页如下
标签:please 简洁 lse 框架 ase 出现 ext 代码 行操作
原文地址:https://www.cnblogs.com/liujiacai/p/10946768.html