由于我实现的Property 类中, setter getter deleter 都是返回self ;
因此你不必在使用装饰器的类(PersonUseDesc) , 使用相同的属性(函数)名,因为他们总是指向同一个Property对象.
而内置函数property 中的setter 这些返回的是一个副本.
自己实现Property前,必须先熟悉什么是描述符.
描述符介绍与深入:描述符简介
#自己构建一个内置的property
#需要理解描述符,才能理解以下实现
class Property:
str_nomethod = "未定义方法"
def __init__(self,fget = None , fset = None, fdel = None , doc = None): #初始化函数与property一样
self.fget = fget
self.fset = fset
self.fdel = fdel
self.__doc__ = doc
def check_method(self,func): #用来检测函数是否被传入
if func is None:raise AttributeError(self.str_nomethod)
def __get__(self, instance, owner): #当获取时会调用此函数
#print('Property.__get__, fget:',self.fget)
if instance is None: return self
self.check_method(self.fget) #检查一下获取函数是否已被传入
return self.fget(instance) #调用被传入的函数
def __set__(self, instance, value): #当设置/修改时调用此函数
#print('Property.__set__, fset:',self.fset)
self.check_method(self.fset)
self.fset(instance,value) #调用被传入的函数
def __delete__(self, instance): #同上
self.check_method(self.fdel)
self.fdel(instance)
def setter(self,func): #模拟内置函数property.setter , 主要用于装饰器语法的使用
print('Property.setter,func:',func)
self.fset = func
return self
def getter(self,func): #同上
print('Property.getter,func:',func)
self.fget = func
return self
def deleter(self,func): #同上
self.fdel = func
return self
#使用函数的方式
class PersonUseMethod:
def __init__(self,value = 'Person'):
self.value = value
def getName(self):
print('PersonUseMethod.getName')
return self.value
def setName(self,value):
print('PersonUseMethod.setName')
self.value = value
name = Property(getName,setName) #使用与内置函数property 一样的方式给类属性 name 赋值,此时name是一个Property对象
p = PersonUseMethod()
p.name #展开:Property.__get__(PersonUserMethod.name, p,PersonUserMethod)
#echo:
#Property.__get__, fget: <function PersonUseMethod.getName at 0x00000000026D6048>
#PersonUseMethod.getName
print('*' * 20)
#使用装饰器的方式
class PersonUseDesc:
def __init__(self,value = 'Person'):
self.value = value
@Property
def name(self): #此时,name将成为Property的对象, name = Property(name,None,None,None), name函数成为fget
return self.value
@name.setter #展开: name = Property.setter(name) , 把name函数设置成 fset
def name(self,value):
print('PersonUseDesc 设置完成')
self.value = value
p = PersonUseDesc()
p.name = '123'
print(p.name)