(重)python:描述符的应用,类实例化时,参数类型的限制功能实现

#描述符的应用;
#众所周知,python是弱类型的语言;但是,很多时候,我们在class实例化传参时,
# 需要限定不同的参数用不同的数据类型;这个时候就需要描述符的应用来代理要描述的参数
#描述符指:一个类,中重写了__get__()、__set__()、__delete__()方法中的一个,
# 但是,数据描述符都必须将三个函数重写;功能也要自己添加

class Typed():
    def __init__(self,key,type):
        '''
        :param key: 描述的属性关键字
        :param type: 所描述的属性期待的数据类型
        '''
        self.key=key
        self.type=type

    def __set__(self, instance, value):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身,
          value  :描述的对象的属性的值\即实例化的传参值
        '''
        #为了实现需求:限制传入参数的类型,这里采用if语句
        if not isinstance(value,self.type):
            raise TypeError("参数类型错误,%s的类型不是%s"%(self.key,self.type))
            #抛出异常,你也可以不抛出异常,直接print
        else:
            instance.__dict__[self.key]=value
    def __get__(self, instance, owner):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身,
        owner  :描述的对象的所属的类
        '''
        return instance.__dict__[self.key]
    def __delete__(self, instance):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身
        '''
        instance.__dict__.pop(self.key)

#上面实现了数据描述符的编写,下面举例使用描述符
class People:
    '''
    总的来说:描述符描述属性,就是绕了一个弯,
    调用了描述符类的__get__()、__set__()、__delete__()方法,
    而不是在类自身的方法;
    这样可以实现,参数类型的限制
    '''
    name=Typed("name",str)
    age=Typed("age",int)
    # 利用描述符代理属性,当People实例化时,就会触发Typed()实例化,
    # 同时,触发__set__(),传入属性值在dict属性字典中;
    # 在调用People实例对象的name\age属性时,会触发Typed()的__get__()方法
    def __init__(self,name,age):
        self.name=name
        self.age=age


if __name__ == '__main__':
    people=People("张三",18)#不会报错
    print(people.name)
    people1=People(12,"张三")#会报错
#描述符  +  装饰器   应用于类class,描述符用来限制参数类型,装饰器用来给类添加属性
#众所周知,python是弱类型的语言;但是,很多时候,我们在class实例化传参时,
# 需要限定不同的参数用不同的数据类型;这个时候就需要描述符的应用来代理要描述的参数
#描述符指:一个类,中重写了__get__()、__set__()、__delete__()方法中的一个,
# 但是,数据描述符都必须将三个函数重写;功能也要自己添加

class Typed():
    def __init__(self,key,type):
        '''
        :param key: 描述的属性关键字
        :param type: 所描述的属性期待的数据类型
        '''
        self.key=key
        self.type=type

    def __set__(self, instance, value):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身,
          value  :描述的对象的属性的值\即实例化的传参值
        '''
        #为了实现需求:限制传入参数的类型,这里采用if语句
        if not isinstance(value,self.type):
            raise TypeError("参数类型错误,%s的类型不是%s"%(self.key,self.type))
            #抛出异常,你也可以不抛出异常,直接print
        else:
            instance.__dict__[self.key]=value
    def __get__(self, instance, owner):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身,
        owner  :描述的对象的所属的类
        '''
        return instance.__dict__[self.key]
    def __delete__(self, instance):
        '''
        注释:这个函数的参数是默认的;
        instance  ;实例对象本身
        '''
        instance.__dict__.pop(self.key)

#上面实现了数据描述符的编写,下面举例使用描述符
#结合:装饰器+描述符

def decorator(*args,**kwargs):
    def wrapper(obj):
        for key,type in kwargs.items():#将字典转换称元祖对:(key,type)
            setattr(obj,key,Typed(key,type))#利用描述符添加属性,描述符主要限制类型;
        return obj
    return wrapper

@decorator(name=str,age=int,gender=str)
class People:
    '''
    总的来说:描述符描述属性,就是绕了一个弯,
    调用了描述符类的__get__()、__set__()、__delete__()方法,
    而不是在类自身的方法;
    这样可以实现,参数类型的限制
    '''

    # 利用描述符代理属性,当People实例化时,就会触发Typed()实例化,
    # 同时,触发__set__(),传入属性值在dict属性字典中;
    # 在调用People实例对象的name\age属性时,会触发Typed()的__get__()方法
    def __init__(self,name,age):
        self.name=name
        self.age=age


if __name__ == '__main__':
    people=People("张三",18)#不会报错
    print(people.name)
    print(People.__dict__)
    print(people.__dict__)
    # people1=People(12,"张三")#会报错

猜你喜欢

转载自blog.csdn.net/ak739105231/article/details/86626912