cls主要用在类方法定义,而self则是实例方法。

self, cls 不是关键字,完全可以使用自己写的任意变量代替实现一样的效果。

普通的实例方法,第一个参数需要是self,它表示一个具体的实例本身。

如果用了staticmethod,那么就可以无视这个self,而将这个方法当成一个普通的函数使用。

而对于classmethod,它的第一个参数不是self,是cls,它表示这个类本身。

>>> class A(object):
def foo1(self):
print "Hello",self
@staticmethod
def foo2():
print "hello"
@classmethod
def foo3(cls):
print "hello",cls
>>> a = A()
>>> a.foo1() #最常见的调用方式,但与下面的方式相同
Hello <__main__.A object at 0x9f6abec>
>>> A.foo1(a) #这里传入实例a,相当于普通方法的self
Hello <__main__.A object at 0x9f6abec>
>>> A.foo2() #这里,由于静态方法没有参数,故可以不传东西
hello
>>> A.foo3() #这里,由于是类方法,因此,它的第一个参数为类本身。
hello 
>>> A #可以看到,直接输入A,与上面那种调用返回同样的信息。

---------------------------------------------------------------------------------

类的定义可以动态修改

class MyTest:
myname = 'peter'
def sayhello(self):
print "say hello to %s" % self.myname
if __name__ == "__main__":
MyTest.myname = 'hone'
MyTest.sayhello = lambda self, name: "I want say hello to %s" % name
MyTest.saygoodbye = lambda self,name: "I do not want say goodbye to %s" % name
print MyTest().sayhello(MyTest.myname)
print MyTest().saygoodbye(MyTest.myname)

这里修改了MyTest类中的变量和函数定义, 实例化的instance有了不同的行为特征。

-------------------------------------------------------------------------------------

1.Python是一门动态语言,任何实体都可以动态地添加或删除属性。

2.一个类定义了一个作用域。

3.类实例也引入了一个作用域,这与相应类定义的作用域不同。

4.在类实例中查找属性的时候,首先在实例自己的作用域中查找,如果没有找到,则再在类定义的作用域中查找。

5.在对类实例属性进行赋值的时候,实际上会在类实例定义的作用域中添加一个属性(如果还不存在的话),并不会影响到相应类中定义的同名属性。

class A:
cls_i = 0
cls_j = {}
def __init__(self):
self.instance_i = 0
self.instance_j = {}
if __name__ == '__main__':
a = A()
print A.__dict__ #{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {}, '__doc__': None}
print a.__dict__ # {'instance_j': {}, 'instance_i': 0}
>>> a.cls_i
0
>>>
a.instance_i
0

在查找cls_i的时候,实例a的作用域中是没有它的,却在A的作用域中找到了它;在查找instance_i的时候,直接可在a的作用域中找到它。

如果我们企图通过实例a来修改cls_i的值,那会怎样呢:

>>> a.cls_i = 1
>>>a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i': 0}
>>>A.__dict__
{'__init__': , '__module__': '__main__', 'cls_i': 0, 'cls_j': {},
'__doc__': None}

我们可以看到,a的作用域中多了一个cls_i属性,其值为1;同时,我们也注意到A作用域中的cls_i属性的值仍然为0;在这里,我们其实是增加了一个实例属性,并没有修改到类属性。

如果我们通过实例a操纵cls_j中的数据(注意不是cls_j本身),又会怎么样呢:

>>> a.cls_j['a'] ='a'
>>> a.__dict__
{'instance_j': {}, 'cls_i': 1, 'instance_i':0}
>>> A.__dict__
{'__init__': , '__module__': '__main__','cls_i': 0, 'cls_j': {'a': 'a'}, '__doc__': None}

我们可以看到a的作用域没有发生什么变化,但是A的作用域发生了一些变化,cls_j中的数据发生了变化。

实例的作用域发生变化,并不会影响到该类的其它实例,但是类的作用域发生变化,则会影响到该类的所有实例,包括在这之前创建的实例.