[python] 之 类编码细节

时间:2022-05-07 00:58:24

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语句创建

    通过调用使用

    总是位于一个模块中