@property把一个方法包装成属性,访问该属性就是调用该方法。
例如:
@property
def a():
return self.b
等于把方法a变成了属性,访问self.a时,等于运行了该方法。
与之配套的有许多参数,此处以setter为例
@a.setter
def a(self.val):
#注意对a设置setter,def后接的函数名也必须完全一致,否则报错
self.b = val
如此一来,我们就实现了存取转移。
读取a,等于读取b。 写入a,等于写入b。
eval更神奇一点。
eval() 函数用来执行一个字符串表达式,并返回表达式的值。
上面是百科描述,然而在示例代码中可以看到,eval的效果是读取""字符串中指向的方法(但不运行)。
示例代码:
class test(object):
def like_work(self):
a= 'work seccessfully'
print(a)
return a
def set_handler(self,method):
method = eval('self.'+method + '_work')
print("type of method is ",type(method))
self.handler = method
#注意,eval只是把handler设置为like_work方法,而非like_work的返回值
print("type of self.handler is ")
print(type(self.handler))
@property
def handler(self):
print('property handler is runned')
print('self._handler is ',self._handler)
return self._handler
@handler.setter
def handler(self,val):
print("_handler is set to val")
print('val is ',val)
self._handler = val
@property
def ddd(self):
self._ddd = self._handler()
return self._ddd
再运行如下代码
te=test()
te.set_handler('like')
得到结果
type of method is <class 'method'>
_handler is set to val
val is <bound method test.like_work of <__main__.test object at 0x0000000004E0C390>>
property handler is runned
self._handler is <bound method test.like_work of <__main__.test object at 0x0000000004E0C390>>
type of self.handler is<class 'method'>
可以看到,
赋值操作优先于读取操作
或者说是覆盖了,重点理解即可。
原本我以为self.handler = method这句,会先运行等号左边。
实际上根本没有运行到 @property def handler(self),
而是直接去了@handler.setter 这个方法。
后面print(type(self.handler))时,才运行了 @property def handler(self)。
注意,@handler.setter必须声明,否则任何 self.handler = xxx 的句式都会因为无法赋值而报错。
再运行
print('aa',te.ddd)
得到结果
work seccessfully
aa work seccessfully
可以看到
之前的self._handler 只是把方法like_work存起来了,没有运行。
self._ddd = self._handler() 这样,在方法后面加了(),才是获取了like_work()的返回值。