本文采用知识共享署名 4.0 国际许可协议进行许可,转载时请注明原文链接,图片在使用时请保留全部内容,可适当缩放并在引用处附上图片所在的文章链接。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Document():
def __init__(self, title, author, context):
print('init function called')
self.title = title
self.author = author
self.__context = context # __ 开头的属性是私有属性
def get_context_length(self):
return len(self.__context)
def intercept_context(self, length):
self.__context = self.__context[:length]
harry_potter_book = Document('Harry Potter', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')
print(harry_potter_book.title)
print(harry_potter_book.author)
print(harry_potter_book.get_context_length())
harry_potter_book.intercept_context(10)
print(harry_potter_book.get_context_length())
print(harry_potter_book.__context)
|
- 类:一群有着相似性的事物的集合,这里对应 Python 的 class。
- 对象:集合中的一个事物,这里对应由 class 生成的某一个 object,比如代码中的 harry_potter_book。
- 属性:对象的某个静态特征,比如上述代码中的 title、author 和 __context。
- 函数:对象的某个动态能力,比如上述代码中的 intercept_context () 函数。
1. 类的成员
类的成员包括:属性和方法。
属性可以分为:静态属性和实例属性
方法可以分为:普通方法、类方法和静态方法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
#!/usr/bin/python3
class MyClass:
"""一个简单的类实例"""
i = 12345
def f(self):
return 'hello world'
# 实例化类
x = MyClass()
# 访问类的属性和方法
print("MyClass 类的属性 i 为:", x.i)
print("MyClass 类的方法 f 输出为:", x.f())
|
1.1. 类的属性
属性可以分为:静态属性和实例属性。
实例属性属于对象,而静态属性属于类。
通过类创建对象时,如果每个对象都具有相同的属性,那么就使用静态属性。
1.1.1. 静态属性的创建方式
静态属性是属于类的,所以不用创建对象访问。
1
2
3
4
5
6
7
8
9
10
|
#!/usr/bin/python3
class Province:
# 静态字段
country = '中国'
# 直接访问静态字段
Province.country
|
1.1.2. 实例属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
lass Goods:
def __init__(self):
# 原价
self.original_price = 100
# 折扣
self.discount = 0.8
@property
def price(self):
# 实际价格 = 原价 * 折扣
new_price = self.original_price * self.discount
return new_price
@price.setter
def price(self, value):
self.original_price = value
@price.deleter
def price(self):
del self.original_price
|
实例属性可以在构造方法中进行初始化。@property装饰器可以把一个实例方法变成其同名属性,以支持.号访问。我们可以根据属性的访问特点,分别将三个方法定义为对同一个属性:获取、修改、删除。
扩展:
对于静态属性还可以使用property函数的形式定义一个属性。与@property实现原理类似。
property(fget=None, fset=None, fdel=None, doc=None)
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Foo:
def get_bar(self):
return 'get_bar'
# *必须两个参数
def set_bar(self, value):
return 'set value' + value
def del_bar(self):
return 'del_bar'
age = property(fget=get_bar,fset=set_bar,fdel=del_bar,doc='description...')
|
1.2. 类的方法
方法包括:普通方法、类方法和静态方法。
如果Python中没有属性,方法完全可以代替其功能。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Foo:
def __init__(self, name):
self.name = name
def ord_func(self):
""" 定义普通方法,至少有一个self参数 """
# print self.name
print('普通方法')
@classmethod
def class_func(cls):
""" 定义类方法,至少有一个cls参数 """
print('类方法')
@staticmethod
def static_func():
""" 定义静态方法 ,无默认参数"""
print('静态方法')
|
2. 类成员的修饰符
对于每一个类的成员而言都有两种形式:
公有成员,在任何地方都能访问。
私有成员,只有在类的内部才能方法。
私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:init、call、__dict__等)
ps:如果想要强制访问私有字段,可以通过 【对象._类名__私有字段明 】访问(如:obj._C__foo),不建议强制访问私有成员。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class C:
name = '公有静态字段'
__sname ='私有静态字段'
def pub_func(self):
print(C.name)
def pra_func(self):
print(C._sname)
class D(C):
def pub_show(self):
print(C.name)
def pra_show(self):
print(C._sname)
|
注:不建议强制访问私有成员。
3. 类的特殊成员
-
__doc__ : 表示类的描述信息。
-
__module__ : 表示当前操作的对象在哪个模块
-
__class__ : 表示当前操作的对象的类是什么
-
__init__ : 构造方法,通过类创建对象时,自动触发执行。
1
2
3
4
5
6
7
8
|
#!/usr/bin/python3
class Complex:
def __init__(self, realpart, imagpart):
self.r = realpart
self.i = imagpart
x = Complex(3.0, -4.5)
print(x.r, x.i) # 输出结果:3.0 -4.5
|
-
__del__ : 当对象在内存中被释放时,自动触发执行。
-
__call__ : 对象后面加括号,触发执行。
-
__dict__ : 类或对象中的所有成员。
-
__str__ : 如果一个类中定义了__str__方法,那么在打印 对象 时,默认输出该方法的返回值。有点像java中的toString方法。
-
__getitem__、__setitem__、__delitem__ : 用于索引操作,如字典。以上分别表示获取、设置、删除数据。
-
__getslice__、__setslice__、__delslice__ : 三个方法用于分片操作。
-
__iter__ : 用于迭代器,之所以列表、字典、元组可以进行for循环,是因为类型内部定义了 __iter__。
4. 类的专有方法:
- __init__ : 构造函数,在生成对象时调用
- __del__ : 析构函数,释放对象时使用
- __repr__ : 打印,转换
- __setitem__ : 按照索引赋值
- __getitem__: 按照索引获取值
- __len__: 获得长度
- __cmp__: 比较运算
- __call__: 函数调用
- __add__: 加运算
- __sub__: 减运算
- __mul__: 乘运算
- __truediv__: 除运算
- __mod__: 求余运算
- __pow__: 乘方
5. 继承
5.1. 单继承
Python 同样支持类的继承,如果一种语言不支持继承,类就没有什么意义。派生类的定义如下所示:
1
2
3
4
5
6
|
class DerivedClassName(BaseClassName):
<statement-1>
.
.
.
<statement-N>
|
子类(派生类 DerivedClassName)会继承父类(基类 BaseClassName)的属性和方法。
BaseClassName(实例中的基类名)必须与派生类定义在一个作用域内。除了类,还可以用表达式,基类定义在另一个模块中时这一点非常有用:
1
|
class DerivedClassName(modname.BaseClassName):
|
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
|
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
s = student('ken',10,60,3)
s.speak()
|
5.2. 多继承
1
2
3
4
5
6
|
class DerivedClassName(Base1, Base2, Base3):
<statement-1>
.
.
.
<statement-N>
|
需要注意圆括号中父类的顺序,若是父类中有相同的方法名,而在子类使用时未指定,python从左至右搜索 即方法在子类中未找到时,从左到右查找父类中是否包含方法。
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
38
39
40
41
42
43
44
45
46
47
|
#!/usr/bin/python3
#类定义
class people:
#定义基本属性
name = ''
age = 0
#定义私有属性,私有属性在类外部无法直接进行访问
__weight = 0
#定义构造方法
def __init__(self,n,a,w):
self.name = n
self.age = a
self.__weight = w
def speak(self):
print("%s 说: 我 %d 岁。" %(self.name,self.age))
#单继承示例
class student(people):
grade = ''
def __init__(self,n,a,w,g):
#调用父类的构函
people.__init__(self,n,a,w)
self.grade = g
#覆写父类的方法
def speak(self):
print("%s 说: 我 %d 岁了,我在读 %d 年级"%(self.name,self.age,self.grade))
#另一个类,多重继承之前的准备
class speaker():
topic = ''
name = ''
def __init__(self,n,t):
self.name = n
self.topic = t
def speak(self):
print("我叫 %s,我是一个演说家,我演讲的主题是 %s"%(self.name,self.topic))
#多重继承
class sample(speaker,student):
a =''
def __init__(self,n,a,w,g,t):
student.__init__(self,n,a,w,g)
speaker.__init__(self,n,t)
test = sample("Tim",25,80,4,"Python")
test.speak() #方法名同,默认调用的是在括号中参数位置排前父类的方法
|
5.3. 方法重写
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
#!/usr/bin/python3
class Parent: # 定义父类
def myMethod(self):
print ('调用父类方法')
class Child(Parent): # 定义子类
def myMethod(self):
print ('调用子类方法')
c = Child() # 子类实例
c.myMethod() # 子类调用重写方法
super(Child,c).myMethod() #用子类对象调用父类已被覆盖的方法
|
super() 函数是用于调用父类(超类)的一个方法。
执行以上程序输出结果为:
6. 运算符重载
Python同样支持运算符重载,我们可以对类的专有方法进行重载,实例如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
#!/usr/bin/python3
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return 'Vector (%d, %d)' % (self.a, self.b)
def __add__(self,other):
return Vector(self.a + other.a, self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print (v1 + v2)
|