蓝图/模板/设计图
定义了有哪些属性和行为,但本身不占数据
例:class Dog — 定义"狗"这个概念
实例/实体/具体的东西
按类创建的具体数据,每个对象独立
例:Dog("旺财") — 一只具体的狗
# 定义类
class Dog:
"""狗类"""
# __init__ 是构造方法,创建对象时自动调用
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
# 实例方法
def bark(self):
return f"{self.name}说:汪汪!"
def info(self):
return f"名字:{self.name}, 年龄:{self.age}岁"
# 创建对象(实例化)
dog1 = Dog("旺财", 3)
dog2 = Dog("小黑", 5)
# 调用方法
print(dog1.bark()) # 旺财说:汪汪!
print(dog2.info()) # 名字:小黑, 年龄:5岁
# 访问属性
print(dog1.name) # 旺财
dog1.bark() 时,Python自动把dog1传给self。所以方法定义必须写self,但调用时不传。
class Dog:
# 类属性 — 所有对象共享
species = "犬科动物"
count = 0
def __init__(self, name):
self.name = name # 实例属性 — 每个对象独有
Dog.count += 1 # 每创建一个对象,计数+1
dog1 = Dog("旺财")
dog2 = Dog("小黑")
print(Dog.species) # 犬科动物 (类属性,通过类访问)
print(dog1.species) # 犬科动物 (也能通过对象访问)
print(dog1.name) # 旺财 (实例属性)
print(Dog.count) # 2 (创建了2个对象)
class BankAccount:
def __init__(self, owner, balance=0):
self.owner = owner
self.__balance = 0 # 私有属性:两个下划线开头
self.deposit(balance) # 通过方法初始化
def deposit(self, amount):
if amount <= 0:
raise ValueError("存款金额必须大于0")
self.__balance += amount
return self.__balance
def withdraw(self, amount):
if amount > self.__balance:
raise ValueError("余额不足")
self.__balance -= amount
return self.__balance
def get_balance(self):
return self.__balance
account = BankAccount("张三", 1000)
account.deposit(500)
print(account.get_balance()) # 1500
# account.__balance = 0 ← 不能直接改!(实际上是名称重整)
# account.__balance ← 不能直接访问!
# 只能通过deposit/withdraw来操作,保证安全
__ 开头的属性实际上会被"名称重整"为 _类名__属性名,所以理论上还是能访问 account._BankAccount__balance。但请尊重约定,不要从外部直接访问。
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def area(self):
"""面积 — 像属性一样访问,但每次动态计算"""
import math
return math.pi * self.radius ** 2
@property
def perimeter(self):
"""周长"""
import math
return 2 * math.pi * self.radius
c = Circle(5)
print(c.area) # 78.54... (不加括号!)
print(c.perimeter) # 31.42...
# 父类(基类)
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}在睡觉")
# 子类 — 继承Animal
class Dog(Animal):
def __init__(self, name, age, breed):
super().__init__(name, age) # 调用父类的__init__
self.breed = breed # 子类新增属性
def bark(self): # 子类新增方法
print(f"{self.name}:汪汪!")
def info(self): # 子类可以覆盖父类方法
return f"{self.breed}犬{name}, {self.age}岁"
class Cat(Animal):
def meow(self):
print(f"{self.name}:喵~")
# 使用
dog = Dog("旺财", 3, "金毛")
cat = Cat("咪咪", 2)
dog.eat() # 旺财在吃东西 (继承自Animal)
dog.sleep() # 旺财在睡觉 (继承自Animal)
dog.bark() # 旺财:汪汪! (Dog特有)
cat.meow() # 咪咪:喵~ (Cat特有)
print(dog.info()) # 金毛犬旺财, 3岁
class Vehicle:
def __init__(self, brand):
self.brand = brand
print("Vehicle初始化")
class Car(Vehicle):
def __init__(self, brand, model):
super().__init__(brand) # 先初始化父类
self.model = model
print("Car初始化")
car = Car("Toyota", "Camry")
# Vehicle初始化
# Car初始化
class Flyable:
def fly(self):
print("飞行中...")
class Swimmable:
def swim(self):
print("游泳中...")
# 多重继承:同时获得两个父类的能力
class Duck(Flyable, Swimmable):
def quack(self):
print("嘎嘎!")
duck = Duck()
duck.fly() # 飞行中...
duck.swim() # 游泳中...
duck.quack() # 嘎嘎!
class Dog:
def speak(self):
return "汪汪"
class Cat:
def speak(self):
return "喵喵"
class Duck:
def speak(self):
return "嘎嘎"
# 多态:同一个函数,处理不同类型
def animal_sound(animal):
print(animal.speak()) # 不关心是什么动物,只要有speak方法
animals = [Dog(), Cat(), Duck()]
for a in animals:
animal_sound(a)
# 汪汪
# 喵喵
# 嘎嘎
speak() 方法的对象都能传给 animal_sound()。
| 方法 | 触发时机 | 用途 |
|---|---|---|
__init__ | 创建对象时 | 初始化 |
__str__ | print(对象) / str(对象) | 用户友好的显示 |
__repr__ | repr(对象) / 直接显示 | 开发者友好的显示 |
__len__ | len(对象) | 支持长度 |
__eq__ | 对象 == 对象 | 支持相等比较 |
__lt__ | 对象 < 对象 | 支持大小比较 |
__add__ | 对象 + 对象 | 支持加法 |
__getitem__ | 对象[key] | 支持索引 |
__iter__ | for x in 对象 | 支持迭代 |
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
def __str__(self):
# print(student) 时显示
return f"{self.name}({self.score}分)"
def __repr__(self):
# 直接输入变量名时显示
return f"Student('{self.name}', {self.score})"
def __eq__(self, other):
# student1 == student2 时调用
return self.score == other.score
def __lt__(self, other):
# student1 < student2 时调用(按分数比较)
return self.score < other.score
def __add__(self, other):
# student1 + student2 → 合并分数
return self.score + other.score
s1 = Student("张三", 85)
s2 = Student("李四", 92)
print(s1) # 张三(85分) — __str__
print(s1 == s2) # False — __eq__
print(s1 < s2) # True — __lt__
print(s1 + s2) # 177 — __add__
# 因为定义了__lt__,所以可以排序
students = [Student("王五", 78), Student("赵六", 95), s1, s2]
students.sort()
for s in students:
print(s) # 按分数从低到高
class MathHelper:
pi = 3.14159
# 实例方法 — 操作实例(self)
def instance_method(self):
return "我是实例方法"
# 类方法 — 操作类(cls)
@classmethod
def circle_area(cls, radius):
return cls.pi * radius ** 2 # 用cls访问类属性
# 静态方法 — 不需要self也不需要cls
@staticmethod
def is_positive(n):
return n > 0
# 类方法通过类调用
print(MathHelper.circle_area(5)) # 78.54...
# 静态方法通过类调用
print(MathHelper.is_positive(10)) # True
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_str):
"""从字符串 '2026-01-15' 创建Date对象"""
year, month, day = map(int, date_str.split("-"))
return cls(year, month, day) # cls就是Date
@classmethod
def today(cls):
"""创建今天的Date对象"""
import datetime
t = datetime.date.today()
return cls(t.year, t.month, t.day)
d1 = Date(2026, 1, 15) # 传统方式
d2 = Date.from_string("2026-01-15") # 工厂方法
d3 = Date.today() # 工厂方法
class Book:
"""图书类"""
def __init__(self, title, author, isbn):
self.title = title
self.author = author
self.isbn = isbn
self.is_borrowed = False
def __str__(self):
status = "已借出" if self.is_borrowed else "可借"
return f"《{self.title}》-{self.author} [{status}]"
class Library:
"""图书馆类"""
def __init__(self, name):
self.name = name
self.books = []
def add_book(self, book):
self.books.append(book)
print(f"已添加: {book}")
def borrow(self, title):
for book in self.books:
if book.title == title and not book.is_borrowed:
book.is_borrowed = True
print(f"借出成功: {book}")
return book
print(f"《{title}》不可借")
return None
def return_book(self, title):
for book in self.books:
if book.title == title and book.is_borrowed:
book.is_borrowed = False
print(f"归还成功: {book}")
return
print(f"《{title}》不在借出列表")
def list_books(self):
print(f"\n=== {self.name} 图书列表 ===")
for book in self.books:
print(book)
# 使用
lib = Library("城市图书馆")
lib.add_book(Book("Python入门", "Guido", "001"))
lib.add_book(Book("算法导论", "CLRS", "002"))
lib.list_books()
lib.borrow("Python入门")
lib.list_books()
lib.return_book("Python入门")
创建Rectangle类,有width和height属性,方法:area()计算面积、perimeter()计算周长、is_square()判断是否正方形。用@property装饰area和perimeter。
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
@property
def area(self):
return self.width * self.height
@property
def perimeter(self):
return 2 * (self.width + self.height)
def is_square(self):
return self.width == self.height
r = Rectangle(5, 3)
print(f"面积: {r.area}, 周长: {r.perimeter}, 正方形: {r.is_square()}")
# 面积: 15, 周长: 16, 正方形: False
s = Rectangle(4, 4)
print(f"面积: {s.area}, 正方形: {s.is_square()}")
# 面积: 16, 正方形: True
创建Employee基类(name, salary),Manager子类(额外有bonus,总工资=salary+bonus),Developer子类(额外有programming_language)。都有get_info()方法,但输出不同。
class Employee:
def __init__(self, name, salary):
self.name = name
self.salary = salary
def get_info(self):
return f"员工: {self.name}, 工资: {self.salary}"
class Manager(Employee):
def __init__(self, name, salary, bonus):
super().__init__(name, salary)
self.bonus = bonus
def get_info(self):
total = self.salary + self.bonus
return f"经理: {self.name}, 基本工资: {self.salary}, 奖金: {self.bonus}, 总计: {total}"
class Developer(Employee):
def __init__(self, name, salary, language):
super().__init__(name, salary)
self.language = language
def get_info(self):
return f"开发: {self.name}, 工资: {self.salary}, 语言: {self.language}"
emps = [
Manager("张三", 20000, 5000),
Developer("李四", 15000, "Python"),
Employee("王五", 8000),
]
for e in emps:
print(e.get_info())
创建Product类(name, price)和ShoppingCart类。购物车有add()、remove()、total()方法。用__len__支持len(cart),用__str__支持print(cart)。
class Product:
def __init__(self, name, price):
self.name = name
self.price = price
def __str__(self):
return f"{self.name}(¥{self.price})"
class ShoppingCart:
def __init__(self):
self.items = []
def add(self, product, qty=1):
self.items.append({"product": product, "qty": qty})
def remove(self, product_name):
self.items = [i for i in self.items if i["product"].name != product_name]
def total(self):
return sum(i["product"].price * i["qty"] for i in self.items)
def __len__(self):
return len(self.items)
def __str__(self):
lines = [f" {i['product']} x{i['qty']}" for i in self.items]
return "购物车:\n" + "\n".join(lines) + f"\n总计: ¥{self.total()}"
cart = ShoppingCart()
cart.add(Product("苹果", 5), 3)
cart.add(Product("面包", 10), 2)
cart.add(Product("牛奶", 8), 1)
print(cart)
print(f"商品种类: {len(cart)}")
cart.remove("面包")
print(cart)