[python] 之 类编码细节
1. class语句创建类
class()语句是对象的创建者并且是一个隐含的赋值运算-执行时,它会创建对象,并把引用值存储在前面所使用的变量名,这一点和函数def语句一样,语法定义如下。
1 class <name>(superclass, ... ): #asssign to name 2 data = value #shared class data 3 def method(self, ...): #methods 4 sself.member = value #Per-instance data
注:在类中,所有顶层的赋值语句,一般都可以看作是类的属性,可以供所有由给类创建的实例所共享。类和实例都有着自己的命名空间或作用域,且所有类的属性都可以被其创建的实例所共享。而各个实例虽然来自于同一个类所创建,但是它们有着封闭的独立命名空间,互不干扰。若更改类的属性,会影响所有的实例,但如果只更改某一个实例的属性,不会影响其它的实例和创建该实例的类;在python当中,一般函数,类,模块能够创建作用域,封闭变量名。
1 class P(object): 2 spam = 88 3 4 x1 = P() 5 x2 = P() 6 print (P.spam,x1.spam,x2.spam) 7 print ('P.__dict__:',P.__dict__) 8 print ('x1.__dict__:',x1.__dict__) 9 print ('x2.__dict__:',x2.__dict__) 10 11 P.spam = 99 12 print (P.spam,x1.spam,x2.spam) 13 print ('P.__dict__:',P.__dict__) 14 print ('x1.__dict__:',x1.__dict__) 15 print ('x2.__dict__:',x2.__dict__) 16 17 x1.spam = 66 18 print (P.spam,x1.spam,x2.spam) 19 print ('P.__dict__:',P.__dict__) 20 print ('x1.__dict__:',x1.__dict__) 21 print ('x2.__dict__:',x2.__dict__) 22 #输出 23 88 88 88 24 P.__dict__: {'__weakref__': <attribute '__weakref__' of 'P' objects>, '__module__': '__main__', 'spam': 88, '__dict__': <attribute '__dict__' of 'P' objects>, '__doc__': None} 25 x1.__dict__: {} 26 x2.__dict__: {} 27 99 99 99 28 P.__dict__: {'__weakref__': <attribute '__weakref__' of 'P' objects>, '__module__': '__main__', 'spam': 99, '__dict__': <attribute '__dict__' of 'P' objects>, '__doc__': None} 29 x1.__dict__: {} 30 x2.__dict__: {} 31 99 66 99 32 P.__dict__: {'__weakref__': <attribute '__weakref__' of 'P' objects>, '__module__': '__main__', 'spam': 99, '__dict__': <attribute '__dict__' of 'P' objects>, '__doc__': None} 33 x1.__dict__: {'spam': 66} 34 x2.__dict__: {}
2. 方法
方法通过实例或类本身两种方法其中的任意一种进行调用。
self明确化的意义:明确脚本中使用的是实例属性名称,而不是本地作用域或全局作用域。
通过类调用方法的模式,是扩展继承方法行为的一般基础,但一定要为方法传入实例。
instance.method(args) <=> class.method(instance, args)
3. 调用超类构造函数
通过类调用方法一定要为类提供实例
4. 继承
继承 ---》 定制 ---》 扩展
属性树的构建:
1》实例属性是由对方法内self属性进行赋值运算而生成的
2》类属性是通过class语句内的顶层赋值语句赋值而生成的
3》属性树的搜索顺序在2.2版本以后都采用了广度优先的搜索算法;经典类采用深度优先算法,从左至右;新式类采用广度优先搜索。
6. 继承方法的专有化
命名空间或作用域的专有化,只能由创建它们的类或实例调用。
7. 命名空间-完整内容
在python中,创建命名空间的功能语句只有def,class,model。
7.1 变量名有无点号的区别
1》无点号运算的变量名(例如,X)与作用域对应
2》点号的属性名使用(object.X)的是对象(object)的命名空间
7.2 简单变量名:如果赋值就不是全局变量
无点号的简单变量名遵循LEGB法则
1》赋值语句(X=value)
使变量名变为本地变量:在当前作用域内,创建或改变变量名X,除非声明是全局变量
2》引用(X)
在当前作用域内搜索变量名(X),之后是在任何以及所有的嵌套的函数中,然后是在当前的全局作用域中搜索,最后在内置作用域中搜索。
7.3 属性名称:对象命名空间
点号的属性名指的是特定对象的属性,并遵循模块和类的规则,引用增加了继承搜索规则。
1》赋值语句(object.X = value)
在进行点号运算的对象的命名空间内创建或修改属性名X
2》引用(object.X)
基于类的对象,在对象内搜索属性名,然后是其上所有可读取的类(使用继承搜索流程);
基于模块的对象,从对象中直接读取。
注:作用域总是由源代码中的赋值语句位置决定的(也就是语句),而绝不会受到其导入关系的影响;创建实例属性的方法是在类的__init__构造函数内进行赋值的,但并不是唯一的,只要进行了self赋值运算都创建实例属性。典型例子如下:
1 #manyneme.py 2 x = 11 # ①.模块属性 3 4 def f(): 5 print x 6 7 def g(): 8 x = 22 # ②.函数内的本地变量 9 print x 10 11 class C: 12 x = 33 # ③.类属性 13 def m(self): 14 x = 44 # ④.方法中的本地变量 15 self.x = 55 # ⑤.实例属性
8. 命名空间字典
object.__dict__:只显示object对象的命名空间字典,不包含继承的命名空间字典。
dir(object):显示object对象本身的命名空间字典和继承的命名空间字典。
9. 文档字符串
下面以一个例子说明文档字符串出现的位置(这些位置的文档字符串可以通过object.__doc__访问)
1 #docstr.py 2 "I am: docstr.__doc__" 3 4 def func(args): 5 "I am: docstr.func.__doc__ " 6 pass 7 8 class P(object): 9 "I am: docstr.P.__doc__ or P.__doc__ " 10 def method(self): 11 "I am: P.method.__doc__ or self.method__doc__"
10. 类与模块的关系
模块:
是数据或逻辑包
通过python文件或C扩展创建
通过导入来使用
类:
实现新的对象
由class语句创建
通过调用使用
总是位于一个模块中