• 例子:对象构造函数指定类型传入参数(描述符与装饰器的应用)


    在python中,传入参数并不像c++,java那种,有严格的类型检查,可以传入不同类型的参数给一变量。如形参name,可传字符串、整形、浮点型实参;如何对其改进?

     1 class Typed:
     2     def __init__(self,key,type_var):
     3         self.type_var=type_var
     4         self.key=key
     5     def __get__(self, instance, owner):
     6         print('get------>',instance)
     7         print('get------>', owner)
     8         return instance.__dict__[self.key]
     9     def __set__(self, instance, value):
    10         print('set------>',instance)
    11         print('set------>', value)
    12         if not isinstance(value,self.type_var):
    13             raise TypeError('你输入的%s不是%s类型'%(self.key,self.type_var))
    14         else:
    15             instance.__dict__[self.key]=value
    16 class People:
    17     name=Typed('name',str)
    18     age=Typed('age',int)
    19     salary=Typed('salary',int)
    20     def __init__(self,name,age,salary):
    21         self.name=name
    22         self.age=age
    23         self.salary=salary
    24 p=People(12,18,22014)
    25 ----------输出
    26     raise TypeError('你输入的%s不是%s类型'%(self.key,self.type_var))
    27 TypeError: 你输入的name不是<class 'str'>类型

      同理,当输入的name不是str,age不是int,salary不是int类型,会报出错误;People中的name,age,salay均为被描述符代理属性,当执行21,22,23行代码时,当然只有当正确实例化对象后才会执行,会触发描述符中的set设置方法。如图输出

    1 #p=People(12,18,22014)
    2 p1=People('alex',18,2201)
    3 -----------输出
    4 set------> <__main__.People object at 0x00000253C8E8B438>
    5 set------> alex
    6 set------> <__main__.People object at 0x00000253C8E8B438>
    7 set------> 18
    8 set------> <__main__.People object at 0x00000253C8E8B438>
    9 set------> 2201

     注意的是描述符类的构造函数__init__,里面预先设置了key,typ_var属性,用于描述符对象name,age等传参时方便触发其set,get有关的操作。但是貌似还是不太简便,若想去给规定参数传入严格要求限制时,须属性=Typed(‘属性’,属性的类型),如要想name为str类型,须name=Typed(‘name’,str),若想设置多个,则会有许多重复累赘代码。接下来利用装饰器来改进----------------》》》

     1 class Typed:
     2     def __init__(self,key,type_var):
     3         self.type_var=type_var
     4         self.key=key
     5     def __get__(self, instance, owner):
     6         print('get------>',instance)
     7         print('get------>', owner)
     8         return instance.__dict__[self.key]
     9     def __set__(self, instance, value):
    10         print('set------>',instance)
    11         print('set------>', value)
    12         if not isinstance(value,self.type_var):
    13             raise TypeError('你输入的%s不是%s类型'%(self.key,self.type_var))
    14         else:
    15             instance.__dict__[self.key]=value
    16 def foo(**kwargs):
    17     def wrapper(obj):
    18         for key,value in kwargs.items():
    19             print('----',key,value)
    20             setattr(obj,key,Typed(key,value))#People.name=Typed('name',str)
    21         return obj
    22     return wrapper
    23 @foo(name=str,age=int,salary=int)#@wrapper---->People=wrapper(People)
    24 class People:
    25     # name=Typed('name',str)
    26     # age=Typed('age',int)
    27     # salary=Typed('salary',int)
    28     def __init__(self,name,age,salary):
    29         self.name=name
    30         self.age=age
    31         self.salary=salary
    32 p=People(12,18,22014)
    33 print(p.__dict__)
     ------》》》》》》raise TypeError('你输入的%s不是%s类型'%(self.key,self.type_var))
    TypeError: 你输入的name不是<class 'str'>类型
     1 # p=People(12,18,22014)
     2 # print(p.__dict__)
     3 p1=People('alex',18,2201)
     4 print(p1.__dict__)
     5 ---------》》
     6 ---- name <class 'str'>
     7 ---- age <class 'int'>
     8 ---- salary <class 'int'>
     9 set------> <__main__.People object at 0x00000161D311B400>
    10 set------> alex
    11 set------> <__main__.People object at 0x00000161D311B400>
    12 set------> 18
    13 set------> <__main__.People object at 0x00000161D311B400>
    14 set------> 2201
    15 {'name': 'alex', 'age': 18, 'salary': 2201}

      此时就可根据其添加属性,无需累赘复写代码,将想传的的变量及类型写入即可,会存进装饰器的字典中进行进一步统一的加工

  • 相关阅读:
    Linux命令行界面使用代理上网
    .NET 开发框架 代码生成器
    如何正确地学习
    Ubuntu实用命令——不断更新中......
    MSSQL如何快速清除数据库日志转,经实践有效
    C# 获取机器码
    C#中得到每周,每月,每季,每年的年初末日期
    asp.net(C#)解析Json的类代码
    由拖库攻击谈口令字段的加密策略(数据库加密)
    用sql查询当天,一周,一个月的数据
  • 原文地址:https://www.cnblogs.com/XiaoJin0/p/10159460.html
Copyright © 2020-2023  润新知