第60集:类属性与实例属性
学习目标
- 理解类属性与实例属性的区别
- 掌握类属性的访问和修改方式
- 学会合理使用类属性和实例属性
- 理解类方法、实例方法和静态方法的区别
- 掌握属性的查找顺序
一、类属性与实例属性概述
1.1 类属性
类属性:定义在类中,在方法之外的变量,所有对象共享。
1.2 实例属性
实例属性:定义在方法中,使用self绑定的变量,每个对象独立。
1.3 基本示例
class Dog:
species = "犬科动物" # 类属性
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age # 实例属性
dog1 = Dog("旺财", 3)
dog2 = Dog("来福", 5)
print(dog1.species) # 输出:犬科动物
print(dog2.species) # 输出:犬科动物
print(Dog.species) # 输出:犬科动物
print(dog1.name) # 输出:旺财
print(dog2.name) # 输出:来福二、类属性详解
2.1 定义类属性
class Circle:
pi = 3.14159 # 类属性:圆周率
count = 0 # 类属性:计数器
print(f"π = {Circle.pi}")
print(f"计数: {Circle.count}")2.2 访问类属性
class Student:
school = "Python学院" # 类属性
count = 0 # 学生计数
# 通过类访问
print(Student.school) # 输出:Python学院
# 通过对象访问
stu1 = Student()
print(stu1.school) # 输出:Python学院
# 所有对象共享类属性
stu2 = Student()
print(f"stu1.school: {stu1.school}")
print(f"stu2.school: {stu2.school}")2.3 修改类属性
class Product:
discount_rate = 0.1 # 默认折扣率
print(f"默认折扣: {Product.discount_rate}")
# 通过类修改
Product.discount_rate = 0.15
print(f"修改后折扣: {Product.discount_rate}")
# 所有对象都看到修改后的值
p1 = Product()
p2 = Product()
print(f"p1折扣: {p1.discount_rate}")
print(f"p2折扣: {p2.discount_rate}")2.4 注意:通过对象修改类属性
class Counter:
count = 0
counter = Counter()
# 通过对象赋值会创建实例属性
counter.count = 10
print(f"Counter.count: {Counter.count}") # 输出:0
print(f"counter.count: {counter.count}") # 输出:10
# 实例属性遮蔽了类属性三、实例属性详解
3.1 定义实例属性
class Person:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age # 实例属性
person = Person("张三", 25)
print(f"姓名: {person.name}")
print(f"年龄: {person.age}")3.2 动态添加实例属性
class Book:
pass
book = Book()
# 动态添加属性
book.title = "Python编程"
book.author = "张三"
book.price = 59.9
print(f"书名: {book.title}")
print(f"作者: {book.author}")
print(f"价格: {book.price}元")3.3 每个对象的实例属性独立
class Student:
def __init__(self, name, score):
self.name = name
self.score = score
stu1 = Student("张三", 90)
stu2 = Student("李四", 85)
# 修改stu1的分数
stu1.score = 95
print(f"stu1分数: {stu1.score}") # 输出:95
print(f"stu2分数: {stu2.score}") # 输出:85(不受影响)四、属性查找顺序
4.1 查找顺序
实例对象 → 实例属性 → 类属性 → 父类属性 → object4.2 查找示例
class MyClass:
class_var = "类属性"
obj = MyClass()
# 1. 添加同名实例属性
obj.class_var = "实例属性"
print(obj.class_var) # 输出:实例属性(实例属性遮蔽类属性)
print(MyClass.class_var) # 输出:类属性
# 2. 删除实例属性
del obj.class_var
print(obj.class_var) # 输出:类属性(回到类属性)4.3 完整查找示例
class Parent:
var = "父类属性"
class Child(Parent):
var = "子类属性"
obj = Child()
# 查找顺序
print(obj.var) # 输出:子类属性
print(Child.var) # 输出:子类属性
print(Parent.var) # 输出:父类属性五、使用类属性实现计数
5.1 对象计数器
class Item:
count = 0 # 类属性:计数器
def __init__(self, name):
self.name = name
Item.count += 1 # 创建对象时计数加1
def __del__(self):
Item.count -= 1 # 删除对象时计数减1
print(f"创建前: {Item.count}个对象")
item1 = Item("商品1")
item2 = Item("商品2")
item3 = Item("商品3")
print(f"创建后: {Item.count}个对象")
del item1
print(f"删除一个后: {Item.count}个对象")5.2 生成唯一ID
class User:
next_id = 1 # 下一个可用的ID
def __init__(self, name):
self.name = name
self.id = User.next_id
User.next_id += 1
def __str__(self):
return f"ID: {self.id}, 姓名: {self.name}"
users = [User("张三"), User("李四"), User("王五")]
for user in users:
print(user)六、类属性的实际应用
6.1 配置管理
class Config:
"""配置类"""
DEBUG = True
MAX_CONNECTIONS = 100
TIMEOUT = 30
LOG_LEVEL = "INFO"
# 使用配置
print(f"调试模式: {Config.DEBUG}")
print(f"最大连接数: {Config.MAX_CONNECTIONS}")
# 修改配置
Config.DEBUG = False
print(f"修改后调试模式: {Config.DEBUG}")6.2 常量定义
class MathConstants:
"""数学常量"""
PI = 3.141592653589793
E = 2.718281828459045
GOLDEN_RATIO = 1.618033988749895
print(f"π = {MathConstants.PI}")
print(f"e = {MathConstants.E}")
print(f"黄金分割 = {MathConstants.GOLDEN_RATIO}")6.3 缓存管理
class Cache:
"""缓存类"""
_cache = {} # 私有类属性
@classmethod
def get(cls, key):
return cls._cache.get(key)
@classmethod
def set(cls, key, value):
cls._cache[key] = value
@classmethod
def clear(cls):
cls._cache.clear()
@classmethod
def show(cls):
print(f"缓存内容: {cls._cache}")
# 使用缓存
Cache.set("user:1", {"name": "张三", "age": 25})
Cache.set("user:2", {"name": "李四", "age": 30})
Cache.show()
user = Cache.get("user:1")
print(f"用户1: {user}")七、类方法与实例方法
7.1 实例方法
class Calculator:
def __init__(self):
self.result = 0
def add(self, a, b): # 实例方法
self.result = a + b
return self.result
calc = Calculator()
print(calc.add(3, 5)) # 输出:87.2 类方法
class Date:
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def today(cls):
import datetime
today = datetime.date.today()
return cls(today.year, today.month, today.day)
@classmethod
def from_string(cls, date_str):
year, month, day = map(int, date_str.split('-'))
return cls(year, month, day)
today = Date.today()
print(f"今天: {today.year}-{today.month}-{today.day}")
date = Date.from_string("2024-12-25")
print(f"指定日期: {date.year}-{date.month}-{date.day}")7.3 静态方法
class MathUtils:
@staticmethod
def add(a, b):
return a + b
@staticmethod
def multiply(a, b):
return a * b
print(MathUtils.add(3, 5)) # 输出:8
print(MathUtils.multiply(3, 5)) # 输出:15八、属性装饰器
8.1 @property装饰器
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
temp = Temperature(25)
print(f"摄氏度: {temp.celsius}°C")
print(f"华氏度: {temp.fahrenheit:.1f}°F")
temp.celsius = 30
print(f"修改后摄氏度: {temp.celsius}°C")九、常见错误与注意事项
9.1 常见错误
- 通过对象修改类属性:
class Counter:
count = 0
c1 = Counter()
c2 = Counter()
c1.count = 10 # 创建实例属性
print(c1.count) # 输出:10
print(c2.count) # 输出:0
print(Counter.count) # 输出:0- 忘记使用类名:
class MyClass:
value = 0
def method(self):
value += 1 # 错误!应该用 self.value 或 MyClass.value9.2 注意事项
- 类属性被所有对象共享
- 实例属性每个对象独立
- 通过对象修改类属性会创建实例属性
- 合理使用类属性存储共享数据
- 使用实例属性存储对象特有数据
十、课后练习
练习题
编程题
- 定义一个Person类
- 使用类属性计数人数
- 每创建一个对象人数加1
编程题
- 定义一个配置类
- 使用类属性存储配置
- 提供修改配置的方法
思考题
- 类属性和实例属性有什么区别?
- 什么时候应该使用类属性?
- 属性的查找顺序是什么?
十一、本集总结
核心知识点回顾
- 类属性:定义在类中,所有对象共享
- 实例属性:定义在实例中,每个对象独立
- 属性查找:实例→类→父类→object
- 类方法:使用@classmethod,操作类属性
- 静态方法:使用@staticmethod,不依赖实例或类
- 属性装饰器:@property实现属性访问控制
下集预告
下一集我们将学习面向对象高级特性,包括静态方法、类方法、属性装饰器等。
学习建议: 理解类属性和实例属性的区别非常重要,合理使用可以提高代码的效率和可维护性。