描述符的应用

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:\python35\python3.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:\python35\python3.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:\python35\python3.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:\python35\python3.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:\python35\python3.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:\python35\python3.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:\python35\python3.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'>
posted @ 2018-06-23 10:24  gouguoqi  阅读(258)  评论(0编辑  收藏  举报