首页 > 代码库 > class随笔(一)

class随笔(一)

  • 每个class语句会生成一个新的类对象。
  • 每次类调用时,就会生成一个新的实例对象。
  • 实例自动连接至创建了这些实例的类。
  • 类连接至其超类的方式是:将超类列在类头部的括号内,从左到右的顺序会决定树中的次序。

 

举个例子:

技术分享
1 class C2:...  # make class objects
2 class C1:...
3 
4 class C3(C1, C2):....  # linked to superclasses
5 L1 = C3()  # make instance objects
6 L2 = C3()  # link to their classes
View Code

...

附加在实例上的属性只属于那些实例,但附加在类上的属性则由所有子类及其实例共享。

故:

  • 属性通常是在class语句中通过赋值语句添加在类中,而不是嵌入在函数的def语句中。
  • 属性通常是在类内,对传给函数的特殊参数(即self),做赋值运算而添加在实例中。

例:

技术分享
class C1(C2, C3):     # make and link class 
    def setname(self, who):    # assign name : C1.setname       
        self.name = who

L1 = C1()    # make 2 instances
L2 = C2()
L1.setname(bob)    # set L1.name to ‘bob‘
L2.setname(calvin)     # set L2.name to ‘calvin‘
print(L1.name)     # prints ‘bob‘
View Code

从操作的角度来看,当def出现在这种类的内部时,通常称为方法,而且会自动接收第一个特殊参数(通常称为self),这个参数提供了被处理的实例的参照值。因为类是多个实例的工厂,每当需要取出或设定正由某个方法调用所处理的特定的实例的属性时,那些方法通常都会通过这个自动传入的参数self。

类和实例属性并没有事先声明,而是在首次赋值时它的值才会存在。当方法对self属性进行赋值时,会创建或修改类树底端实例内的属性,因为self自动引用正在处理的实例。

 

事实上,因为类树中所有对象都不过是命名空间对象,可以通过变量名读取或设置其属性。只要变量名C1和L1都位于代码的作用域内,写C1.setname和L1.setname都是有效的。

对上面的代码进行分析:在setname方法调用前,C1类都不会把name属性附加在实例之上。事实上,调用L1.setname前引用L1.setname会产生未定义变量名的错误。

如果类想确保像name这样的变量名一定会在其实例中设置,通常才最佳在构造时填好这个属性。

如下:

技术分享
class C1(C2, C3):
    def __init__(self, who):    # set name when constructed
        self.name = who    # self is either L1 or L2

L1 = C1(bob)    # sets L1.name to ‘bob‘
L2 = C1(calvin)    # sets L2.name to ‘calvin‘
print(L1.name)    # prints ‘bob‘
View Code

执行过程:每次从类产生实例时,python会自动调用名为__init__的方法,新实例会正常传入__init__的self参数,而列在类调用小括号内的任何值会成为第二以及其后的参数。其效果就是在创建实例时初始化了这个实例,而不需要额外的方法调用。

所以,__init__被称为构造函数。

class随笔(一)