和其他面向对象的编程语言一样,python也是可以定义类的,下面我将对python中的类做一下总结,主要包括:类的定义、继承、静态方法、类方法、特性和运算符重载。
和c++一样,Python使用关键字class定义类。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
classPeople(object):
numbers=0
def__init__(self, name, age, male, address):
self.name=name
self.age=age
self.male=male
self.address=address
People.numbers+=1
def__del__(self):
People.numbers-=1
defeat(self, food):
printself.name+' is eating '+food+'.'
>>> wuyuan=People('wuyuan',20,True,'wuyuans.com')
>>> wuyuan.eat('apple')
wuyuaniseating apple.
>>> wuyuan.name
'wuyuan'
|
类通常由类变量、方法和属性组成,其中类变量相当于c++中类的静态变量,所有该类的实例都可以访问,通常用于保存公共资源和类实例的相关信息,比如实例的数量。Python中类的方法和一般的有点不一样,多了个self,这个相当于c#中的this变量,表示当前对象实例,在类中访问实例方法和属性时都需要使用self来指示。属性就是类的实例变量,也可以说是成员变量,一般在构造函数__init__中定义,__del__为类的析构函数。
在class语句中可以使用以逗号分隔的基类列表来指定继承,如果未指明将默认继承object类。
1
2
3
4
5
6
7
8
|
classStudent(People):
def__init__(self, name, age, male, address, school):
self.school=school
super(Student,self).__init__(name, age, male, address)
defeat(self, food):
print'Student '+self.name+' is eating '+food+'.'
>>> wuyuan.eat('apple')
Student wuyuaniseating apple.
|
子类可以重定义父类的方法,比如构造函数__init__,以此来添加子类成员变量。使用super函数也可以在构造函数中调用父类的__init__,或者直接使用People.__init__()调用。在使用super时父类在定义时必须继承object类,否则出现TypeError:
1
|
TypeError: must be type, not classobj
|
Python中类的方法一般以实例作为第一个参数self传递,但也有例外的情况,比如静态方法和类方法。
和其他面向对象语言一样,Python的类中也可以定义静态方法,使用@staticmenthod装饰器定义。因为没有传递self参数,静态方法不会对任何实例类型进行操作。
1
2
3
4
5
6
|
classFoo(object):
@staticmethod
defadd(x, y):
returnx+y
>>> Foo.add(1,2)
3
|
如果在编写类时需要采用不同的方式创建新实例,比如工厂模式,则通常使用静态方法。
类方法和静态方法很相似,不同的是当前类将作为第一个参数cls传递,使用@classmethod装饰器定义。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
classTimes(object):
factor=1
@classmethod
defmul(cls, x):
returncls.factor*x
classTwoTimes(Times):
factor=2
>>> Times.mul(3)
3
>>> TwoTimes.mul(3)
6
|
TwoTimes是Times的子类,但在调用mul时cls为TwoTimes,所以cls.factor为2。
特性是一种特殊的属性,访问它时会计算他的值,和c#中的属性类似,使用@property装饰器定义。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
classCircle(object):
def__init__(self, r):
self.__radius=r
@property
defarea(self):
returnmath.pi*self.__radius**2
@property
defperimeter(self):
return2*math.pi*self.__radius
@property
defradius(self):
returnself.__radius
@radius.setter
defradius(self, value):
ifnotisinstance(value,float):
raiseTypeError('Must be a float')
self.__radius=value
@radius.deleter
defradius(self):
self.__radius=0
>>> c=Circle(3.0)
>>> c.radius
3.0
>>> c.area
28.274333882308138
>>> c.perimeter
18.84955592153876
# 赋值
>>> c.radius=4.0
>>> c.radius
4.0
# 删除
>>>delc.radius
>>> c.radius
0
|
当定义了特性后,只能简单访问该特性,要做赋值和删除操作的话必须附加setter和deleter方法。
和c++一样,Python也可以对运算符进行重载。可以重载的方法如下表所示。
Method | Overloads | Call for |
---|---|---|
__init__ | 构造函数 | X=Class() |
__del__ | 析构函数 | 对象销毁 |
__repr__ | 打印转换 | print X,repr(X) |
__str__ | 打印转换 | print X,str(X) |
__call__ | 调用函数 | X() |
__getattr__ | 限制 | X.undefine |
__setattr__ | 取值 | X.any=value |
__getitem__ | 索引 | X[key],For If |
__setitem__ | 索引 | X[key]=value |
__len__ | 长度 | len(X) |
__iter__ | 迭代 | For In |
__add__ | + | X+Y,X+=Y |
__sub__ | - | X-Y,X-=Y |
__mul__ | * | X*Y |
__radd__ | 右加+ | +X |
__iadd__ | += | X+=Y |
__or__ | | | X|Y,X|=Y |
__cmp__ | 比较 == | X==Y,X |
__lt__ | 小于< | X |
__eq__ | 等于= | X=Y |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
classNumber(object):
def__init__(self, value):
self.value=value
# 加重载
def__add__(self, other):
returnNumber(self.value+other.value)
# 打印重载
def__str__(self):
return'The value is %d.'%self.value
# 比较重载
def__cmp__(self, other):
returncmp(self.value, other.value)
>>> x=Number(1)
>>> y=Number(2)
>>>printx+y
The valueis3.
>>> x > y
False
>>> x < y
True
|