描述符实现Property

由于我实现的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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值