
文章目录
- 📖 开篇导读
- 🎯 学习目标
- 📚 知识点理论精讲
-
- 一、类属性 vs 实例属性
-
- 1.1 定义与访问
- 1.2 属性查找机制
- 1.3 修改类属性
- 1.4 可变类属性的陷阱
- 二、类方法(`@classmethod`)
-
- 2.1 定义与调用
- 2.2 应用场景
- 2.3 类方法与实例方法的区别
- 三、静态方法(`@staticmethod`)
-
- 3.1 定义与调用
- 3.2 应用场景
- 3.3 静态方法与类方法的区别
- 四、`@property` 属性访问
- 五、最佳实践总结
- 💻 代码案例实操
-
- 案例1:类属性实现计数器
- 案例2:类方法实现工厂模式
- 案例3:静态方法组织工具函数
- 案例4:类属性与实例属性混合使用
- 案例5:`@property` vs 直接属性
- 案例6:综合应用——配置管理器
- 案例7:宠物商店——综合运用
- ⚠️ 易错点避坑总结
- 📝 课后实战练习题
-
-
- 第1题:类属性计数器
- 第2题:工厂类方法
- 第3题:静态方法工具类
- 第4题:类属性与实例属性综合
- 第5题:`@property`实现只读和验证
- 第6题:综合设计——图书馆
- 第7题:单例配置类(扩展)
-
- 🧠 知识点思维导图总结
- 🔜 下节课预告
-
- 第27课:魔术方法大全:__init__/__str__/__repr__等常用魔术方法实战
- 🔗《50节课 Python 从入门到精通》系列课程导航
📖 开篇导读
在前几节课中,我们学习了面向对象的三大特性:封装、继承、多态。你能够定义类、创建对象、使用继承和多态来设计灵活的系统。但是,你是否注意到:有些属性应该属于类本身,而不是某个具体对象?有些方法不需要访问实例数据,只为了组织代码?Python为我们提供了类属性、实例属性、类方法、静态方法这些不同的工具,各自有不同的适用场景。
💡 工作场景:在真实项目中:
- 类属性:适合存储所有实例共享的数据,如配置参数、计数器、默认值。
- 实例属性:每个对象独有的数据,如用户姓名、订单金额。
- 类方法:常用于工厂模式(创建特定配置的实例)、操作类变量、实现多态构造器。
- 静态方法:纯工具函数,与类相关但不需要访问实例或类,放在类命名空间下便于组织。
本课将深入对比这四者的本质和最佳实践,通过大量实战案例,让你清楚何时使用哪种特性。学完本课,你写出的类将更加清晰、高效、符合Python设计哲学。
🎯 学习目标
| 1️⃣ | 深入理解类属性与实例属性的区别及访问机制 | 避免覆盖导致意外 |
| 2️⃣ | 掌握类方法的用途:工厂方法、操作类状态 | 写出灵活API |
| 3️⃣ | 掌握静态方法的用途:工具函数归类 | 组织代码逻辑 |
| 4️⃣ | 掌握@property、@classmethod、@staticmethod装饰器区别 | 选择正确方法类型 |
| 5️⃣ | 理解属性查找顺序(实例→类→父类)和修改类属性的影响 | 面试高频 |
| 6️⃣ | 实战:计数器、配置类、工厂模式 | 提升设计能力 |
🔥 面试考点:“类属性和实例属性的区别?”“如何修改类属性?”“类方法和静态方法的区别?”“@property的作用?”
📚 知识点理论精讲
一、类属性 vs 实例属性
1.1 定义与访问
- 实例属性:属于每个对象个体,在__init__中使用self.属性定义,不同对象的值独立。
- 类属性:属于类本身,定义在类内部但不在任何方法内,所有实例共享同一个值。
class Student:
school = "第一中学" # 类属性
total_students = 0 # 类属性,跟踪学生总数
def __init__(self, name):
self.name = name # 实例属性
Student.total_students += 1
s1 = Student("张三")
s2 = Student("李四")
print(s1.school) # 第一中学(通过实例访问类属性)
print(Student.school) # 第一中学(通过类访问)
print(Student.total_students) # 2
1.2 属性查找机制
当通过实例访问属性时,Python先查找实例的__dict__,如果没有则查找类的__dict__,再沿着继承链向上。
class A:
x = 10
a = A()
print(a.x) # 10(实例没有x,从类找到)
a.x = 20 # 创建实例属性x,覆盖类属性
print(a.x) # 20
print(A.x) # 10(类属性未变)
1.3 修改类属性
- 通过类名修改会影响所有实例(除非实例自己覆盖了该属性)。
- 通过实例修改类属性:实际上会创建同名的实例属性,不会影响类属性。
Student.school = "第二中学" # 修改类属性
print(s1.school) # 第二中学
s1.school = "第三中学" # 创建实例属性
print(s1.school) # 第三中学
print(s2.school) # 第二中学(类属性值)
💡 最佳实践:访问类属性时推荐使用类名.属性,而不是self.属性,避免与实例属性混淆。修改类属性必须通过类名。
1.4 可变类属性的陷阱
如果类属性是可变对象(如列表、字典),通过实例修改其内容会影响所有实例。
class Employee:
skills = [] # 类属性(可变)
e1 = Employee()
e2 = Employee()
e1.skills.append("Python")
print(e2.skills) # ['Python'],被影响了!
# 解决方案:不在类属性中使用可变对象,或者在实例中独立创建
class EmployeeFixed:
def __init__(self):
self.skills = [] # 实例属性
二、类方法(@classmethod)
2.1 定义与调用
类方法的第一个参数是cls(类本身),通过@classmethod装饰。可以通过类或实例调用。
class Circle:
pi = 3.14159
@classmethod
def from_diameter(cls, diameter):
radius = diameter / 2
return cls(radius) # 等价于 Circle(radius)
def __init__(self, radius):
self.radius = radius
def area(self):
return self.pi * self.radius ** 2
c = Circle.from_diameter(10)
print(c.area())
2.2 应用场景
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, date_str):
year, month, day = map(int, date_str.split('-'))
return cls(year, month, day)
@classmethod
def today(cls):
import datetime
t = datetime.date.today()
return cls(t.year, t.month, t.day)
2.3 类方法与实例方法的区别
| 第一个参数 | self(实例) | cls(类) |
| 可以访问实例属性 | 是 | 否 |
| 可以访问类属性 | 是(通过self.__class__) | 是 |
| 可以被子类覆盖 | 是 | 是(cls会指向子类) |
| 调用方式 | 实例调用 | 类或实例调用 |
三、静态方法(@staticmethod)
3.1 定义与调用
静态方法没有默认的第一个参数,既不需要self也不需要cls,类似于普通函数,但放在类的命名空间中。
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def is_even(n):
return n % 2 == 0
print(MathUtils.add(3, 5)) # 8
print(MathUtils.is_even(4)) # True
3.2 应用场景
- 工具函数:逻辑上属于该类相关,但不依赖实例或类状态。
- 代码组织:将相关函数放在类内部,提升可读性。
- 避免全局函数:减少命名空间污染。
3.3 静态方法与类方法的区别
| 第一个参数 | cls | 无 |
| 可以访问类属性 | 是 | 否(需通过类名显式访问) |
| 可以被子类覆盖 | 是(通过cls动态) | 是(但无法获得子类信息) |
| 调用方式 | Class.method() | Class.method() |
| 典型用途 | 工厂、操作类状态 | 工具函数 |
四、@property 属性访问
虽然@property已在第23课介绍,但这里着重它在类设计中的作用:将方法伪装成属性,实现更好的封装。
class Temperature:
def __init__(self, celsius):
self._celsius = celsius
@property
def celsius(self):
return self._celsius
@celsius.setter
def celsius(self, value):
if value < –273.15:
raise ValueError("温度不能低于绝对零度")
self._celsius = value
@property
def fahrenheit(self):
return self.celsius * 9/5 + 32
五、最佳实践总结
| 每个对象独有的数据 | 实例属性 |
| 所有对象共享的数据(如配置、计数器) | 类属性 |
| 需要多种方式创建实例 | 类方法(工厂) |
| 需要访问或修改类状态(如类级别的计数器) | 类方法 |
| 与类相关但独立于实例的工具函数 | 静态方法 |
| 控制属性访问(验证、计算、只读) | @property |
💻 代码案例实操
案例1:类属性实现计数器
"""
counter_using_class_attr.py
使用类属性统计实例个数
"""
class Product:
count = 0 # 类属性,记录总产品数
def __init__(self, name, price):
self.name = name
self.price = price
Product.count += 1
self.id = Product.count
@classmethod
def get_count(cls):
return cls.count
@classmethod
def reset_count(cls):
cls.count = 0
print("计数器已重置")
p1 = Product("手机", 2999)
p2 = Product("电脑", 5999)
p3 = Product("耳机", 199)
print(f"总产品数: {Product.get_count()}") # 3
print(f"p3的id: {p3.id}") # 3
Product.reset_count()
p4 = Product("键盘", 399)
print(f"重置后总数: {Product.get_count()}") # 1
案例2:类方法实现工厂模式
"""
factory_classmethod.py
使用类方法创建不同配置的对象
"""
import datetime
class User:
def __init__(self, username, email, registered_at):
self.username = username
self.email = email
self.registered_at = registered_at
@classmethod
def from_dict(cls, data):
"""从字典创建"""
return cls(
data['username'],
data['email'],
datetime.datetime.strptime(data['registered_at'], "%Y-%m-%d")
)
@classmethod
def create_guest(cls):
"""创建访客用户"""
return cls("guest", "guest@example.com", datetime.datetime.now())
@classmethod
def create_system_user(cls):
return cls("system", "system@localhost", datetime.datetime.now())
def info(self):
print(f"User: {self.username}, email={self.email}, registered={self.registered_at.date()}")
# 使用
guest = User.create_guest()
guest.info()
data = {"username": "alice", "email": "alice@example.com", "registered_at": "2025-01-15"}
alice = User.from_dict(data)
alice.info()
案例3:静态方法组织工具函数
"""
static_method_tools.py
使用静态方法提供数学和字符串工具
"""
class StringUtils:
@staticmethod
def is_palindrome(s):
s = ''.join(c.lower() for c in s if c.isalnum())
return s == s[::–1]
@staticmethod
def camel_to_snake(name):
import re
s1 = re.sub('(.)([A-Z][a-z]+)', r'\\1_\\2', name)
return re.sub('([a-z0-9])([A-Z])', r'\\1_\\2', s1).lower()
@staticmethod
def snake_to_camel(name):
components = name.split('_')
return components[0] + ''.join(x.title() for x in components[1:])
class FileUtils:
@staticmethod
def get_extension(filename):
if '.' not in filename:
return ''
return filename.rsplit('.', 1)[–1].lower()
@staticmethod
def is_image(filename):
ext = FileUtils.get_extension(filename)
return ext in ('jpg', 'jpeg', 'png', 'gif', 'bmp')
print(StringUtils.is_palindrome("A man, a plan, a canal: Panama")) # True
print(StringUtils.camel_to_snake("helloWorldPython")) # hello_world_python
print(FileUtils.get_extension("photo.jpg")) # jpg
案例4:类属性与实例属性混合使用
"""
mixed_attributes.py
演示类属性和实例属性的正确使用
"""
class Bank:
interest_rate = 0.02 # 类属性,基准利率
bank_name = "Python Bank"
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
self.transactions = [] # 实例属性
def add_interest(self):
# 可以使用 self.interest_rate,但更推荐 Bank.interest_rate 或 self.__class__.interest_rate
interest = self.balance * self.__class__.interest_rate
self.balance += interest
self.transactions.append(f"增加利息 {interest}")
@classmethod
def set_interest_rate(cls, rate):
if rate < 0:
raise ValueError("利率不能为负")
cls.interest_rate = rate
print(f"基准利率已修改为 {rate}")
def info(self):
print(f"{self.bank_name} – 账户: {self.owner}, 余额: {self.balance}")
# 所有实例共享基准利率
acc1 = Bank("张三", 1000)
acc2 = Bank("李四", 2000)
acc1.add_interest()
acc2.add_interest()
print(acc1.balance, acc2.balance) # 1020.0, 2040.0
# 修改类属性后,新创建的实例使用新利率,已有实例在下次add_interest时使用新利率
Bank.set_interest_rate(0.03)
acc3 = Bank("王五", 3000)
acc1.add_interest() # 使用新的0.03
print(acc1.balance) # 1020 + 1020*0.03 = 1050.6
案例5:@property vs 直接属性
"""
property_design.py
演示使用property实现更好的封装
"""
class Student:
def __init__(self, name, score):
self.name = name
self._score = score # 受保护属性
@property
def score(self):
"""成绩,范围0-100"""
return self._score
@score.setter
def score(self, value):
if not isinstance(value, (int, float)):
raise TypeError("成绩必须是数字")
if not 0 <= value <= 100:
raise ValueError("成绩必须在0-100之间")
self._score = value
@property
def grade(self):
"""等级(只读)"""
if self._score >= 90:
return "A"
elif self._score >= 80:
return "B"
elif self._score >= 70:
return "C"
elif self._score >= 60:
return "D"
else:
return "F"
@property
def is_pass(self):
return self._score >= 60
s = Student("张三", 85)
print(s.score) # 85
s.score = 95
print(s.grade) # A
# s.grade = "B" # AttributeError: can't set attribute
print(s.is_pass) # True
案例6:综合应用——配置管理器
"""
config_manager.py
使用类属性、类方法、静态方法实现配置管理
"""
import json
import os
class Config:
# 类属性:默认配置
default_config = {
"host": "localhost",
"port": 8080,
"debug": True,
"log_level": "INFO"
}
_instance = None # 单例模式
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
cls._instance._config = cls.default_config.copy()
return cls._instance
@classmethod
def load_from_file(cls, filepath):
"""类方法:从文件加载配置"""
if not os.path.exists(filepath):
print(f"配置文件 {filepath} 不存在,使用默认配置")
return cls()
with open(filepath, 'r') as f:
data = json.load(f)
instance = cls()
instance._config.update(data)
return instance
@classmethod
def set_default(cls, key, value):
"""类方法:修改默认配置"""
cls.default_config[key] = value
@staticmethod
def is_valid_port(port):
"""静态方法:验证端口是否合法"""
return isinstance(port, int) and 1 <= port <= 65535
def get(self, key, default=None):
return self._config.get(key, default)
def set(self, key, value):
self._config[key] = value
def save_to_file(self, filepath):
with open(filepath, 'w') as f:
json.dump(self._config, f, indent=4)
# 使用
Config.set_default("host", "0.0.0.0")
# 从文件加载(假设有config.json)
config = Config.load_from_file("config.json")
print(config.get("host"))
config.set("port", 9090)
print(Config.is_valid_port(9090)) # True
config.save_to_file("config_out.json")
案例7:宠物商店——综合运用
"""
pet_shop.py
综合运用类属性、实例属性、类方法、静态方法
"""
class Pet:
# 类属性
species_count = {} # 统计每种宠物的数量
total_pets = 0
def __init__(self, name, species, price):
self.name = name
self.species = species
self.price = price
self.id = Pet.total_pets + 1
Pet.total_pets += 1
Pet.species_count[species] = Pet.species_count.get(species, 0) + 1
@classmethod
def create_dog(cls, name, price):
"""类方法:创建狗(工厂)"""
return cls(name, "dog", price)
@classmethod
def create_cat(cls, name, price):
return cls(name, "cat", price)
@classmethod
def get_species_report(cls):
"""类方法:获取统计报告"""
report = "宠物库存统计:\\n"
for species, count in cls.species_count.items():
report += f" {species}: {count}只\\n"
report += f"总计: {cls.total_pets}只"
return report
@staticmethod
def validate_price(price):
"""静态方法:价格验证"""
return isinstance(price, (int, float)) and price > 0
def __str__(self):
return f"Pet(id={self.id}, name={self.name}, species={self.species}, price={self.price})"
class Shop:
def __init__(self, name):
self.name = name
self.inventory = []
def add_pet(self, pet):
if not Pet.validate_price(pet.price):
print(f"价格无效,无法添加 {pet.name}")
return
self.inventory.append(pet)
print(f"添加宠物: {pet}")
def list_pets(self):
for pet in self.inventory:
print(pet)
def total_value(self):
return sum(pet.price for pet in self.inventory)
# 使用
dog1 = Pet.create_dog("旺财", 500)
dog2 = Pet.create_dog("阿福", 600)
cat1 = Pet.create_cat("咪咪", 400)
hamster = Pet("小仓", "hamster", 50)
print(Pet.get_species_report())
shop = Shop("快乐宠物店")
shop.add_pet(dog1)
shop.add_pet(dog2)
shop.add_pet(cat1)
shop.add_pet(hamster)
shop.list_pets()
print(f"总价值: {shop.total_value()}")
⚠️ 易错点避坑总结
| 1 | 通过实例修改类属性 | 实际创建了实例属性,类属性未变 | 使用类名修改类属性 |
| 2 | 类属性使用可变对象,并通过实例修改其内容 | 所有实例共享改变,可能产生意外 | 类属性中避免使用可变对象,或在实例中独立创建 |
| 3 | 在实例方法中通过self访问类属性,然后子类覆盖类属性时,引用混乱 | 子类实例可能使用父类的类属性值 | 推荐使用self.__class__.attr或直接ClassName.attr |
| 4 | 类方法中试图访问实例属性 | 错误或不可预知行为 | 类方法只能访问类变量和调用其他类方法/静态方法 |
| 5 | 静态方法中需要访问类变量时,使用cls | 静态方法没有cls | 改用类方法 |
| 6 | 忘记在静态方法或类方法中使用装饰器 | 方法会成为普通实例方法,调用时参数错误 | 始终加上@staticmethod或@classmethod |
| 7 | 在__init__中定义类属性(使用self.xxx = …) | 成为实例属性,不是类属性 | 类属性定义在类体顶层 |
| 8 | @property的setter中误用self.xxx = value导致递归 | 无限递归,栈溢出 | setter中操作私有变量,如self._xxx |
| 9 | 子类中重写类方法时,忘记处理cls参数 | 调用时参数不匹配 | 保持第一个参数为cls |
| 10 | 混淆静态方法和类方法的应用场景,导致设计不合理 | 代码可读性差 | 需要操作类状态用类方法,纯工具用静态方法 |
📝 课后实战练习题
第1题:类属性计数器
定义一个Vehicle类,类属性count统计创建的实例数量。每创建一个实例,count加1,提供类方法get_count()返回数量。创建多个不同子类(Car、Bike)实例,验证计数是否正确。
第2题:工厂类方法
定义Shape类,有子类Circle和Rectangle。在Shape中添加类方法create(shape_type, **kwargs),根据shape_type返回对应的实例。例如Shape.create("circle", radius=5)返回Circle实例。
第3题:静态方法工具类
编写一个Validator类,包含以下静态方法:
- is_email(email):简单验证邮箱格式(包含@和点)
- is_phone(phone):验证手机号(11位数字,以1开头)
- is_username(username):字母数字下划线,长度3-20 使用这些方法验证用户输入。
第4题:类属性与实例属性综合
设计一个BankAccount类,类属性annual_interest_rate表示年利率,实例属性balance。提供实例方法add_interest()增加利息。类方法set_interest_rate(rate)修改利率。创建多个账户,存入不同金额,调用add_interest后观察余额,再次修改利率后,新利率是否影响旧账户的下一次计息?
第5题:@property实现只读和验证
定义Product类,属性name(字符串,非空)、price(正数)、discount(0到1)。使用@property对price设置验证,discount设置验证,同时提供只读属性final_price(折扣后价格)。实现__str__方法。
第6题:综合设计——图书馆
设计Book类,类属性total_books记录总藏书量。实例属性title、author、isbn、borrowed(是否借出)。提供类方法find_by_author(author)返回该作者的所有书籍列表。静态方法is_valid_isbn(isbn)验证ISBN格式(简单:13位数字)。创建几本书,测试。
第7题:单例配置类(扩展)
修改案例6,使得Config类为真正的单例:任何方式获取的实例都是同一个。验证load_from_file和直接创建返回同一对象。添加__new__控制实例个数。
🧠 知识点思维导图总结
#mermaid-svg-fXuQZQXu3zWyIzCf{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fXuQZQXu3zWyIzCf .error-icon{fill:#552222;}#mermaid-svg-fXuQZQXu3zWyIzCf .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fXuQZQXu3zWyIzCf .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fXuQZQXu3zWyIzCf .marker.cross{stroke:#333333;}#mermaid-svg-fXuQZQXu3zWyIzCf svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fXuQZQXu3zWyIzCf p{margin:0;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge{stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 path{fill:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 text{fill:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon–1{font-size:40px;color:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge–1{stroke:hsl(240, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth–1{stroke-width:17;}#mermaid-svg-fXuQZQXu3zWyIzCf .section–1 line{stroke:hsl(60, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 path{fill:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-0{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-0{stroke:hsl(60, 100%, 73.5294117647%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-0{stroke-width:14;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-0 line{stroke:hsl(240, 100%, 83.5294117647%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 path{fill:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-1{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-1{stroke:hsl(80, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-1{stroke-width:11;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-1 line{stroke:hsl(260, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 path{fill:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 text{fill:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-2{font-size:40px;color:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-2{stroke:hsl(270, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-2{stroke-width:8;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 line{stroke:hsl(90, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 path{fill:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-3{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-3{stroke:hsl(300, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-3{stroke-width:5;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-3 line{stroke:hsl(120, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 path{fill:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-4{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-4{stroke:hsl(330, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-4{stroke-width:2;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-4 line{stroke:hsl(150, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 path{fill:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-5{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-5{stroke:hsl(0, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-5{stroke-width:-1;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-5 line{stroke:hsl(180, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 path{fill:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-6{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-6{stroke:hsl(30, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-6{stroke-width:-4;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-6 line{stroke:hsl(210, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 path{fill:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-7{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-7{stroke:hsl(90, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-7{stroke-width:-7;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-7 line{stroke:hsl(270, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 path{fill:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-8{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-8{stroke:hsl(150, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-8{stroke-width:-10;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-8 line{stroke:hsl(330, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 path{fill:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-9{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-9{stroke:hsl(180, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-9{stroke-width:-13;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-9 line{stroke:hsl(0, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 polygon,#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 path{fill:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 text{fill:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .node-icon-10{font-size:40px;color:black;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-edge-10{stroke:hsl(210, 100%, 76.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .edge-depth-10{stroke-width:-16;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-10 line{stroke:hsl(30, 100%, 86.2745098039%);stroke-width:3;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled circle,#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:lightgray;}#mermaid-svg-fXuQZQXu3zWyIzCf .disabled text{fill:#efefef;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-root rect,#mermaid-svg-fXuQZQXu3zWyIzCf .section-root path,#mermaid-svg-fXuQZQXu3zWyIzCf .section-root circle,#mermaid-svg-fXuQZQXu3zWyIzCf .section-root polygon{fill:hsl(240, 100%, 46.2745098039%);}#mermaid-svg-fXuQZQXu3zWyIzCf .section-root text{fill:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-root span{color:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .section-2 span{color:#ffffff;}#mermaid-svg-fXuQZQXu3zWyIzCf .icon-container{height:100%;display:flex;justify-content:center;align-items:center;}#mermaid-svg-fXuQZQXu3zWyIzCf .edge{fill:none;}#mermaid-svg-fXuQZQXu3zWyIzCf .mindmap-node-label{dy:1em;alignment-baseline:middle;text-anchor:middle;dominant-baseline:middle;text-align:center;}#mermaid-svg-fXuQZQXu3zWyIzCf :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
第26课:类属性、实例属性、类方法、静态方法
属性对比
类属性
定义在类体顶层
所有实例共享
修改需通过类名
可变对象陷阱
实例属性
定义在__init__中 self
每个对象独立
查找顺序
实例 dict → 类 dict → 父类
方法对比
实例方法
第一个参数self
可访问实例和类
类方法 @classmethod
第一个参数cls
可访问类属性,可被子类覆盖
用途:工厂、操作类状态
静态方法 @staticmethod
无默认参数
不能访问类/实例状态
用途:工具函数组织
property
将方法转为属性
getter/setter/deleter
实现验证、只读、计算
应用场景
计数器
配置管理
工厂模式
工具类
面试考点
类属性与实例属性区别
类方法与静态方法区别
何时使用类方法
property实现封装
🔜 下节课预告
本课我们详细学习了类属性、实例属性、类方法、静态方法。下一节课我们将探索Python中的魔术方法(Magic Methods/Dunder Methods),这些特殊方法可以让你的类支持len()、+运算、迭代等语言特性。
第27课:魔术方法大全:init/str/__repr__等常用魔术方法实战
内容包括:
- 对象表示的__str__和__repr__
- 容器模拟:__len__、__getitem__、__setitem__、__delitem__
- 运算符重载:__add__、__sub__、__eq__等
- 上下文管理器:__enter__、__exit__
- 可调用对象:__call__
- 属性访问:__getattr__、__setattr__
- 实战:实现一个可迭代的集合类
魔术方法是Python面向对象的高级特性,掌握它们可以让你写出更Pythonic的代码。
🌟 学习鼓励:理解类属性和实例属性的区别是写出正确面向对象代码的基础。类方法和静态方法虽然看起来简单,但恰当使用能让你的API更加优雅。建议你在编写类之前,先思考哪些数据是共享的,哪些方法是与实例无关的,选择合适的设计。动手完成练习题,你一定会有更深的理解。
🔗《50节课 Python 从入门到精通》系列课程导航
去订阅
🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~


