python3:属性描述符(__get__,__set__,__delete__)

版权声明:转载 或者复制请标注来源 https://blog.csdn.net/qq_34979346/article/details/83758447

我先问大家个问题。

如何对属性进行校验呢 比如有个要保证 age 属性 它只能是int类型且大小处于0到100之间?
第一直觉就是用get 和set 方法如下:

1.基本的调用 set 和get 方法

class Student:
    def __init__(self):
        pass


    def get(self):
        return self.age
    def set(self,age):
        if isinstance(age,int) and  0<age<100:
            self.age=age
        else:
            print("请输入合法的年龄")

stu=Student()

stu.set(110)  #请输入合法的年龄

stu.set(10)

print(stu.get()) #10

有的小伙伴该说了,你这太低级了,现在都是用property 了

2.利用@property

对,正确的做法就是 用**@property 装饰器**,可以把方法封装成
属性。
例如:

class Student:
    def __init__(self):
        pass
    @property
    def age(self):
        return self.value
    @age.setter
    def age(self,value):
        if isinstance(value,int) and  0<value<100:
            self.value=value
        else:
            print("请输入合法的年龄")
stu=Student()

stu.age=10
print(stu.age)   # 10

恭喜你明白了@property 的用法。前面都是引子,现在开始我们的正题。

现在又有一个场景:
像age属性 一共有十几个,你该如何做呢

用@property 是可以做到,你知道你需要写多少方法吗,得写20多个,
这代码量也实在太大了吧,这个难道不了我们的优秀的高级开发测试员。

3.利用属性描述符

属性描述符的原理利用的是抽象的方法, 把十几个字段共同的特性抽出来,
每个字段都用这个特性,达到节省代码的目的。 看下 下边的例子:

class Int_validation:
    def __get__(self, instance, owner):
        return  self.value
    def __set__(self, instance, value):
        if  isinstance(value,int) and 0<value<100:
            self.value=value        #这个要注意 要用value,不能用instance 否则会陷入死循环
        else:
            print("请输入合法的数字")
    def __delete__(self, instance):
        pass

class Student:
    age=Int_validation()

stu=Student()   
stu.age=50
print(stu.age)

解释下

  1. 首先我们要把共同的校验封装在一个类里也就是 Int_validation 类,
  2. 重写两个魔法函数 (get 和set)
  3. age=Int_validation() 这个是关键,age 本来是个对象,放在类里当作了Student类属性
  4. 实例化对象stu给age进行赋值 ,它会自动调用Int_validation get的方法 ,我们debug get方法看下过程
value = {int} 50
self = {Int_validation} <__main__.Int_validation object at 0x0000025AA8362CC0>
instance = {Student} <__main__.Student object at 0x0000025AA8362CF8>

显然会把 50 给value, self 就是age本身, instance就是stu

这就是为什么不能 self.instance=instance,而是 self.value=value ,
它会再走一次流程进入死循环。

value=50 进入校验流程 。
5. 当我们调用了 stu.age ,它会调用get方法 并返回值。
debug 的代码

instance = {Student} <__main__.Student object at 0x000001883B6F2CF8>
self = {Int_validation} <__main__.Int_validation object at 0x000001883B6F2CC0>

总结:

1.其他属性也可以用age 方式,自己可以试试
2.这里面 有属性描述符的三要素 要掌握并理解它们的含义, (value,instance,self)缺一不可。
3.巧妙的利用了三个魔法函数,正好 校验类对象是应用类的属性,并且你们会发现我们并没有
调用set和get 方法,这也是魔法函数的特性 。
有不明白的或者错误的请联系我,或者在下边评论 ,谢谢

猜你喜欢

转载自blog.csdn.net/qq_34979346/article/details/83758447