面向对象概述

面向对象编程是一种以"对象"为核心来组织代码的编程思想,将数据和操作数据的方法封装在一起

在之前的学习中,我们主要通过函数来组织代码——把数据传入函数,函数处理后返回结果。这是面向过程编程。

而面向对象编程的核心思路是:将现实世界中的事物抽象为对象,每个对象有自己的属性(数据)和方法(行为)。

面向过程 vs 面向对象:

面向过程:关注"怎么做"——步骤1→步骤2→步骤3,按流程执行
面向对象:关注"谁来做"——找到负责的对象,让它调用方法来完成

一个简单的对比:

1
2
3
4
5
6
7
8
9
10
# 面向过程:用函数处理学生的数据
stu_name = "小明"
stu_age = 18
stu_scores = [85, 92, 78]

def get_average(scores):
return sum(scores) / len(scores)

print(f"{stu_name}{stu_age}岁,平均分{get_average(stu_scores)}")
# 输出 小明,18岁,平均分85.0
1
2
3
4
5
6
7
8
9
10
11
12
13
# 面向对象:把学生抽象为一个对象
class Student:
def __init__(self, name, age, scores):
self.name = name
self.age = age
self.scores = scores

def get_average(self):
return sum(self.scores) / len(self.scores)

stu = Student("小明", 18, [85, 92, 78])
print(f"{stu.name}{stu.age}岁,平均分{stu.get_average()}")
# 输出 小明,18岁,平均分85.0

面向对象的三大特性:

封装 — 将数据和操作封装在类内部,隐藏实现细节
继承 — 子类复用父类的属性和方法,实现代码复用
多态 — 同一操作作用于不同对象,可以有不同的行为

类与对象

类是对象的模板/蓝图,对象是类的具体实例。通过 class 关键字定义类,通过 类名() 创建对象

  1. 类的定义与对象的创建
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 类名:
类的属性和方法定义

对象名 = 类名() 创建该类的实例
"""

# 定义一个类
class Dog:
"""狗类"""
# 类属性(所有实例共享)
species = "犬科"

# 方法
def bark(self):
print("汪汪!")

# 创建对象(实例化)
dog1 = Dog()
dog2 = Dog()

print(dog1.species) # 输出 犬科
dog1.bark() # 输出 汪汪!
print(dog2.species) # 输出 犬科
1
2
3
4
# 对象在内存中是独立的存在
print(dog1) # 输出 <__main__.Dog object at 0x...> (内存地址)
print(dog2) # 输出 <__main__.Dog object at 0x...> (不同的内存地址)
print(dog1 is dog2) # 输出 False (两个不同的对象)
  1. 实例属性与 self
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"""
self 代表当前对象本身,是方法中访问对象属性的桥梁
在定义方法时,self 必须作为第一个参数
在调用方法时,Python 会自动将调用者传给 self,不需要手动传
"""

class Dog:
def set_info(self, name, age):
"""给当前对象设置属性"""
self.name = name # self.name 是实例属性
self.age = age

def introduce(self):
print(f"我叫{self.name},今年{self.age}岁")

dog = Dog()
dog.set_info("旺财", 3) # Python 内部:Dog.set_info(dog, "旺财", 3)
dog.introduce() # 输出 我叫旺财,今年3岁

构造方法 init

init 是类的构造方法,在创建对象时自动调用,用于初始化对象的属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
"""
__init__(self, ...) 构造方法:
- 在 类名() 创建对象时自动执行
- 用于设置对象的初始状态(属性)
- self 参数必须有,后面可以跟其他参数
"""

class Student:
def __init__(self, name, age, grade):
"""创建学生对象时自动调用,初始化属性"""
self.name = name
self.age = age
self.grade = grade
print(f"学生 {self.name} 已创建")

def show_info(self):
print(f"姓名:{self.name},年龄:{self.age},年级:{self.grade}")

# 创建对象时传入参数
stu1 = Student("小明", 18, "高三") # 输出 学生 小明 已创建
stu2 = Student("小红", 17, "高二") # 输出 学生 小红 已创建

stu1.show_info() # 输出 姓名:小明,年龄:18,年级:高三
stu2.show_info() # 输出 姓名:小红,年龄:17,年级:高二
1
2
3
4
5
6
7
8
9
10
11
12
# 构造方法也可以有默认参数
class Book:
def __init__(self, title, author="佚名", pages=0):
self.title = title
self.author = author
self.pages = pages

book1 = Book("Python入门", "张三", 300)
book2 = Book("日记本") # author 和 pages 使用默认值

print(book2.author) # 输出 佚名
print(book2.pages) # 输出 0

成员方法与属性

类内部定义的函数称为方法,通过 self 绑定的变量称为实例属性

  1. 实例方法
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
"""
实例方法:第一个参数是 self,通过对象来调用
实例方法可以访问和修改对象的属性
"""

class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner # 实例属性
self.balance = balance

def deposit(self, amount): # 实例方法 — 存款
if amount > 0:
self.balance += amount
print(f"存入 {amount} 元,余额:{self.balance} 元")

def withdraw(self, amount): # 实例方法 — 取款
if amount > self.balance:
print(f"余额不足(余额:{self.balance} 元)")
elif amount > 0:
self.balance -= amount
print(f"取出 {amount} 元,余额:{self.balance} 元")

def show_balance(self): # 实例方法 — 查询
print(f"{self.owner} 的余额:{self.balance} 元")

acc = BankAccount("PyTs1n9", 1000)
acc.deposit(500) # 输出 存入 500 元,余额:1500 元
acc.withdraw(200) # 输出 取出 200 元,余额:1300 元
acc.show_balance() # 输出 PyTs1n9 的余额:1300 元
  1. str 方法(魔术方法)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
"""
__str__(self) 方法:
定义对象被 print() 或 str() 时的字符串表示
不定义时默认输出 <__main__.类名 object at 0x...>
"""

class Student:
def __init__(self, name, age):
self.name = name
self.age = age

def __str__(self):
"""定义对象的字符串表示"""
return f"Student({self.name}, {self.age}岁)"

stu = Student("小明", 18)
print(stu) # 输出 Student(小明, 18岁)
# 没定义 __str__ 时输出 <__main__.Student object at 0x...>
  1. 类属性 vs 实例属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
"""
类属性:定义在类内部、方法外部的变量,所有实例共享
实例属性:通过 self.xxx 在方法内部定义的变量,每个实例独有
"""

class Student:
school = "第一中学" # 类属性(所有学生共享)

def __init__(self, name):
self.name = name # 实例属性(每个学生不同)

stu1 = Student("小明")
stu2 = Student("小红")

print(stu1.school) # 输出 第一中学
print(stu2.school) # 输出 第一中学
print(stu1.name) # 输出 小明
print(stu2.name) # 输出 小红

# 修改类属性影响所有实例
Student.school = "第二中学"
print(stu1.school) # 输出 第二中学
print(stu2.school) # 输出 第二中学

封装

将属性和方法"包装"在类内部,通过访问控制隐藏内部实现,只暴露必要的接口

  1. 私有属性与方法
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
"""
Python 中通过命名约定来实现封装:
- _name:单下划线开头,表示"约定受保护"(仍可从外部访问,但不建议)
- __name:双下划线开头,触发名称改写(name mangling),更难从外部访问
- __name__:双下划线开头结尾,是系统定义的魔术方法,一般不自己定义这种
"""

class Student:
def __init__(self, name, age):
self.name = name # 公开属性
self._age = age # "受保护"属性(约定,不强制)
self.__score = 0 # 私有属性(名称改写)

def set_score(self, score):
"""通过公开方法设置私有属性(可以加校验逻辑)"""
if 0 <= score <= 100:
self.__score = score
else:
print("分数必须在 0-100 之间")

def get_score(self):
"""通过公开方法获取私有属性"""
return self.__score

def __private_method(self):
"""私有方法,只能在类内部调用"""
print("这是私有方法")

stu = Student("小明", 18)
print(stu.name) # 输出 小明(公开属性,直接访问)
print(stu._age) # 输出 18(_ 仅约定,仍可访问,但不建议)

stu.set_score(95) # 通过公开方法设置
print(stu.get_score()) # 输出 95

# print(stu.__score) # 报错 AttributeError(私有属性不能直接访问)
# stu.__private_method() # 报错 AttributeError(私有方法不能直接调用)
1
2
3
4
5
6
7
8
9
10
# 双下划线名称改写原理
"""
__score 实际上被改名为 _Student__score
Python 并没有真正的"私有",只是改了名字防止意外访问
"""
stu = Student("小明", 18)
stu.set_score(88)

# 实际上可以通过改写后的名字访问(不推荐!)
print(stu._Student__score) # 输出 88
  1. 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
"""
@property 装饰器将方法调用变成属性访问的形式
既保留了封装(内部可以加逻辑),又让调用更简洁
"""

class Circle:
def __init__(self, radius):
self._radius = radius

@property
def radius(self):
"""获取半径"""
return self._radius

@radius.setter
def radius(self, value):
"""设置半径(带校验)"""
if value <= 0:
raise ValueError("半径必须大于 0")
self._radius = value

@property
def area(self):
"""面积(只读属性,不需要 setter)"""
import math
return math.pi * self._radius ** 2

c = Circle(5)
print(c.radius) # 输出 5 (像属性一样访问,实际调用了 radius getter)
c.radius = 10 # 像属性一样赋值,实际调用了 radius setter
print(c.area) # 输出 314.159... (只读属性)
# c.area = 100 # 报错 AttributeError(没有定义 setter)

继承

子类继承父类的属性和方法,实现代码复用;可以重写父类方法来定制行为

  1. 单继承
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
"""
class 子类名(父类名):
pass

子类自动获得父类的所有属性和方法
"""

# 父类
class Animal:
def __init__(self, name):
self.name = name

def eat(self):
print(f"{self.name} 在吃东西")

def sleep(self):
print(f"{self.name} 在睡觉")

# 子类继承父类
class Dog(Animal):
def bark(self):
print(f"{self.name} 汪汪叫")

class Cat(Animal):
def meow(self):
print(f"{self.name} 喵喵叫")

dog = Dog("旺财")
dog.eat() # 输出 旺财 在吃东西(继承自 Animal)
dog.sleep() # 输出 旺财 在睡觉(继承自 Animal)
dog.bark() # 输出 旺财 汪汪叫(Dog 自己的方法)

cat = Cat("咪咪")
cat.meow() # 输出 咪咪 喵喵叫
# cat.bark() # 报错 AttributeError(Cat 没有 bark 方法)
  1. 方法重写(Override)
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
"""
子类定义与父类同名的方法,覆盖父类的实现
通过 super() 可以在重写的方法中调用父类的方法
"""

class Animal:
def __init__(self, name):
self.name = name

def speak(self):
print(f"{self.name} 发出声音")

class Dog(Animal):
def speak(self):
"""重写父类的 speak 方法"""
print(f"{self.name} 汪汪叫")

class Cat(Animal):
def speak(self):
print(f"{self.name} 喵喵叫")

dog = Dog("旺财")
cat = Cat("咪咪")
dog.speak() # 输出 旺财 汪汪叫
cat.speak() # 输出 咪咪 喵喵叫
  1. super() 调用父类方法
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
"""
super() 返回父类的临时对象,用于调用父类方法
在重写方法时经常需要先调用父类的同名方法,再添加子类的逻辑
"""

class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"Animal init:{self.name}")

class Dog(Animal):
def __init__(self, name, age, breed):
# 调用父类的 __init__,传入父类需要的参数
super().__init__(name, age)
# 添加子类特有的属性
self.breed = breed
print(f"Dog init:{self.name},品种{self.breed}")

dog = Dog("旺财", 3, "金毛")
# 输出:
# Animal init:旺财
# Dog init:旺财,品种金毛

print(dog.breed) # 输出 金毛
1
2
3
4
5
# 不使用 super() 的对比
class DogWithoutSuper(Animal):
def __init__(self, name, age, breed):
Animal.__init__(self, name, age) # 直接调用父类方法(繁琐且不推荐)
self.breed = breed
  1. 多重继承
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
"""
class 子类(父类1, 父类2, ...):
子类可以继承多个父类

属性/方法的查找顺序遵循 MRO(Method Resolution Order)
使用 类名.__mro__ 或 类名.mro() 查看解析顺序
"""

class Flyer:
def fly(self):
print("可以飞")

class Swimmer:
def swim(self):
print("可以游泳")

class Duck(Flyer, Swimmer):
def quack(self):
print("嘎嘎叫")

duck = Duck()
duck.fly() # 输出 可以飞
duck.swim() # 输出 可以游泳
duck.quack() # 输出 嘎嘎叫

# 查看方法解析顺序
print(Duck.__mro__)
# 输出 (<class '__main__.Duck'>, <class '__main__.Flyer'>, \
# <class '__main__.Swimmer'>, <class 'object'>)

多态

多态是指同一操作作用于不同对象时,可以产生不同的行为;在 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
"""
多态的核心:不同的对象拥有同名方法,调用时不需要关心对象具体是什么类型
Python 的鸭子类型:"如果它走起来像鸭子,叫起来像鸭子,那它就是鸭子"
"""

class Dog:
def speak(self):
return "汪汪"

class Cat:
def speak(self):
return "喵喵"

class Duck:
def speak(self):
return "嘎嘎"

# 多态:不关心对象类型,只要有 speak 方法就能用
def animal_sound(animal):
"""任何有 speak 方法的对象都可以传入"""
print(animal.speak())

animal_sound(Dog()) # 输出 汪汪
animal_sound(Cat()) # 输出 喵喵
animal_sound(Duck()) # 输出 嘎嘎
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
# 多态的实际应用:统一处理不同类型的对象
class Circle:
def __init__(self, radius):
self.radius = radius

def area(self):
import math
return math.pi * self.radius ** 2

class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height

def area(self):
return self.width * self.height

class Triangle:
def __init__(self, base, height):
self.base = base
self.height = height

def area(self):
return 0.5 * self.base * self.height

# 多态:不论什么图形,统一计算总面积
shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 8)
]

total_area = sum(shape.area() for shape in shapes)
print(f"总面积:{total_area:.2f}")
# 输出 总面积:114.54

类方法与静态方法

类方法用 @classmethod 装饰,操作类本身;静态方法用 @staticmethod 装饰,逻辑上属于类但不操作实例或类

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
class Student:
count = 0 # 类属性,统计学生总数

def __init__(self, name):
self.name = name
Student.count += 1

def introduce(self):
"""实例方法:操作实例属性"""
print(f"我叫{self.name}")

@classmethod
def get_count(cls):
"""类方法:操作类属性,第一个参数是类本身(cls)"""
return cls.count

@classmethod
def create_anonymous(cls):
"""类方法:作为工厂方法创建实例"""
return cls("无名")

@staticmethod
def is_valid_name(name):
"""静态方法:不需要访问实例或类,只是逻辑上相关"""
return len(name) >= 2 and not name.isspace()

# 实例方法:通过对象调用
stu = Student("小明")
stu.introduce() # 输出 我叫小明

# 类方法:通过类名或对象调用
print(Student.get_count()) # 输出 1
stu2 = Student.create_anonymous()
print(stu2.name) # 输出 无名

# 静态方法:通过类名或对象调用
print(Student.is_valid_name("王")) # 输出 False(长度不足)
print(Student.is_valid_name("王小")) # 输出 True
1
2
3
4
5
6
7
8
9
10
# 三种方法的对比总结
"""
┌──────────────┬─────────────┬──────────────┬──────────────────┐
│ 类型 │ 装饰器 │ 第一个参数 │ 主要用途 │
├──────────────┼─────────────┼──────────────┼──────────────────┤
│ 实例方法 │ 不需要 │ self(实例) │ 操作实例属性 │
│ 类方法 │ @classmethod │ cls(类) │ 操作类属性/工厂方法 │
│ 静态方法 │@staticmethod │ 无 │ 工具函数/逻辑归组 │
└──────────────┴─────────────┴──────────────┴──────────────────┘
"""

魔术方法

魔术方法(Magic Method)是 Python 中以双下划线开头和结尾的特殊方法,可以自定义对象的行为

常用的魔术方法:

__init__(self, ...)		构造方法,创建对象时调用
__str__(self)			print() / str() 时调用,返回用户友好的字符串
__repr__(self)			repr() / 调试时调用,返回开发者友好的字符串
__len__(self)			len() 时调用
__eq__(self, other)		使用 == 比较时调用
__lt__(self, other)		使用 < 比较时调用
__add__(self, other)		使用 + 运算时调用
__getitem__(self, key)		使用 obj[key] 索引时调用
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
class Book:
def __init__(self, title, author, pages):
self.title = title
self.author = author
self.pages = pages

def __str__(self):
"""用户友好的字符串表示"""
return f"《{self.title}》— {self.author}"

def __repr__(self):
"""开发者友好的字符串表示"""
return f"Book('{self.title}', '{self.author}', {self.pages})"

def __len__(self):
"""len() 返回页数"""
return self.pages

def __eq__(self, other):
"""== 判断是否是同一本书(同书名和同作者)"""
if isinstance(other, Book):
return self.title == other.title and self.author == other.author
return False

book1 = Book("Python入门", "张三", 300)
book2 = Book("Python入门", "张三", 500)

print(str(book1)) # 输出 《Python入门》— 张三
print(repr(book1)) # 输出 Book('Python入门', '张三', 300)
print(len(book1)) # 输出 300
print(book1 == book2) # 输出 True (虽然页数不同,但书名和作者相同)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 运算符重载:让自定义对象支持 + 运算
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y

def __add__(self, other):
"""定义 + 运算:向量加法"""
return Vector(self.x + other.x, self.y + other.y)

def __mul__(self, scalar):
"""定义 * 运算:向量数乘"""
return Vector(self.x * scalar, self.y * scalar)

def __str__(self):
return f"Vector({self.x}, {self.y})"

v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1 + v2) # 输出 Vector(4, 6)
print(v1 * 3) # 输出 Vector(3, 6)

综合练习

将面向对象知识融会贯通,通过实际案例巩固类与对象、封装、继承、多态的使用

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
75
76
"""
练习一:图书管理系统
演示:封装、继承、多态
"""

class LibraryItem:
"""图书馆通用物品(父类)"""
def __init__(self, title, item_id):
self.title = title
self.item_id = item_id
self.__is_borrowed = False # 私有属性:借出状态

def borrow(self):
if self.__is_borrowed:
print(f"「{self.title}」已被借出")
return False
self.__is_borrowed = True
print(f"「{self.title}」借出成功")
return True

def return_item(self):
if not self.__is_borrowed:
print(f"「{self.title}」未被借出")
return False
self.__is_borrowed = False
print(f"「{self.title}」归还成功")
return True

def is_borrowed(self):
return self.__is_borrowed

def get_info(self):
status = "已借出" if self.__is_borrowed else "可借"
return f"[{self.item_id}] {self.title}{status}"

class Book(LibraryItem):
"""书籍(子类)"""
def __init__(self, title, item_id, author, pages):
super().__init__(title, item_id)
self.author = author
self.pages = pages

def get_info(self):
"""重写父类方法,添加书籍特有信息"""
base_info = super().get_info()
return f"{base_info} | 作者:{self.author} | {self.pages}页"

class DVD(LibraryItem):
"""DVD(子类)"""
def __init__(self, title, item_id, duration):
super().__init__(title, item_id)
self.duration = duration

def get_info(self):
base_info = super().get_info()
return f"{base_info} | 时长:{self.duration}分钟"

# 使用
items = [
Book("Python编程", "B001", "张三", 450),
Book("数据结构", "B002", "李四", 320),
DVD("Python教程", "D001", 120)
]

for item in items:
print(item.get_info())

# 输出:
# [B001] Python编程 — 可借 | 作者:张三 | 450页
# [B002] 数据结构 — 可借 | 作者:李四 | 320页
# [D001] Python教程 — 可借 | 时长:120分钟

# 借书和还书
items[0].borrow() # 输出 「Python编程」借出成功
items[0].borrow() # 输出 「Python编程」已被借出
items[0].return_item() # 输出 「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
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
"""
练习二:猜拳游戏(面向对象版)
演示:封装,类的交互
"""
import random

class Player:
def __init__(self, name):
self.name = name
self.score = 0

def choose(self):
"""玩家出拳"""
choices = {1: "石头", 2: "剪刀", 3: "布"}
while True:
try:
choice = int(input(f"{self.name},请出拳(1石头 2剪刀 3布):"))
if choice in choices:
return choice
print("请输入 1、2 或 3")
except ValueError:
print("请输入有效数字")

class Computer:
def __init__(self):
self.name = "电脑"
self.score = 0

def choose(self):
"""电脑随机出拳"""
return random.randint(1, 3)

class Game:
"""游戏主逻辑"""
CHOICES = {1: "石头", 2: "剪刀", 3: "布"}

def __init__(self):
self.player = Player("玩家")
self.computer = Computer()

def judge(self, p_choice, c_choice):
"""判断胜负,返回 1=玩家赢 -1=电脑赢 0=平局"""
diff = p_choice - c_choice
if diff == 0:
return 0
# 石头(1) 剪刀(2) 布(3)
# 1-2= -1 ← 石头克剪刀(玩家赢)
# 2-3= -1 ← 剪刀克布(玩家赢)
# 3-1= 2 ← 布克石头(玩家赢)
return 1 if diff in (-1, 2) else -1

def play_round(self):
p = self.player.choose()
c = self.computer.choose()
print(f"{self.computer.name}出了:{self.CHOICES[c]}")

result = self.judge(p, c)
if result == 1:
self.player.score += 1
print(f"{self.player.name} 赢!")
elif result == -1:
self.computer.score += 1
print(f"{self.computer.name} 赢!")
else:
print("平局!")

print(f"比分 — {self.player.name}{self.player.score} \
{self.computer.name}{self.computer.score}")

# game = Game()
# game.play_round()

面向对象是 Python 编程的分水岭。掌握类与对象的创建、理解封装/继承/多态三大特性、善用魔术方法和 property 装饰器,你就能以更符合人类思维方式来组织代码。记住:类是模板,对象是实例;self 指向当前对象;super() 连接父子类;多态让代码更灵活。面向对象不是银弹,但在构建大型项目时,它是不可或缺的组织工具。

Python Study Note 系列文章

  1. Python Study Note
  2. Python 函数使用(四)
  3. Python 判断语句(二)
  4. Python 基础语法(一)
  5. Python 异常处理(七)
  6. Python 循环语句(三)
  7. Python 数据容器(五)
  8. Python 文件基础操作(六)
  9. Python 模块与包(八)
  10. Python 类型注解(十)
  11. Python 面向对象(九)重点
  12. Python 高阶技巧(十一)