Python class
转载请标明出处(http://blog.csdn.net/lis_12/article/details/52950845).
class
类通常由函数(方法),变量(类变量),和计算出的属性(特性)组成的集合.
使用class语句可定义类.类主体包含一系列在类定义时执行的语句,如
#!/usr/bin/python
# -*- coding: utf-8 -*-
class Accounts(object):
num_accounts = 0 #类变量,所有实例共享该属性,用于跟踪实例的个数
def __init__(self,a,b):#self相当于实例本身
self.name = a
self.age = b
Accounts.num_accounts += 1
def __del__(self):
Accounts.num_accounts -= 1
def fun(self):
print self.name,self.age
return self #self相当于实例本身
if __name__ == '__main__':
print Accounts #<class '__main__.Accounts'>
print Accounts.fun #<unbound method Accounts.fun>,实例方法,需要绑定,所以显示的是未绑定的方法
print Accounts.num_accounts#0
print dir(Accounts) #['__class__', '__del__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'fun', 'num_accounts'] 实例方法即使没有实例也会在类属性中
a = Accounts('xyz',2) #相当于调用Accounts.__init__(a,'xyz',2)
b = a.fun() #xyz 2,b相当于a的引用
print a is b #True
print Accounts.num_accounts#1
b.fun() #xyz 2
a.age = 100
b.fun() #xyz 100
注:
- 在类主体执行期间创建的属性放在类对象中,这个类对象充当着命名空间,与模块极为相似.
- class语句本身并不创建该类的任何实例,类仅仅创建以后所有实例都会使用的属性.
类实例
类的实例以函数形式调用类对象来创建的.这种方法将创建一个新实例,然后将实例传递给类的__init__()
方法.__init__()
方法的参数包括新创建的实例对象(也就是self)和在调用类对象时提供的参数.
以上述代码为例,a = Accounts('xyz',2)相当于调用了Accounts.__init__(a,'xyz',2)
,也就是说self就是实例的引用,对self的操作相当于对实例操作.
在__init__()
内,通过将属性分配给self来将其保存到实例中(属性绑定),当实例调用这些属性时,使用点(.)运算符即可访问.点”.”运算符属于属性绑定.
访问属性时,结果可能来自不同的地方.如上述代码中a.fun()返回Accounts中的fun()方法.访问属性时,首先会检查实例,如果实例中没有该属性,则会对实例的类进行搜索,如果该类存在多个父类,则根据该类的__mro__
在父类中搜索.
注:定义实例方法时,self为第一个参数,self代表实例本身,但是所有合法的标识符都可以替代self,只不过根据约定,我们将其定义为self,增加代码可读性.(约定cls代表类本身).
范围规则
尽管类会定义命名空间,但它们不会为在方法体内使用的变量限定范围.所以在实现类的时候,对属性和方法的引用必须是完全限定的.
通俗用语:如果想在类中方法调用实例属性var,必须用self.var来调用,仅仅使用var的话,并不会在实例中搜索名称为var的属性,而是像正常变量一样搜索(参考作用域这篇博客).如果想从一个方法调用另一个方法,也得采用这种形式,如f1(self),中调用f2(self),则用self.f2()调用.
类中没有范围是Python与C++的区别之一.Python中的self与c++中的this指针类似.
需要显式使用self的原因在于,Python为动态语言,没有提供显式声明变量的方式,因此无法区分在方法中要赋值的变量是局部变量还是要将其保存为实例属性.显式调用self可解决此问题,存储在self中的所有值都是实例本身的一部分,其他赋值为局部变量.
注:如果为某个实例单独添加的属性,其他实例对象是无法访问的.
#!/usr/bin/python
# -*- coding: utf-8 -*-
class A(object):
def __init__(self):
self.a = 1
m = A()
n = A()
print m.a,n.a # 1,1
m.a = 2
print m.a,m.a # 2,1 a为实例属性,但是由于绑定的实例不,所以互不影响
m.c = 3
print m.c # 3 c为m的实例属性,n中并没有属性c,所以n.c错误
print n.c #AttributeError: 'A' object has no attribute 'c'