第八章python元类编程
1.property动态属性
一般对象中的属性使用单下划线或双下划线开头的都是伪私有类型,对于单下划线开头的属性(表示为protected类型)直接可以通过对象访问,而双下滑线开头的属性(表示private类型)必须使用对象.__类名__私有属性名即可访问
1 class Test: 2 def __init__(self): 3 self.__t1 = "t1" 4 self._t2 = "t2" 5 6 7 test = Test() 8 print(test._Test__t1, test._t2) # t1 t2 9 10 test._Test__t1 = "Test_t1" 11 test._t2 = "Test_t2" 12 print(test._Test__t1, test._t2) # Test_t1 Test_t2
大家应该遵守一个约定就是不要对伪私有类型进行赋值等操作,我们应该使用函数调用的方式,为了让程序更加优雅,我们有装饰器@property让函数变为对象的属性
- @property:设置age为对象属性默认隐藏掉__age,并且设置age像普通属性一样,使用user.age来获得值
- @age.setter:设置@property修饰过的属性的赋值操作像普通属性一样,使用user.age = 65来赋值
1 class User: 2 def __init__(self, name): 3 self.name = name 4 self.__age = 0 5 6 # 一般的函数调用 7 def get_age(self): 8 return self.__age 9 10 # __age的get方法 11 @property 12 def age(self): 13 return self.__age 14 15 # __age的set方法 16 @age.setter 17 def age(self, value): 18 if value > 150 or value < 0: 19 raise ValueError('invalid age') 20 self.__age = value 21 22 23 if __name__ == "__main__": 24 user = User("user1") 25 user.age = 35 26 print(user.age) # 35 27 28 user._User__age = 65 29 print(user._User__age, user.age) # 65 65 30 print(user.get_age()) # 65
2.__getattr__、__getattribute__魔法函数
- __getattribute__:当访问属性时,都会进入这个魔法函数
- __getattr:当访问属性时,没有找到访问的属性则调用这个魔法函数
1 class User: 2 def __init__(self, info={}): 3 self.info = info 4 5 def __getattr__(self, item): 6 return self.info[item] 7 8 # def __getattribute__(self, item): 9 # return "getattribute" 10 11 12 if __name__ == "__main__": 13 user = User(info={"company_name": "imooc", "name": "bobby"}) 14 print(user.name) # imooc
3.属性描述符和属性查找过程
1.什么是属性描述符
实现了__get__、__set__、__delete__中的任意一个方法的类,称为属性描述符
2.什么是数据描述符
实现__get__、__set__两个方法的类
3.什么是非数据描述符
只实现__get__方法的类
4.属性的查找
如果test_user是User类的实例,test_user.age 等价与getattr(test_user,'age')
执行test_user.age步骤:
- 调用__getattribute__
- 如果没有找到属性age,则__getattribute__抛出AttributeError再调用__getattr__
- 如果可以找到age,则调用__get__
进入__getattribute__整体流程:
1 import numbers 2 3 4 class IntField: 5 # 数据描述符 6 def __get__(self, instance, owner): 7 return self.value 8 9 def __set__(self, instance, value): 10 if not isinstance(value, numbers.Integral): 11 raise ValueError("int value need") 12 if value < 0: 13 raise ValueError("positive value need") 14 self.value = value 15 16 def __delete__(self, instance): 17 pass 18 19 20 class NonDataIntField: 21 # 非数据属性描述符 22 def __get__(self, instance, owner): 23 return self.value 24 25 26 class User: 27 age = IntField() 28 # age = NonDataIntField() 29 30 31 if __name__ == "__main__": 32 test_user = User() 33 test_user.age = 1 34 print(test_user.__dict__, User.__dict__) 35 print(test_user.age) 36 pass 37 pass 38 # print(dir(test_user)) 39 # print(test_user.age)
4.__new__和__init__的区别
5.自定义元类
6.元类实现简单的orm