首先申明下,本文为笔者学习《Python学习手册》的笔记,并加入笔者自己的理解和归纳总结。
1. 类的定义
class
语句创建类对象并将其赋值给变量名,类可以看成是模块中的变量。
>>> class Sample:
def setValue(self, val): # self指向类实例
self.val = val # 添加一个实例变量val
def getValue(self): # 返回实例变量val的值
return self.val
2. 创建实例
每个实例都拥有自己的命名空间,实例变量的修改不会影响其他实例。
>>> s = Sample() # 在Sample加上括号创建类实例
>>> s.setValue("Hello World!") # 调用方法setValue
>>> s.getValue()
'Hello World!'
>>> s1 = Sample() # 创建另一个实例s1
>>> s1.setValue("Welcome") # 在s1上调用方法
>>> s1.getValue()
'Welcome'
>>> s.getValue() # s和s1互不干扰
'Hello World!'
3. 访问变量和方法
通过逗号(.)
访问变量和方法
>>> s = Sample()
>>> s.val = "Welcome" # 访问实例变量
>>> s.getValue()
'Welcome'
通过__dict__
变量访问变量
>>> s.__dict__ # __dict__是一个字典
{'val': 'Welcome'}
>>> s.__dict__.get("val")
'Welcome'
通过类来访问方法
>>> Sample.setValue(s, "value init") # 类似于s.setValue("value init")
>>> s.getValue()
'value init'
4. 构造函数
新的实例构造时,会调用__init__()
方法。
>>> class Shape:
def __init__(self, x, y, w=10, h=10):
self.x = x
self.y = y
self.width = w
self.height = h
def draw(self):
print "draw"
访问构造函数,构造函数同一般的函数一样,可以设默认值,通过关键字访问。
>>> s = Shape(4, 5) # width和height采用默认值
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 10, 'width': 10}
>>> s = Shape(4, 5, 100)
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 10, 'width': 100}
>>> s = Shape(4, 5, w=50, h=45) # 采用混合参数
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 45, 'width': 50}
对于一个已经定义了构造函数的类来说,默认构造方法不一定有效。
>>> s = Shape()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
s = Shape()
TypeError: __init__() takes at least 3 arguments (1 given)
5. 类属性
__dict__
显示类的属性。
>>> s = Shape(4, 5, 50, 45)
>>> s.__dict__
{'y': 5, 'x': 4, 'height': 45, 'width': 50}
>>> Shape.__dict__ # 类显示属性和方法
{'__module__': '__main__', 'draw': <function draw at 0x0000000002BF1208>, '__ini
t__': <function __init__ at 0x0000000002BF1198>, '__doc__': None}
__bases__
显示父类
>>> Shape.__bases__
()
>>> class Circle(Shape): # Cirle继承Shape类
pass
>>> Circle.__bases__
(<class __main__.Shape at 0x0000000002BED708>,)
>>> class Oval(Shape, Circle): # Oval继承两个类
pass
>>> Oval.__bases__
(<class __main__.Shape at 0x0000000002BED708>, <class __main__.Circle at 0x0000000002BED768>)
6. 类变量
在Shape
中有一个变量color
,作为Shape
的类变量。
>>> Shape.color = "red"
>>> s1 = Shape(3, 4) # 创建Shape实例s1
>>> s2 = Shape(5, 6) # 创建Shape实例s2
>>> Shape.color, s1.color, s2.color # 所有实例的color都是一样的
('red', 'red', 'red')
修改这个类变量,会影响其他实例。
>>> Shape.color = "blue" # 修改类变量后,所有的实例都被修改
>>> Shape.color, s1.color, s2.color
('blue', 'blue', 'blue')
如果在某个实例中修改了这个变量,实际会把这个变量本地化,二期不会影响其他实例。
>>> s1.color = "green" # 实例设置color值,color成为实例的本地变量
>>> Shape.color, s1.color, s2.color
('blue', 'green', 'blue')
>>> Shape.color = "red" # 再次修改Shape类的color变量
>>> Shape.color, s1.color, s2.color # s1已经设置了本地变量,不会受到影响
('red', 'green', 'red')
可以设置方法。
>>> def draw(self):
print "position at (%d, %d)" % (self.x, self.y)
>>> Shape.draw = draw # 把方法赋值给一个变量
>>> Shape.draw(s1)
position at (3, 4) # Shape类调用方法
>>> s1.draw() # s1实例调用方法
position at (3, 4)
7. 方法重载
两个相同名称的方法,最后出现的方法会覆盖之前所有的方法,类似于给一个变量赋值,只有最后一次有效
>>> class Sample:
def add(self, val1, val2):
return val1 + val2
def add(self, val1, val2, val3):
return val1 + val2 + val3
>>> s = Sample()
>>> s.add(13, 23) # 调用add方法,add方法被覆盖
Traceback (most recent call last):
File "<pyshell#71>", line 1, in <module>
s.add(13, 23)
TypeError: add() takes exactly 4 arguments (3 given)
>>> s.add(13, 23, 37)
73
8. 类的继承
8.1 继承
实现继承需要在类名后面的括号内加入需要继承的类,Circle
类继承了Shape
类,同时继承了变量、构造函数和其他方法。
>>> class Shape:
def __init__(self, x, y, w=10, h=10):
self.x = x
self.y = y
self.width = w
self.height = h
def draw(self):
print "Shape draw"
>>> class Circle(Shape):
pass
调用Circle
类
>>> c = Circle(50, 65) # Circle继承了Shape的构造函数和属性
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 10, 'width': 10}
>>> c.draw() # Circle继承了Shape的draw方法
Shape draw
8.2 方法覆盖。
覆盖Circle
的构造函数和draw
方法。
>>> class Circle(Shape):
def __init__(self, x, y, radius=10):
Shape.__init__(self, x, y, 0, 0)
self.radius = radius
def draw(self):
print "Circle draw"
>>> c = Circle(50, 65) # 调用Circle的构造函数
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 0, 'radius': 10, 'width': 0}
>>> c = Circle(50, 65, 20)
>>> c.__dict__
{'y': 65, 'x': 50, 'height': 0, 'radius': 20, 'width': 0}
>>> c = Circle(50, 65, 20, 20)
Traceback (most recent call last):
File "<pyshell#188>", line 1, in <module>
c = Circle(50, 65, 20, 20)
TypeError: __init__() takes at most 4 arguments (5 given)
>>> c.draw() # 调用Shape的draw方法
Circle draw
8.3 方法调用顺序
Sampe
有两个父类Sup1
和Sup2
。查找顺序Sample->Sup1->Sup2
。Sup1
和Sup2
是根据在Sample
继承顺序排列的。
>>> class Sup1:
def fun(self):
print "Sup1.fun"
def fun1(self):
print "Sup1.fun1"
>>> class Sup2:
def fun(self):
print "Sup2.fun"
def fun1(self):
print "Sup2.fun1"
def fun2(self):
print "Sup2.fun2"
>>> class Sample(Sup1, Sup2):
def fun(self):
print "Sample.fun"
>>> s = Sample()
>>> s.fun() # 调用Sample自身的fun方法
Sample.fun
>>> s.fun1() # 调用Sup1的fun1方法
Sup1.fun1
>>> s.fun2() # 调用Sup2的fun2方法
Sup2.fun2
9. 抽象类
>>> from abc import ABCMeta, abstractmethod
>>> class Super:
__metaclass__ = ABCMeta # metaclass设置为ABCMeta
@abstractmethod # 方法添加abstractmethod
def fun(self):
pass
>>> Super()
Traceback (most recent call last):
File "<pyshell#46>", line 1, in <module>
Super()
TypeError: Can't instantiate abstract class Super with abstract methods fun
>>> class Sample(Super):
def fun(self):
print "in sample"
>>> Sample().fun()
in sample
10. 特殊变量
>>> class Sample:
def __init__(self):
self._x = 12
self.__x = 13
def fun(self):
print "fun"
def _fun(self):
print "_fun"
def __fun(self):
print "__fun"
>>> s = Sample()
>>> dir(s) # __x和__fun变成_Sample__xx
['_Sample__fun', '_Sample__x', '__doc__', '__init__', '__module__', '_fun', '_x', 'fun']
11. 限定属性__slots__
>>> class Sample(object): # 定义一个继承object的类
__slots__ = ("name", "age") # __slots__定义了两个属性
>>> s = Sample()
>>> s.name = "Mike" # 可以进行属性name
>>> s.name
'Mike'
>>> s.addr = "ShangHai" # addr没有定义,无法访问
Traceback (most recent call last):
File "<pyshell#216>", line 1, in <module>
s.addr = "ShangHai"
AttributeError: 'Sample' object has no attribute 'addr'
12. 自定义类的打印信息
class
实例会调用默认打印信息。
>>> class Sample:
pass
>>> Sample()
<__main__.Sample instance at 0x03302940>
字符串表达式__repr__
定义交互式界面的输出。
>>> class Sample:
def __repr__(self):
return "[Sample, repr]"
>>> Sample() # 交互式界面调用repr方法
[Sample, repr]
>>> print Sample() # print方法也会调用repr方法
[Sample, repr]
字符串表达式__str__
定义print
的输出。
>>> class Sample:
def __str__(self):
return "[Sample, str]"
>>> Sample() # 交互式界面调用默认方法
<__main__.Sample instance at 0x0000000002AC8848>
>>> print Sample() # print方法调用str方法
[Sample, str]
__repr__
和__str__
都被定义。
>>> class Sample:
def __repr__(self):
return "[Sample, repr]"
def __str__(self):
return "[Sample, str]"
>>> Sample() # 交互式界面调用repr方法
[Sample, repr]
>>> print Sample() # print方法调用str方法
[Sample, str]