Python 面向对象编程完全指南:从零基础到“猫狗大战”实战
·
适合人群:Python 初学者、编程爱好者、准备面试的开发者
难度:⭐⭐⭐☆☆
关键词:类、对象、封装、继承、多态、类方法、静态方法、构造方法、析构方法
目录
- 面向对象编程思想
- 类与对象的基本定义
- 构造方法与析构方法
- self 参数详解
- 类变量与实例变量
- 类方法与静态方法
- 封装与私有成员
- 单继承与多继承
- 方法重写与 super()
- 多态的实现
- 综合实战项目
- 常见面试题与总结
一、面向对象编程思想
1.1 什么是面向对象?
面向对象编程(OOP)是一种编程范式,它把数据和操作数据的方法封装在一起,形成“对象”。现实世界中的任何事物都可以抽象为对象。
1.2 面向对象 vs 面向过程
| 对比维度 | 面向过程 | 面向对象 |
|---|---|---|
| 核心 | 函数/过程 | 类/对象 |
| 数据组织 | 数据结构独立于函数 | 数据和方法绑定在一起 |
| 代码复用 | 通过函数调用 | 通过继承、组合 |
| 扩展性 | 较差 | 较好 |
| 典型语言 | C | Java, Python, C++ |
二、类与对象的基本定义
2.1 定义一个最简单的类
class Dog:
pass
# 创建对象
my_dog = Dog()
print(type(my_dog)) # <class '__main__.Dog'>
2.2 为类添加属性和方法
class Dog:
# 类属性(所有实例共享)
species = "Canis familiaris"
# 实例方法
def bark(self):
print("汪汪!")
# 创建对象
dog1 = Dog()
dog2 = Dog()
# 访问类属性
print(dog1.species) # Canis familiaris
# 调用方法
dog1.bark() # 汪汪!
2.3 案例1:学生类
class Student:
"""学生类,包含姓名和成绩"""
school = "第一中学" # 类属性
def study(self):
print(f"{self.name} 正在学习")
def get_score(self):
return self.score
# 创建对象并动态添加属性
s1 = Student()
s1.name = "小明"
s1.score = 95
s1.study() # 小明 正在学习
print(f"{s1.name} 的成绩是 {s1.get_score()}") # 小明的成绩是 95
三、构造方法与析构方法
3.1 构造方法 __init__()
class Person:
def __init__(self, name, age):
print("构造方法被调用")
self.name = name
self.age = age
def introduce(self):
print(f"我叫{self.name},今年{self.age}岁")
# 创建对象时自动调用构造方法
p1 = Person("张三", 20) # 构造方法被调用
p1.introduce() # 我叫张三,今年20岁
3.2 构造方法的重载(Python不支持传统重载,但可设置默认值)
class Book:
def __init__(self, title, author="未知作者", price=0.0):
self.title = title
self.author = author
self.price = price
def info(self):
print(f"《{self.title}》- {self.author} - ¥{self.price}")
b1 = Book("Python入门")
b2 = Book("Python进阶", "李四")
b3 = Book("Python高级", "王五", 99.9)
b1.info() # 《Python入门》- 未知作者 - ¥0.0
b2.info() # 《Python进阶》- 李四 - ¥0.0
b3.info() # 《Python高级》- 王五 - ¥99.9
3.3 析构方法 __del__()
class Resource:
def __init__(self, name):
self.name = name
print(f"资源 {self.name} 已创建")
def __del__(self):
print(f"资源 {self.name} 已销毁")
# 创建对象
r1 = Resource("文件1") # 资源 文件1 已创建
r2 = Resource("文件2") # 资源 文件2 已创建
# 手动删除对象
del r1 # 资源 文件1 已销毁
print("程序结束")
# 程序结束
# 资源 文件2 已销毁(程序结束时自动调用)
3.4 案例2:银行账户类(构造方法+析构方法)
class BankAccount:
account_count = 0 # 统计账户数量
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
BankAccount.account_count += 1
print(f"欢迎 {owner},账户创建成功!当前余额:{balance}元")
def deposit(self, amount):
if amount > 0:
self.balance += amount
print(f"存入 {amount} 元,当前余额:{self.balance}元")
else:
print("存款金额必须大于0")
def withdraw(self, amount):
if amount > self.balance:
print(f"余额不足!当前余额:{self.balance}元")
elif amount <= 0:
print("取款金额必须大于0")
else:
self.balance -= amount
print(f"取出 {amount} 元,当前余额:{self.balance}元")
def __del__(self):
BankAccount.account_count -= 1
print(f"账户 {self.owner} 已注销,剩余账户数:{BankAccount.account_count}")
# 测试
acc1 = BankAccount("张三", 1000) # 欢迎 张三,账户创建成功!当前余额:1000元
acc1.deposit(500) # 存入 500 元,当前余额:1500元
acc1.withdraw(200) # 取出 200 元,当前余额:1300元
acc1.withdraw(2000) # 余额不足!当前余额:1300元
acc2 = BankAccount("李四") # 欢迎 李四,账户创建成功!当前余额:0元
del acc1 # 账户 张三 已注销,剩余账户数:1
四、self 参数详解
4.1 self 的本质
self 代表当前对象本身,类似于 Java/C++ 中的 this。
class Car:
def __init__(self, brand):
self.brand = brand
def show(self):
print(f"这辆车的品牌是 {self.brand}")
print(f"当前对象的id: {id(self)}")
c1 = Car("特斯拉")
c2 = Car("比亚迪")
print(f"c1的id: {id(c1)}") # c1的id: 140234567890
c1.show() # 这辆车的品牌是 特斯拉,当前对象的id: 140234567890
print(f"c2的id: {id(c2)}") # c2的id: 140234567999
c2.show() # 这辆车的品牌是 比亚迪,当前对象的id: 140234567999
4.2 self 可以改名吗?
可以,但不建议这样做,会降低代码可读性。
class Demo:
def method(this_object): # 把 self 改成 this_object
print(f"对象id: {id(this_object)}")
d = Demo()
d.method() # 正常运行
五、类变量与实例变量
5.1 基本区别
| 类型 | 定义位置 | 访问方式 | 归属 | 共享性 |
|---|---|---|---|---|
| 类变量 | 类中方法外 | 类名或对象名 | 类 | 所有实例共享 |
| 实例变量 | __init__() 中 |
只能用对象名 | 实例 | 各自独立 |
5.2 详细案例
class Employee:
company = "科技有限公司" # 类变量
total_employees = 0 # 类变量,统计员工总数
def __init__(self, name, salary):
self.name = name # 实例变量
self.salary = salary # 实例变量
Employee.total_employees += 1
def info(self):
print(f"姓名:{self.name},薪资:{self.salary},公司:{Employee.company}")
# 创建员工
e1 = Employee("张三", 8000)
e2 = Employee("李四", 9000)
# 访问类变量
print(Employee.company) # 科技有限公司
print(e1.company) # 科技有限公司(通过实例访问类变量)
print(e2.company) # 科技有限公司
# 修改类变量会影响所有实例
Employee.company = "新科技有限公司"
print(e1.company) # 新科技有限公司
print(e2.company) # 新科技有限公司
# 通过实例修改类变量?实际上创建了实例变量
e1.company = "个人工作室" # 这是创建了一个实例变量,不是修改类变量
print(e1.company) # 个人工作室(实例变量)
print(e2.company) # 新科技有限公司(类变量)
print(Employee.company) # 新科技有限公司(类变量)
# 员工总数
print(f"员工总数:{Employee.total_employees}") # 员工总数:2
5.3 案例3:商品库存系统
class Product:
category = "电子产品" # 类变量
total_products = 0 # 总商品数
def __init__(self, name, price, stock):
self.name = name # 实例变量
self.price = price # 实例变量
self.stock = stock # 实例变量(库存)
Product.total_products += 1
def sell(self, quantity):
if quantity <= self.stock:
self.stock -= quantity
print(f"售出 {quantity} 个 {self.name},剩余库存:{self.stock}")
else:
print(f"库存不足!当前库存:{self.stock}")
@classmethod
def get_total_products(cls):
return cls.total_products
# 创建商品
p1 = Product("手机", 2999, 50)
p2 = Product("平板", 1999, 30)
p3 = Product("耳机", 199, 100)
print(f"总商品种类:{Product.get_total_products()}") # 总商品种类:3
print(f"商品类别:{p1.category}") # 商品类别:电子产品
p1.sell(10) # 售出 10 个 手机,剩余库存:40
p2.sell(35) # 库存不足!当前库存:30
六、类方法与静态方法
6.1 类方法(@classmethod)
- 第一个参数是
cls(类本身) - 可以访问和修改类变量
- 可以通过类名或实例调用
class Temperature:
_base_freeze = 0 # 摄氏度的冰点
_base_boil = 100 # 摄氏度的沸点
@classmethod
def celsius_to_fahrenheit(cls, celsius):
"""摄氏转华氏"""
return celsius * 9/5 + 32
@classmethod
def fahrenheit_to_celsius(cls, fahrenheit):
"""华氏转摄氏"""
return (fahrenheit - 32) * 5/9
@classmethod
def get_water_state(cls, celsius):
"""根据温度返回水的状态"""
if celsius <= cls._base_freeze:
return "固态(冰)"
elif celsius >= cls._base_boil:
return "气态(水蒸气)"
else:
return "液态(水)"
# 直接通过类名调用类方法
print(Temperature.celsius_to_fahrenheit(25)) # 77.0
print(Temperature.fahrenheit_to_celsius(77)) # 25.0
print(Temperature.get_water_state(-5)) # 固态(冰)
print(Temperature.get_water_state(25)) # 液态(水)
print(Temperature.get_water_state(105)) # 气态(水蒸气)
6.2 静态方法(@staticmethod)
- 没有
self或cls参数 - 不能访问类变量或实例变量
- 类似于普通函数,但放在类中作为逻辑分组
class MathUtils:
"""数学工具类"""
@staticmethod
def is_prime(n):
"""判断是否为质数"""
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
@staticmethod
def factorial(n):
"""计算阶乘"""
if n == 0:
return 1
result = 1
for i in range(1, n + 1):
result *= i
return result
@staticmethod
def gcd(a, b):
"""计算最大公约数(欧几里得算法)"""
while b:
a, b = b, a % b
return a
# 调用静态方法
print(MathUtils.is_prime(17)) # True
print(MathUtils.is_prime(20)) # False
print(MathUtils.factorial(5)) # 120
print(MathUtils.gcd(48, 18)) # 6
6.3 三种方法的对比案例
class MyClass:
class_var = 10 # 类变量
def __init__(self, value):
self.instance_var = value # 实例变量
def instance_method(self):
"""实例方法:可以访问实例变量和类变量"""
print(f"实例方法:instance_var={self.instance_var}, class_var={self.class_var}")
@classmethod
def class_method(cls):
"""类方法:只能访问类变量,不能访问实例变量"""
print(f"类方法:class_var={cls.class_var}")
# print(cls.instance_var) # 报错!
@staticmethod
def static_method():
"""静态方法:不能访问实例变量和类变量"""
print("静态方法:这是一个独立的函数")
# print(class_var) # 报错!
# 使用示例
obj = MyClass(100)
obj.instance_method() # 实例方法:instance_var=100, class_var=10
obj.class_method() # 类方法:class_var=10
obj.static_method() # 静态方法:这是一个独立的函数
MyClass.class_method() # 也可以通过类名调用类方法
MyClass.static_method() # 也可以通过类名调用静态方法
七、封装与私有成员
7.1 私有属性和方法
Python 中使用双下划线 __ 前缀来表示私有成员。
class Bank:
def __init__(self, name, balance):
self.name = name
self.__balance = balance # 私有属性
self.__password = "123456" # 私有属性
def __secret_method(self): # 私有方法
return "这是内部方法"
def deposit(self, amount):
if amount > 0:
self.__balance += amount
print(f"存款成功,当前余额:{self.__balance}")
else:
print("存款金额无效")
def withdraw(self, amount, password):
if password != self.__password:
print("密码错误")
return
if amount > self.__balance:
print("余额不足")
else:
self.__balance -= amount
print(f"取款成功,当前余额:{self.__balance}")
def get_balance(self):
"""提供安全的访问接口"""
return self.__balance
# 测试
acc = Bank("张三", 1000)
acc.deposit(500) # 存款成功,当前余额:1500
# 直接访问私有属性会报错
# print(acc.__balance) # AttributeError
# 通过接口访问
print(acc.get_balance()) # 1500
# 通过 _类名__属性 可以强制访问(不推荐)
print(acc._Bank__balance) # 1500(伪私有)
7.2 使用 property 实现属性控制
class Student:
def __init__(self, name, score):
self.name = name
self.__score = score
@property
def score(self):
"""获取分数"""
return self.__score
@score.setter
def score(self, value):
"""设置分数,带验证"""
if 0 <= value <= 100:
self.__score = value
else:
raise ValueError("分数必须在0-100之间")
@score.deleter
def score(self):
"""删除分数"""
print("删除分数")
del self.__score
# 使用
s = Student("小明", 85)
print(s.score) # 85(像访问属性一样调用getter)
s.score = 95 # 调用setter
print(s.score) # 95
# s.score = 101 # ValueError: 分数必须在0-100之间
7.3 案例4:员工管理系统(封装实践)
class Employee:
def __init__(self, emp_id, name, salary):
self.__emp_id = emp_id # 私有:员工编号
self.__name = name # 私有:姓名
self.__salary = salary # 私有:薪资
self.__performance_bonus = 0 # 私有:绩效奖金
# getter 方法
def get_emp_id(self):
return self.__emp_id
def get_name(self):
return self.__name
def get_salary(self):
return self.__salary
# setter 方法(带验证)
def set_salary(self, salary):
if salary < 0:
raise ValueError("薪资不能为负数")
self.__salary = salary
def set_performance_bonus(self, bonus):
"""设置绩效奖金"""
if bonus < 0:
raise ValueError("奖金不能为负数")
self.__performance_bonus = bonus
def get_total_income(self):
"""计算总收入(薪资 + 奖金)"""
return self.__salary + self.__performance_bonus
def display_info(self):
"""显示员工信息"""
print(f"工号:{self.__emp_id}")
print(f"姓名:{self.__name}")
print(f"底薪:{self.__salary}")
print(f"绩效奖金:{self.__performance_bonus}")
print(f"总收入:{self.get_total_income()}")
print("-" * 30)
# 创建员工
emp1 = Employee("E001", "张三", 8000)
emp2 = Employee("E002", "李四", 9000)
emp1.set_performance_bonus(2000)
emp2.set_performance_bonus(1500)
emp1.display_info()
emp2.display_info()
八、继承
8.1 单继承
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
print(f"{self.name} 正在吃东西")
def sleep(self):
print(f"{self.name} 正在睡觉")
class Dog(Animal):
def bark(self):
print(f"{self.name} 汪汪叫")
def eat(self): # 重写方法
print(f"{self.name} 正在吃狗粮")
def fetch(self):
print(f"{self.name} 正在玩接球游戏")
class Cat(Animal):
def meow(self):
print(f"{self.name} 喵喵叫")
def climb(self):
print(f"{self.name} 正在爬树")
# 测试
dog = Dog("旺财", 3)
cat = Cat("咪咪", 2)
dog.eat() # 旺财 正在吃狗粮(调用了重写的方法)
dog.sleep() # 旺财 正在睡觉(继承自父类)
dog.bark() # 旺财 汪汪叫
dog.fetch() # 旺财 正在玩接球游戏
cat.eat() # 咪咪 正在吃东西(使用父类方法)
cat.meow() # 咪咪 喵喵叫
cat.climb() # 咪咪 正在爬树
8.2 多继承
class Flyable:
def fly(self):
print("正在飞行")
def takeoff(self):
print("正在起飞")
class Swimmable:
def swim(self):
print("正在游泳")
def dive(self):
print("正在潜水")
class Duck(Flyable, Swimmable):
def __init__(self, name):
self.name = name
def quack(self):
print(f"{self.name} 嘎嘎叫")
# 鸭子会飞会游泳
duck = Duck("唐老鸭")
duck.takeoff() # 正在起飞(继承自Flyable)
duck.fly() # 正在飞行
duck.dive() # 正在潜水(继承自Swimmable)
duck.swim() # 正在游泳
duck.quack() # 唐老鸭 嘎嘎叫
8.3 方法解析顺序(MRO)
class A:
def method(self):
print("A的方法")
class B(A):
def method(self):
print("B的方法")
class C(A):
def method(self):
print("C的方法")
class D(B, C):
pass
# 查看方法解析顺序
print(D.__mro__)
# (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
d = D()
d.method() # B的方法(按MRO顺序查找,先找到B)
8.4 super() 函数
class Vehicle:
def __init__(self, brand, model):
print("Vehicle __init__ 被调用")
self.brand = brand
self.model = model
def start(self):
print(f"{self.brand} {self.model} 启动")
class Car(Vehicle):
def __init__(self, brand, model, doors):
print("Car __init__ 被调用")
super().__init__(brand, model) # 调用父类构造方法
self.doors = doors
def start(self):
super().start() # 调用父类方法
print(f"系好安全带,准备出发")
class ElectricCar(Car):
def __init__(self, brand, model, doors, battery_capacity):
print("ElectricCar __init__ 被调用")
super().__init__(brand, model, doors)
self.battery_capacity = battery_capacity
def start(self):
super().start()
print(f"电池剩余:{self.battery_capacity}%,静音启动")
# 测试
tesla = ElectricCar("特斯拉", "Model 3", 4, 85)
tesla.start()
九、多态
9.1 多态的基本概念
class Animal:
def make_sound(self):
pass
class Dog(Animal):
def make_sound(self):
return "汪汪汪"
class Cat(Animal):
def make_sound(self):
return "喵喵喵"
class Cow(Animal):
def make_sound(self):
return "哞哞哞"
def animal_sound(animal):
"""多态函数:可以接收任何Animal的子类"""
print(animal.make_sound())
# 多态的体现
animals = [Dog(), Cat(), Cow()]
for animal in animals:
animal_sound(animal)
# 汪汪汪
# 喵喵喵
# 哞哞哞
9.2 鸭子类型(Python特有)
class Duck:
def quack(self):
print("鸭子嘎嘎叫")
class Person:
def quack(self):
print("人在学鸭子叫")
class Robot:
def quack(self):
print("机器人发出嘎嘎声")
def make_quack(obj):
"""只要有quack方法就可以调用(鸭子类型)"""
obj.quack()
# 不同类的对象,只要有相同的方法,就可以统一调用
make_quack(Duck()) # 鸭子嘎嘎叫
make_quack(Person()) # 人在学鸭子叫
make_quack(Robot()) # 机器人发出嘎嘎声
9.3 案例5:图形面积计算(多态实践)
from abc import ABC, abstractmethod
import math
class Shape(ABC):
"""抽象基类"""
@abstractmethod
def area(self):
"""计算面积(抽象方法)"""
pass
@abstractmethod
def perimeter(self):
"""计算周长(抽象方法)"""
pass
def describe(self):
"""普通方法"""
return f"这是一个{self.__class__.__name__},面积:{self.area():.2f},周长:{self.perimeter():.2f}"
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return math.pi * self.radius ** 2
def perimeter(self):
return 2 * math.pi * self.radius
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
class Triangle(Shape):
def __init__(self, a, b, c):
self.a = a
self.b = b
self.c = c
def area(self):
"""海伦公式"""
s = (self.a + self.b + self.c) / 2
return math.sqrt(s * (s - self.a) * (s - self.b) * (s - self.c))
def perimeter(self):
return self.a + self.b + self.c
# 多态演示
shapes = [
Circle(5),
Rectangle(4, 6),
Triangle(3, 4, 5)
]
for shape in shapes:
print(shape.describe())
# 这是一个Circle,面积:78.54,周长:31.42
# 这是一个Rectangle,面积:24.00,周长:20.00
# 这是一个Triangle,面积:6.00,周长:12.00
十、综合实战项目
项目1:动物园管理系统
class Animal:
"""动物基类"""
total_animals = 0
def __init__(self, name, age, species):
self.name = name
self.age = age
self.species = species
self.__health = 100 # 私有属性:健康值
Animal.total_animals += 1
def eat(self):
print(f"{self.name} 正在吃东西")
self.__health += 5
def make_sound(self):
pass
def get_health(self):
return self.__health
def set_health(self, value):
if 0 <= value <= 100:
self.__health = value
else:
print("健康值无效")
def info(self):
return f"名称:{self.name},年龄:{self.age},物种:{self.species},健康值:{self.__health}"
class Lion(Animal):
def __init__(self, name, age):
super().__init__(name, age, "狮子")
def make_sound(self):
print(f"{self.name} 发出 roar 的吼叫声!")
def hunt(self):
print(f"{self.name} 正在捕猎")
self.set_health(self.get_health() - 10)
class Elephant(Animal):
def __init__(self, name, age):
super().__init__(name, age, "大象")
def make_sound(self):
print(f"{self.name} 发出 trumpet 的声音!")
def spray_water(self):
print(f"{self.name} 正在喷水玩耍")
self.set_health(self.get_health() + 10)
class Monkey(Animal):
def __init__(self, name, age):
super().__init__(name, age, "猴子")
def make_sound(self):
print(f"{self.name} 发出 chatter 的声音!")
def climb(self):
print(f"{self.name} 正在爬树")
self.set_health(self.get_health() - 5)
class Zoo:
def __init__(self, name):
self.name = name
self.animals = []
def add_animal(self, animal):
self.animals.append(animal)
print(f"{animal.name} 已加入 {self.name}")
def show_all_animals(self):
print(f"\n{'='*40}")
print(f"{self.name} 的动物列表")
print(f"{'='*40}")
for animal in self.animals:
print(animal.info())
animal.make_sound()
print("-" * 30)
def feed_all(self):
print(f"\n正在给所有动物喂食...")
for animal in self.animals:
animal.eat()
def get_zoo_stats(self):
print(f"\n动物园统计:")
print(f"动物园名称:{self.name}")
print(f"动物总数:{len(self.animals)}")
print(f"总动物种类(历史):{Animal.total_animals}")
health_avg = sum(a.get_health() for a in self.animals) / len(self.animals)
print(f"平均健康值:{health_avg:.1f}")
# 测试动物园系统
if __name__ == "__main__":
# 创建动物园
zoo = Zoo("野生动物园")
# 添加动物
lion = Lion("辛巴", 5)
elephant = Elephant("多多", 8)
monkey = Monkey("悟空", 3)
zoo.add_animal(lion)
zoo.add_animal(elephant)
zoo.add_animal(monkey)
# 展示所有动物
zoo.show_all_animals()
# 喂食
zoo.feed_all()
# 展示统计
zoo.get_zoo_stats()
# 特殊行为
print(f"\n特殊行为演示:")
lion.hunt()
elephant.spray_water()
monkey.climb()
# 最终状态
zoo.show_all_animals()
项目2:猫狗大战游戏
import random
import time
class Pet:
"""宠物基类"""
def __init__(self, name, health, attack_power):
self.name = name
self.max_health = health
self.health = health
self.attack_power = attack_power
self.is_alive = True
def attack(self, target):
"""攻击目标"""
damage = random.randint(self.attack_power - 5, self.attack_power + 5)
damage = max(1, damage) # 至少造成1点伤害
target.take_damage(damage)
print(f"{self.name} 攻击了 {target.name},造成 {damage} 点伤害!")
time.sleep(0.5)
def take_damage(self, damage):
"""受到伤害"""
self.health -= damage
if self.health <= 0:
self.health = 0
self.is_alive = False
print(f"{self.name} 倒下了!")
def heal(self, amount):
"""治疗"""
self.health = min(self.max_health, self.health + amount)
print(f"{self.name} 恢复了 {amount} 生命值,当前生命:{self.health}")
def show_status(self):
"""显示状态"""
bar_length = 20
health_bar = "█" * int(self.health / self.max_health * bar_length)
health_bar += "░" * (bar_length - len(health_bar))
print(f"{self.name}: [{health_bar}] {self.health}/{self.max_health}")
def __str__(self):
return f"{self.name}({self.health}/{self.max_health})"
class Dog(Pet):
def __init__(self, name):
super().__init__(name, health=120, attack_power=25)
self.species = "狗"
def special_skill(self, target):
"""狗的技能:撕咬(造成额外伤害)"""
print(f"{self.name} 使用技能:疯狂撕咬!")
extra_damage = random.randint(15, 30)
target.take_damage(extra_damage)
print(f"额外造成 {extra_damage} 点伤害!")
time.sleep(0.5)
class Cat(Pet):
def __init__(self, name):
super().__init__(name, health=100, attack_power=30)
self.species = "猫"
def special_skill(self, target):
"""猫的技能:闪避反击(造成伤害并回血)"""
print(f"{self.name} 使用技能:闪避反击!")
# 闪避后反击
heal_amount = random.randint(10, 20)
self.heal(heal_amount)
counter_damage = random.randint(20, 35)
target.take_damage(counter_damage)
print(f"反击造成 {counter_damage} 点伤害!")
time.sleep(0.5)
class Game:
def __init__(self, player1, player2):
self.player1 = player1
self.player2 = player2
self.round = 0
def display_battle_info(self):
print("\n" + "="*50)
print(f"第 {self.round} 回合")
print("="*50)
self.player1.show_status()
self.player2.show_status()
print("-"*50)
def player_turn(self, attacker, defender):
"""玩家回合"""
print(f"\n{attacker.name} 的回合!")
print("1. 普通攻击")
print("2. 使用技能")
print("3. 治疗")
choice = input("请选择行动:")
if choice == "1":
attacker.attack(defender)
elif choice == "2":
if random.random() < 0.8: # 80%成功率
attacker.special_skill(defender)
else:
print(f"{attacker.name} 技能使用失败!")
elif choice == "3":
heal_amount = random.randint(15, 30)
attacker.heal(heal_amount)
else:
print("无效选择,进行普通攻击")
attacker.attack(defender)
def computer_turn(self, attacker, defender):
"""电脑回合"""
print(f"\n{attacker.name} 的回合!")
time.sleep(1)
action = random.choice(["attack", "skill", "heal"])
if action == "attack":
attacker.attack(defender)
elif action == "skill":
if random.random() < 0.7: # 70%成功率
attacker.special_skill(defender)
else:
print(f"{attacker.name} 技能使用失败!")
attacker.attack(defender)
else:
heal_amount = random.randint(15, 30)
attacker.heal(heal_amount)
def play_round(self):
"""执行一回合"""
self.round += 1
self.display_battle_info()
# 根据速度决定谁先攻击(这里简单用随机)
if random.random() < 0.5:
self.player_turn(self.player1, self.player2)
if self.player2.is_alive:
self.computer_turn(self.player2, self.player1)
else:
self.computer_turn(self.player2, self.player1)
if self.player1.is_alive:
self.player_turn(self.player1, self.player2)
def start(self):
"""开始游戏"""
print("\n" + "="*50)
print("🐱🐶 猫狗大战游戏开始! 🐱🐶")
print("="*50)
while self.player1.is_alive and self.player2.is_alive:
self.play_round()
time.sleep(1)
# 游戏结束
print("\n" + "="*50)
print("游戏结束!")
if self.player1.is_alive:
print(f"🎉 {self.player1.name} 获胜! 🎉")
else:
print(f"🎉 {self.player2.name} 获胜! 🎉")
print("="*50)
# 启动游戏
if __name__ == "__main__":
print("选择游戏模式:")
print("1. 单人模式(玩家 vs 电脑)")
print("2. 双人模式(玩家1 vs 玩家2)")
mode = input("请选择模式:")
if mode == "1":
# 单人模式
dog = Dog("旺财")
cat = Cat("咪咪")
print("请选择你的角色:")
print("1. 狗(高生命值)")
print("2. 猫(高攻击力)")
choice = input("请选择:")
if choice == "1":
player = dog
computer = cat
else:
player = cat
computer = dog
print(f"\n你选择了 {player.name}({player.species})")
print(f"电脑选择了 {computer.name}({computer.species})")
game = Game(player, computer)
game.start()
elif mode == "2":
# 双人模式
dog = Dog("旺财")
cat = Cat("咪咪")
print("\n玩家1选择:")
print("1. 狗")
print("2. 猫")
choice1 = input("请选择:")
player1 = dog if choice1 == "1" else cat
print("\n玩家2获得另一个角色")
player2 = cat if choice1 == "1" else dog
print(f"\n玩家1:{player1.name}({player1.species})")
print(f"玩家2:{player2.name}({player2.species})")
game = Game(player1, player2)
game.start()
十一、常见面试题与总结
面试题精选
Q1:Python中类变量和实例变量的区别?
A:类变量所有实例共享,通过类名修改会影响所有实例;实例变量每个实例独立。类变量在方法外定义,实例变量在 __init__ 中以 self. 定义。
Q2:self 是什么?可以不写吗?
A:self 代表实例本身,是实例方法的第一个参数。Python 要求必须写,但可以改成其他名字(不推荐)。
Q3:私有属性真的私有吗?
A:不是真正的私有,Python 只是进行了名称修饰(name mangling),变成 _类名__属性,外部仍然可以访问。
Q4:super() 的作用是什么?
A:用于调用父类的方法,特别是在多继承和方法重写时非常有用,可以避免直接使用父类名。
Q5:Python 支持方法重载吗?
A:不支持传统的方法重载(同名不同参数)。但可以通过默认参数、*args、**kwargs 实现类似效果。
项目小结
通过本文的学习,你应该掌握了:
| 知识点 | 核心内容 |
|---|---|
| 类与对象 | 类是模板,对象是实例 |
| 构造方法 | __init__ 初始化对象 |
| 析构方法 | __del__ 释放资源 |
| self 参数 | 代表实例本身 |
| 类变量 | 所有实例共享 |
| 实例变量 | 每个实例独立 |
| 类方法 | @classmethod,可访问类变量 |
| 静态方法 | @staticmethod,工具函数 |
| 封装 | 私有成员 __ + getter/setter |
| 继承 | 单继承、多继承、MRO |
| 方法重写 | 子类覆盖父类方法 |
| 多态 | 同一接口,不同实现 |
写在最后
面向对象编程是 Python 的核心特性之一,掌握它不仅能让你写出更优雅的代码,还能为后续学习设计模式、框架开发打下坚实基础。
建议学习路径:
- 先理解类和对象的概念
- 多写小案例练习(如银行账户、学生管理系统)
- 尝试用面向对象重构之前的面向过程代码
- 阅读优秀的 Python 开源项目源码
如果你觉得本文对你有帮助,欢迎点赞、收藏、转发支持我继续创作!
更多Python详细学习路径,私信回复“Python”即可领取
更多推荐

所有评论(0)