第八章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步骤:

  1. 调用__getattribute__
    1. 如果没有找到属性age,则__getattribute__抛出AttributeError再调用__getattr__
    2. 如果可以找到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

 

posted @ 2019-12-25 00:57  All_just_for_fun  阅读(199)  评论(0编辑  收藏  举报