Python · 面向对象

基本概念

一个类(Class)能够创建一种新的类型(Type),其中对象(Object)就是类的实例(Instance),这种从属于对象或类的变量叫作字段(Field),对象还可以使用属于类的函数来实现某些功能,这种函数叫作类的方法(Method),字段与方法通称类的属性(Attribute)

self:类方法与普通函数只有一种特定的区别,前者必须多加一个 self 参数在参数列表开头。

示例oop_method.py

1
2
3
4
5
6
7
8
9
10
11
12
class Person:
def say_hi(self):
print('Hello, how are you?')

p = Person()
p.say_hi()
# 前面两行同样可以写作
# Person().say_hi()

输出:
$ python oop_method.py
Hello, how are you?

__init__ :此方法会在类的对象被实例化(Instantiated)时立即运行,对目标对象进行初始化操作。

示例oop_init.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person:
def __init__(self, name):
self.name = name

def say_hi(self):
print('Hello, my name is', self.name)

p = Person('Swaroop')
p.say_hi()
# 前面两行同时也能写作
# Person('Swaroop').say_hi()

输出:
$ python oop_init.py
Hello, my name is Swaroop
  • 类变量(Class Variable):共享的,可以被属于该类的所有实例访问。
  • 对象变量(Object variable):由类的每一个独立的对象或实例所拥有。

示例oop_objvar.py

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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# coding=UTF-8

class Robot:
"""表示有一个带有名字的机器人"""

# 一个类变量,用来计数机器人的数量
population = 0

def __init__(self, name):
"""初始化数据"""

# 一个对象变量
self.name = name
print("(Initializing {})".format(self.name))

# 当有人被创建时,机器人将会增加人口数量
Robot.population += 1

def die(self):
"""我挂了"""
print("{} is being destroyed!".format(self.name))

Robot.population -= 1

if Robot.population == 0:
print("{} was the last one.".format(self.name))
else:
print("There are still {:d} robots working.".format(
Robot.population))

def say_hi(self):
"""来自机器人的诚挚问候:没问题,你做得到!"""
print("Greetings, my masters call me {}.".format(self.name))

# 类方法
@classmethod
def how_many(cls):
"""打印出当前的人口数量"""
print("We have {:d} robots.".format(cls.population))


droid1 = Robot("R2-D2")
droid1.say_hi()
Robot.how_many()

droid2 = Robot("C-3PO")
droid2.say_hi()
Robot.how_many()

print("\nRobots can do some work here.\n")

print("Robots have finished their work. So let's destroy them.")
droid1.die()
droid2.die()

Robot.how_many()

输出:
$ python oop_objvar.py
(Initializing R2-D2)
Greetings, my masters call me R2-D2.
We have 1 robots.
(Initializing C-3PO)
Greetings, my masters call me C-3PO.
We have 2 robots.

Robots can do some work here.

Robots have finished their work. So let's destroy them.
R2-D2 is being destroyed!
There are still 1 robots working.
C-3PO is being destroyed!
C-3PO was the last one.
We have 0 robots.

继承

面向对象编程的一大优点是对代码的重用(Reuse),重用的一种实现方法就是通过继承(Inheritance)机制,继承最好是想象成在类之间实现类型与子类型(Type and Subtype)关系的工具。

  • 多态性(Polymorphism):子类和父类存在相同的方法时,子类覆盖了父类的方法。
  • 基类(Base Class)/ 超类(Superclass)SchoolMember
  • 派生类(Derived Classes)/ 子类(Subclass)TeacherStudent
1
2
3
4
5
6
7
8
9
10
            ┌───────────────┐
│ SchoolMember │
└───────────────┘

┌────────────┴────────────┐
│ │
▼ ▼
┌─────────────┐ ┌─────────────┐
│ Teacher │ │ Student │
└─────────────┘ └─────────────┘

示例oop_subclass.py

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
48
49
50
51
52
53
54
55
56
# coding=UTF-8

class SchoolMember:
'''代表任何学校里的成员。'''
def __init__(self, name, age):
self.name = name
self.age = age
print('(Initialized SchoolMember: {})'.format(self.name))

def tell(self):
'''告诉我有关我的细节。'''
print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ")

class Teacher(SchoolMember):
'''代表一位老师。'''
def __init__(self, name, age, salary):
SchoolMember.__init__(self, name, age)
self.salary = salary
print('(Initialized Teacher: {})'.format(self.name))

def tell(self):
SchoolMember.tell(self)
print('Salary: "{:d}"'.format(self.salary))


class Student(SchoolMember):
'''代表一位学生。'''
def __init__(self, name, age, marks):
SchoolMember.__init__(self, name, age)
self.marks = marks
print('(Initialized Student: {})'.format(self.name))

def tell(self):
SchoolMember.tell(self)
print('Marks: "{:d}"'.format(self.marks))

t = Teacher('Mrs. Shrividya', 40, 30000)
s = Student('Swaroop', 25, 75)

# 打印一行空白行
print()

members = [t, s]
for member in members:
# 对全体师生工作
member.tell()

输出:
$ python oop_subclass.py
(Initialized SchoolMember: Mrs. Shrividya)
(Initialized Teacher: Mrs. Shrividya)
(Initialized SchoolMember: Swaroop)
(Initialized Student: Swaroop)

Name:"Mrs. Shrividya" Age:"40" Salary: "30000"
Name:"Swaroop" Age:"25" Marks: "75"