您的位置:首页 > 编程语言 > Python开发

Python:高级主题之(属性取值和赋值过程、属性描述符、装饰器)

2015-11-18 09:42 615 查看

属性取值和赋值过程



一切皆是对象,类型也是对象。

对象包含一个__class__属性指向其所属类型。

对象包含一个__dict__属性指向其所包含的成员(属性和方法)。

取值过程(下面是伪代码)



1 __getattribute__(property) logic:
2
3 descripter = find first descripter in class and bases's dict(property)
4 if descripter:
5     return descripter.__get__(instance, instance.__class__)
6 else:
7     if value in instance.__dict__
8         return value
9
10     value = find first value in class and bases's dict(property)
11     if value is a function:
12         return bounded function(value)
13     else:
14         return value
15
16 raise AttributeNotFundedException




赋值过程(下面是伪代码)



1 __setattr__(property, value)logic:
2
3 descripter = find first descripter in class and bases's dict(property)
4 if descripter:
5     descripter.__set__(instance, value)
6 else:
7     instance.__dict__[property] = value




根据取值和赋值过程的逻辑可以得出以下结论

赋值和取值的位置可能不同。

取值过程的伪代码第11行会返回绑定方法(我们在Javascript经常会让某个函数绑定到指定的作用域,和这个概念是一样的)。

取值和赋值过程都会先查找属性描述符,也就是说:属性描述的优先级最高,下文会介绍属性描述符。

属性描述符

什么是属性描述符?属性描述符就是一个类型,实现了三个魔法方法而已:__set__、__get__和__del__,属性描述符一般不会独立使用,必须存储在类型的__dict__中才有意义,这样才会参与到属性的取值和赋值过程,具体参见上文。

属性描述符



1 #属性描述符
2 class Descripter:
3     def __get__(self, instance, owner):
4         print(self, instance, owner)
5
6     def __set__(self, instance, value):
7         print(self, instance, value)




测试代码



1 class TestClass:
2     Des = Descripter()
3
4
5     def __getattribute__(self, name):
6         print("before __getattribute__")
7         return    super(TestClass, self).__getattribute__(name)
8         print("after __getattribute__")
9
10     def __setattr__(self, name, value):
11         print("before __setattr__")
12         super(TestClass, self).__setattr__(name, value)
13         print("after __setattr__")
14
15 test1 = TestClass()
16 test2 = TestClass()
17
18 test1.Des = None
19 test2.Des




输出结果

1 before __setattr__
2 <__main__.Descripter object at 0x01D9A030> <__main__.TestClass object at 0x01D9A090> None
3 after __setattr__
4 before __getattribute__
5 <__main__.Descripter object at 0x01D9A030> <__main__.TestClass object at 0x01D9A0B0> <class '__main__.TestClass'>


结论

类型的多个实例共享同一个属性描述符实例,属性描述符的优先级高于实例的__dict__,具体自己可以测试一下。

装饰器(AOP)

最基本的函数装饰器

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

带参数的函数装饰器

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

最基本的类型装饰器

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

带参数的类型装饰器

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

备注:可以使用多个装饰器,不过要保证签名的装饰器也是返回的一个方法或类型。

自己实现@staticmethod和@classmethod

理解了属性的取值和赋值过程,开发自定义@staticmethod和@classmethod就不成问题了,let up do it!

代码



1 class MyStaticObject:
2     def __init__(self, fun):
3         self.fun = fun;
4
5     def __get__(self, instance, owner):
6         return self.fun
7
8 def my_static_method(fun):
9     return MyStaticObject(fun)
10
11 class MyClassObject:
12     def __init__(self, fun):
13         self.fun = fun;
14
15     def __get__(self, instance, owner):
16         def class_method(*args, **kargs):
17             return self.fun(owner, *args, **kargs)
18
19         return class_method
20
21 def my_class_method(fun):
22     return MyClassObject(fun)
23
24 class C(object):
25     """docstring for C"""
26
27     def test_instance_method(self):
28         print(self)
29
30     @staticmethod
31     def test_static_method(message):
32         print(message)
33
34     @my_static_method
35     def test_my_static_method(message):
36         print(message)
37
38     @classmethod
39     def test_class_method(cls):
40         print(cls)
41
42     @my_class_method
43     def test_my_class_method(cls):
44         print(cls)
45
46 print("\n实例方法测试")
47 c = C()
48 print(C.test_instance_method)
49 print(C.__dict__["test_instance_method"])
50 print(c.test_instance_method)
51 C.test_instance_method(c)
52 c.test_instance_method()
53
54 print("\n静态方法测试")
55 print(C.test_static_method)
56 print(C.__dict__["test_static_method"])
57 print(c.test_static_method)
58 C.test_static_method("静态方法测试")
59 c.test_static_method("静态方法测试")
60
61 print("\n自定义静态方法测试")
62 print(C.test_my_static_method)
63 print(C.__dict__["test_my_static_method"])
64 print(c.test_my_static_method)
65 C.test_my_static_method("自定义静态方法测试")
66 c.test_my_static_method("自定义静态方法测试")
67
68 print("\n类方法测试")
69 print(C.test_class_method)
70 print(C.__dict__["test_class_method"])
71 print(c.test_class_method)
72 C.test_class_method()
73 c.test_class_method()
74
75 print("\n自定义类方法测试")
76 print(C.test_my_class_method)
77 print(C.__dict__["test_my_class_method"])
78 print(c.test_my_class_method)
79
80 C.test_my_class_method()
81 c.test_my_class_method()
82
83 print("\n对象上的方法不会返回绑定方法,对象描述符也不会起作用")
84 def test(self):
85     print(self)
86
87 c.test = test
88
89 c.test("测试")




结果



1 实例方法测试
2 <function C.test_instance_method at 0x01D3D8A0>
3 <function C.test_instance_method at 0x01D3D8A0>
4 <bound method C.test_instance_method of <__main__.C object at 0x01D8B5B0>>
5 <__main__.C object at 0x01D8B5B0>
6 <__main__.C object at 0x01D8B5B0>
7
8 静态方法测试
9 <function C.test_static_method at 0x01D69108>
10 <staticmethod object at 0x01D8B4F0>
11 <function C.test_static_method at 0x01D69108>
12 静态方法测试
13 静态方法测试
14
15 自定义静态方法测试
16 <function C.test_my_static_method at 0x01D69078>
17 <__main__.MyStaticObject object at 0x01D8B510>
18 <function C.test_my_static_method at 0x01D69078>
19 自定义静态方法测试
20 自定义静态方法测试
21
22 类方法测试
23 <bound method type.test_class_method of <class '__main__.C'>>
24 <classmethod object at 0x01D8B530>
25 <bound method type.test_class_method of <class '__main__.C'>>
26 <class '__main__.C'>
27 <class '__main__.C'>
28
29 自定义类方法测试
30 <function MyClassObject.__get__.<locals>.class_method at 0x01D5EDF8>
31 <__main__.MyClassObject object at 0x01D8B550>
32 <function MyClassObject.__get__.<locals>.class_method at 0x01D5EDF8>
33 <class '__main__.C'>
34 <class '__main__.C'>
35
36 对象上的方法不会返回绑定方法,对象描述符也不会起作用
37 测试
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: