zoukankan      html  css  js  c++  java
  • 描述符的应用

    1、本来name应该是传字符串,age传数字,salary是传浮点数,但是我瞎传也可以,说明python没有帮我们判断这个类型

    class People:
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    p2=People(222,"28",30000.0)

    2、那我们用学过的描述符来判断一下类型

    class Typed:#定义一个描述符Typed
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            print("get instance参数[%s]" %instance)
            print("get ower参数[%s]"  %owner)
        def __set__(self, instance, value):
            print("set方法")
            print("set instance参数[%s]" % instance)
            print("set value参数[%s]" % value)
        def __delete__(self, instance):
            print("de instance参数[%s]" % instance)
    class People:
        name=Typed()#描述符
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    set instance参数[<__main__.People object at 0x00000000006D4588>]
    
    set value参数[gouguoqi]

    实例化的过程就是触发__init__然后赋值给name,就触发了__set__方法,

    3、查看一下p1的属性字典,发现没有name。因为name被代理了,是一个Peopele的数据描述符

    class Typed:#定义一个描述符Typed
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            print("get instance参数[%s]" %instance)
            print("get ower参数[%s]"  %owner)
        def __set__(self, instance, value):
            print("set方法")
            print("set instance参数[%s]" % instance)
            print("set value参数[%s]" % value)
        def __delete__(self, instance):
            print("de instance参数[%s]" % instance)
    class People:
        name=Typed()
        def __init__(self,name,age,salary):
            self.name=name#这里触发的是Typed的set方法
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    
    p1.name#调用实例p1的name属性,会触发描述符的get方法
    print(p1.__dict__)
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    set instance参数[<__main__.People object at 0x00000000006D4588>]
    
    set value参数[gouguoqi]
    
    get方法
    
    get instance参数[<__main__.People object at 0x0000000000D44588>]
    
    get ower参数[<class '__main__.People'>]
    
    {'age': 28, 'salary': 30000.0}

    4、实现真正意义的赋值和调用和删除,并存入实例的属性字典

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            instance.__dict__[self.key]=value
    
        def __delete__(self, instance):
            print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    print(p1.__dict__)
    print(p1.name)#调用实例p1的name属性,会触发描述符的get方法
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    {'age': 28, 'name': 'gouguoqi', 'salary': 30000.0}
    
    get方法
    
    gouguoqi

    5、试试修改一下名字的值

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            # print("get instance参数[%s]" %instance)
            # print("get ower参数[%s]"  %owner)
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            # print("set instance参数[%s]" % instance)
            # print("set value参数[%s]" % value)
            instance.__dict__[self.key]=value
    
        def __delete__(self, instance):
            print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        # age = Typed("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    print(p1.__dict__)#打印属性字典
    p1.name="sb"#赋值给给实例的name属性的值,触发set
    print(p1.name)#调用实例p1的name属性,会触发描述符的get方法
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    {'name': 'gouguoqi', 'salary': 30000.0, 'age': 28}
    
    set方法
    
    get方法
    
    sb

    6、删除一下试试

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            # print("get instance参数[%s]" %instance)
            # print("get ower参数[%s]"  %owner)
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            # print("set instance参数[%s]" % instance)
            # print("set value参数[%s]" % value)
            instance.__dict__[self.key]=value
    
        def __delete__(self, instance):
            # print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        # age = Typed("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    print(p1.__dict__)#打印属性字典
    del p1.name #删除实例的name属性 会触发Typed的delete方法
    print(p1.__dict__)#再次查看属性字典
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    {'name': 'gouguoqi', 'salary': 30000.0, 'age': 28}
    
    {'salary': 30000.0, 'age': 28} 

    7、加一个判断,如果name传入的值不是字符串的话就raise一个错误

    (1)传入的是字符串的时候,一切正常

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            # print("get instance参数[%s]" %instance)
            # print("get ower参数[%s]"  %owner)
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            # print("set instance参数[%s]" % instance)
            # print("set value参数[%s]" % value)
            if not isinstance(value,str):
                # print("你传入的不是字符串")
                # return
                raise TypeError("你传入的不是字符串")
            instance.__dict__[self.key]=value
    
        def __delete__(self, instance):
            # print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        # age = Typed("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p1=People("gouguoqi",28,30000.0)
    print(p1.__dict__)#打印属性字典
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    {'salary': 30000.0, 'name': 'gouguoqi', 'age': 28}

    (2)传入的name不是字符串的时候

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            # print("get instance参数[%s]" %instance)
            # print("get ower参数[%s]"  %owner)
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            # print("set instance参数[%s]" % instance)
            # print("set value参数[%s]" % value)
            if not isinstance(value,str):
                # print("你传入的不是字符串")
                # return
                raise TypeError("你传入的不是字符串")
            instance.__dict__[self.key]=value
    
        def __delete__(self, instance):
            # print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        # age = Typed("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p2=People(222,28,30000.0)
    
      File "D:/pyproject/day30/描述符的应用.py", line 22, in __set__
    
        raise TypeError("你传入的不是字符串")
    
    TypeError: 你传入的不是字符串

    8、我们现在实现了判断name的值是不是字符串,那么怎么来控制age必须是数字呢,现在的情况是我们age这里也必须得传入字符串才能正常运行

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            # print("get instance参数[%s]" %instance)
            # print("get ower参数[%s]"  %owner)
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            if not isinstance(value,str):
                # print("你传入的不是字符串")
                # return
                raise TypeError("你传入的不是字符串")
            instance.__dict__[self.key]=value
        def __delete__(self, instance):
            # print("de instance参数[%s]" % instance)
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        age=Typed("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p2=People("gouguoqi","28",30000.0)
    print(p2.age)
    
    C:python35python3.exe D:/pyproject/day30/描述符的应用.py
    
    set方法
    
    set方法
    
    get方法
    
    28

    那么应该怎么做呢,现在的问题就是,你判断的东西必须全部是字符串,是别的就会报错,这是写死了呀,那么如何写活呢

    我们可以在复制一个Typed为Type1把判断条件改为int就行了

    class Typed:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            if not isinstance(value,str):
                raise TypeError("你传入的不是字符串")
            instance.__dict__[self.key]=value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    class Typed1:#定义一个描述符Typed
        def __init__(self,key):
            self.key=key
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            if not isinstance(value,int):
                raise TypeError("你传入的不是数字")
            instance.__dict__[self.key]=value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name")
        age=Typed1("age")
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p2=People("gouguoqi","28",30000.0)
    
    TypeError: 你传入的不是数字

    当我们age字段传入的参数是数字的时候就可以正常运行了,但是这样又是重复代码了呀

    最终版本

    class Typed:#定义一个描述符Typed
        def __init__(self,key,expec_type):
            self.key=key
            self.expec_type=expec_type
        def __get__(self, instance, owner):#描述符必须要有get set delelte
            print("get方法")
            return instance.__dict__[self.key]
        def __set__(self, instance, value):
            print("set方法")
            if not isinstance(value,self.expec_type):
                raise TypeError("%s你传入的不是%s" %(self.key,self.expec_type))
            instance.__dict__[self.key]=value
        def __delete__(self, instance):
            instance.__dict__.pop(self.key)
    class People:
        name=Typed("name",str)
        age=Typed("age",int)
        def __init__(self,name,age,salary):
            self.name=name
            self.age=age
            self.salary=salary
    p2=People("gouguoqi","28",30000.0)
    
    TypeError: age你传入的不是<class 'int'>
  • 相关阅读:
    数据库的未来:ORM+LINQ+RX
    工具论-科学是实用工具
    事务、锁与原子性
    ORM-面向对象&关系数据库
    swift Class的内存布局
    使用phpexcel导出到xls文件的时候出现乱码解决
    苹果CMS
    js网页如何获取手机屏幕宽度
    常用正则说明
    php中的线程、进程和并发区别
  • 原文地址:https://www.cnblogs.com/gouguoqilinux/p/9216495.html
Copyright © 2011-2022 走看看