python 3.x 元类编程(property,__getattr__,__getattribute__)
元类编程
property动态属性
- property将函数变成一个属性描述符
- 给函数添加一个@property装饰器,就可以通过获取属性的模式来获取函数.(user.age --> user.age())
1 from datetime import date, datetime 2 3 4 class User: 5 def __init__(self, name, birthday): 6 self.name = name 7 self.birthday = birthday 8 9 def get_age(self): 10 """获取现在的年龄""" 11 return datetime.now().year - self.birthday.year 12 13 14 if __name__ == '__main__': 15 user = User('python', date(1988, 3, 1)) 16 17 # 结果: 31 (2019 - 1988 = 31) 18 print(user.get_age())
1 """ 2 property动态属性 3 4 假设如果存在一个这样的应用场景: 5 比如之前在创建数据库的时候设置一个age的字段,但后期删除age这个字段,删除数据库的字段很正常. 6 但是之前有大量的获取年龄的语句都是以user.age的形式获取.现在如果使用函数的方式来获取年龄. 7 那么之前user.age语句都要修改为调用函数的方式get_age(). 8 9 这样的话修改代码量非常的大.有没有什么方法不修该原来的user.age代码,同时还可以获取age年龄??? 10 11 这就涉及到python的计算属性@property装饰器 12 property将age函数变成一个属性描述符 13 给函数添加一个@property装饰器,就可以通过获取属性的模式来获取函数.(user.age --> user.age()) 14 """ 15 from datetime import date, datetime 16 17 18 class User: 19 def __init__(self, name, birthday): 20 self.name = name 21 self.birthday = birthday 22 # self.age = 0 23 24 # def get_age(self): 25 # """获取现在的年龄""" 26 # return datetime.now().year - self.birthday.year 27 28 @property 29 def age(self): 30 return datetime.now().year - self.birthday.year 31 32 33 if __name__ == '__main__': 34 user = User('python', date(1988, 3, 1)) 35 # 结果: 31 (2019 - 1988 = 31) 36 print(user.age)
1 """ 2 property动态属性 3 4 假设如果存在一个这样的应用场景: 5 比如之前在创建数据库的时候设置一个age的字段,但后期删除age这个字段,删除数据库的字段很正常. 6 但是之前有大量的获取年龄的语句都是以user.age的形式获取.现在如果使用函数的方式来获取年龄. 7 那么之前user.age语句都要修改为调用函数的方式get_age(). 8 9 这样的话修改代码量非常的大.有没有什么方法不修该原来的user.age代码,同时还可以获取age年龄??? 10 11 这就涉及到python的计算属性@property装饰器 12 property将age函数变成一个属性描述符 13 给函数添加一个@property装饰器,就可以通过获取属性的模式来获取函数.(user.age --> 函数def age(self)) 14 15 设置@property装饰器修饰的函数的值,需要装饰器@function_name.setter 16 代码书写规范使用@function_name.setter装饰器时,需要设置属性的变量名前添加单一下划线.如_age,_birthday 17 """ 18 from datetime import date, datetime 19 20 21 class User: 22 def __init__(self, name, birthday): 23 self.name = name 24 self.birthday = birthday 25 self._age = 0 26 27 @property 28 def age(self): 29 return datetime.now().year - self.birthday.year 30 31 @age.setter 32 def age(self, value): 33 self._age = value 34 35 36 if __name__ == '__main__': 37 user = User('python', date(1988, 3, 1)) 38 user.age = 18 39 # 结果: 18 40 print(user._age) 41 # 结果: 31 42 print(user.age)
1 """ 2 property动态属性 3 4 假设如果存在一个这样的应用场景: 5 比如之前在创建数据库的时候设置一个age的字段,但后期删除age这个字段,删除数据库的字段很正常. 6 但是之前有大量的获取年龄的语句都是以user.age的形式获取.现在如果使用函数的方式来获取年龄. 7 那么之前user.age语句都要修改为调用函数的方式get_age(). 8 9 这样的话修改代码量非常的大.有没有什么方法不修该原来的user.age代码,同时还可以获取age年龄??? 10 11 这就涉及到python的计算属性@property装饰器 12 property将age函数变成一个属性描述符 13 给函数添加一个@property装饰器,就可以通过获取属性的模式来获取函数.(user.age --> 函数def age(self)) 14 15 设置@property装饰器修饰的函数的值,需要装饰器@function_name.setter 16 代码书写规范使用@function_name.setter装饰器时,需要设置属性的变量名前添加单一下划线.如_age,_birthday 17 """ 18 from datetime import date, datetime 19 20 21 class User: 22 def __init__(self, name, birthday): 23 self.name = name 24 self._birthday = birthday 25 self._age = 0 26 27 @property 28 def age(self): 29 return datetime.now().year - self._birthday.year 30 31 @age.setter 32 def age(self, value): 33 self._birthday = value 34 35 36 if __name__ == '__main__': 37 user = User('python', date(1988, 3, 1)) 38 user.age = date(2016, 2, 2) 39 # 结果: 2016-02-02 40 print(user._birthday) 41 # 结果: 3 42 print(user.age) 43 # 结果: 0 44 print(user._age)
__getattr__()与__getattribute__()魔法函数的区别
- 类当中对属性操作的两个重要的魔法函数
- __getattr__(self, item)魔法函数,在查找不到属性的时候调用.
- __getattribute__(self,item)魔法函数在__getattr__()魔法函数先调用.在构造函数初始化属性时,无条件执行魔法函数(所以不要轻易的覆写__getattribute__()魔法函数.一但逻辑上处理不完善,会影响整个类的属性)
1 """ 2 __getattr__()与__getattribute__()魔法函数的区别 3 类当中对属性操作的两个重要的魔法函数 4 __getattr__()魔法函数,在查找不到属性的时候调用. 5 """ 6 from datetime import date 7 8 9 class User: 10 def __init__(self, name, birthday): 11 self.name = name 12 self.birthday = birthday 13 14 15 if __name__ == '__main__': 16 user = User('python', date(1990, 10, 11)) 17 # 当age属性在User类中不存在的时候调用age,没有覆写__getattr__()魔法函数. 18 # 报错: AttributeError: 'User' object has no attribute 'age' 19 print(user.age)
1 """ 2 __getattr__()与__getattribute__()魔法函数的区别 3 类当中对属性操作的两个重要的魔法函数 4 __getattr__()魔法函数,在查找不到属性的时候调用. 5 """ 6 from datetime import date 7 8 9 class User: 10 def __init__(self, name, birthday): 11 self.name = name 12 self.birthday = birthday 13 14 def __getattr__(self, item): 15 return 'not find attribute' 16 17 18 if __name__ == '__main__': 19 user = User('python', date(1990, 10, 11)) 20 # 当age属性在User类中不存在的时候,去调用魔法函数__getattr__()将结果返回. 21 # 结果: not find attribute 22 print(user.age)
1 """ 2 __getattr__()与__getattribute__()魔法函数的区别 3 类当中对属性操作的两个重要的魔法函数 4 __getattr__(self, item)魔法函数,在查找不到属性的时候调用. 5 6 比如在User里面维护一个dict的类型的参数.我们在类的外部不使用user.dict[key]的形式来获取value. 7 想通过user.key的形式来获取value.这时就需要调用__getattr__(self, item)魔法函数,在魔法函数内部实现自己的逻辑 8 9 """ 10 11 12 class User: 13 def __init__(self, infos): 14 self.infos = infos 15 16 def __getattr__(self, item): 17 """ 18 __getattr__(self, item)魔法函数,在查找不到属性的时候调用. 19 :param item: 获取指定的key 20 :return: value 21 """ 22 return self.infos[item] 23 24 25 if __name__ == '__main__': 26 user = User(infos={'name': 'python', 'age': 18}) 27 # 当age属性在User类中不存在的时候调用age,调用魔法函数__getattr__() 28 # 结果: python 29 print(user.name) 30 # 结果: 18 31 print(user.age)
1 """ 2 __getattr__()与__getattribute__()魔法函数的区别 3 类当中对属性操作的两个重要的魔法函数 4 __getattr__(self, item)魔法函数,在查找不到属性的时候调用. 5 __getattribute__(self,item)魔法函数在__getattr__()魔法函数前先调用.在构造函数初始化属性时,无条件执行的魔法函数 6 """ 7 8 9 class User: 10 def __init__(self, infos): 11 self.infos = infos 12 13 def __getattr__(self, item): 14 return user.infos[item] 15 16 def __getattribute__(self, item): 17 return "__getattribute__" 18 19 20 if __name__ == '__main__': 21 user = User({'name': 'python', 'age': 18}) 22 # 结果: __getattribute__ 23 print(user.name) 24 # 结果: __getattribute__ 25 print(user.age) 26 27 """ 28 通过以上的结果得出结论: 29 __getattribute__(self,item)魔法函数影响整个类的属性,稍有逻辑上处理不好,导致整个类的属性出现问题. 30 所以不要轻易的覆写__getattribute__(self,item)魔法函数. 31 """
********
posted on 2019-04-08 13:00 jaydenjune 阅读(48) 评论(0) 收藏 举报
浙公网安备 33010602011771号