第52集:类与对象基础
学习目标
- 掌握如何定义类
- 学会创建和使用对象
- 理解类属性和实例属性
- 掌握类方法、实例方法和静态方法
- 了解对象的生命周期
- 掌握对象的内存管理
一、定义类
1.1 类的定义语法
class ClassName:
"""类文档字符串"""
# 类体
# 属性
# 方法
pass1.2 基本示例
# 定义一个简单的类
class Person:
"""人类"""
# 类属性(所有对象共享)
species = "人类"
# 实例方法
def say_hello(self):
print("你好!")1.3 命名规范
类名:使用大驼峰命名法(PascalCase)
- 例如:
Person、Student、BankAccount
- 例如:
方法名:使用小写加下划线(snake_case)
- 例如:
say_hello、get_name、set_age
- 例如:
属性名:使用小写加下划线(snake_case)
- 例如:
name、age、address
- 例如:
二、创建对象
2.1 创建对象的语法
# 对象创建的语法
对象名 = 类名()2.2 创建对象示例
class Person:
species = "人类"
def say_hello(self):
print("你好!")
# 创建对象
person1 = Person()
person2 = Person()
# 使用对象
person1.say_hello() # 输出:你好!
person2.say_hello() # 输出:你好!2.3 对象的独立性
class Counter:
count = 0 # 类属性
def increment(self):
self.count += 1 # 创建实例属性
# 创建多个对象
c1 = Counter()
c2 = Counter()
# 每个对象的属性是独立的
c1.increment()
c1.increment()
c2.increment()
print(f"c1.count: {c1.count}") # 输出:2
print(f"c2.count: {c2.count}") # 输出:1三、类属性 vs 实例属性
3.1 类属性
定义: 定义在类中、方法外的属性,所有对象共享。
特点:
- 所有对象共享同一个值
- 通过类名或对象名访问
- 修改类属性会影响所有对象
示例:
class Dog:
species = "犬科动物" # 类属性
def __init__(self, name):
self.name = name # 实例属性
# 访问类属性
print(Dog.species) # 输出:犬科动物
# 通过对象访问
dog1 = Dog("小白")
dog2 = Dog("小黑")
print(dog1.species) # 输出:犬科动物
print(dog2.species) # 输出:犬科动物
# 修改类属性
Dog.species = "狗"
print(dog1.species) # 输出:狗
print(dog2.species) # 输出:狗3.2 实例属性
定义: 定义在__init__方法中,通过self设置的属性,每个对象独立拥有。
特点:
- 每个对象有自己独立的值
- 只能通过对象名访问
- 修改实例属性不影响其他对象
示例:
class Student:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age # 实例属性
# 创建对象
s1 = Student("张三", 18)
s2 = Student("李四", 19)
# 每个对象的属性是独立的
print(f"s1: {s1.name}, {s1.age}") # 输出:s1: 张三, 18
print(f"s2: {s2.name}, {s2.age}") # 输出:s2: 李四, 19
# 修改实例属性
s1.name = "王五"
s1.age = 20
print(f"s1: {s1.name}, {s1.age}") # 输出:s1: 王五, 20
print(f"s2: {s2.name}, {s2.age}") # 输出:s2: 李四, 193.3 属性查找顺序
当访问一个属性时,Python的查找顺序:
实例属性 -> 类属性 -> 报错示例:
class MyClass:
class_attr = "类属性"
def __init__(self):
self.instance_attr = "实例属性"
obj = MyClass()
# 优先访问实例属性
print(obj.instance_attr) # 输出:实例属性
# 访问类属性
print(obj.class_attr) # 输出:类属性
# 修改(实际上是创建实例属性)
obj.class_attr = "修改后的实例属性"
print(obj.class_attr) # 输出:修改后的实例属性
print(MyClass.class_attr) # 输出:类属性(未改变)四、实例方法
4.1 定义实例方法
class ClassName:
def method_name(self, 参数1, 参数2, ...):
# 方法体
pass关键点:
- 方法的第一个参数必须是
self self代表当前对象实例- 通过
self可以访问对象的属性和方法
4.2 self的作用
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
# 通过self访问属性
print(f"我叫{self.name},今年{self.age}岁")
def greet(self, other):
# self代表当前对象,other代表其他对象
print(f"{self.name}向{other.name}打招呼")
# 创建对象
p1 = Person("张三", 18)
p2 = Person("李四", 20)
p1.introduce() # 输出:我叫张三,今年18岁
p1.greet(p2) # 输出:张三向李四打招呼4.3 方法的类型
4.3.1 实例方法
class MyClass:
def instance_method(self):
print("这是实例方法")
print(f"self的值: {self}")4.3.2 类方法(使用@classmethod装饰器)
class MyClass:
class_attr = "类属性"
@classmethod
def class_method(cls):
print("这是类方法")
print(f"cls的值: {cls}")
print(f"访问类属性: {cls.class_attr}")
# 调用类方法
MyClass.class_method()特点:
- 第一个参数是
cls,代表类本身 - 可以访问类属性和类方法
- 通过类名或对象名调用
4.3.3 静态方法(使用@staticmethod装饰器)
class MyClass:
@staticmethod
def static_method():
print("这是静态方法")
# 不能访问self或cls
# 调用静态方法
MyClass.static_method()特点:
- 不需要特殊的第一个参数
- 不能访问实例属性或类属性
- 通常用于工具函数
4.4 三种方法的对比
| 类型 | 第一个参数 | 调用方式 | 可访问 | 用途 |
|---|---|---|---|---|
| 实例方法 | self |
对象名 | 实例属性和方法 | 操作对象数据 |
| 类方法 | cls |
类名或对象名 | 类属性和方法 | 操作类数据 |
| 静态方法 | 无 | 类名或对象名 | 无 | 工具函数 |
综合示例:
class MathUtil:
pi = 3.14159 # 类属性
# 实例方法
def __init__(self, value):
self.value = value
def multiply(self, other):
return self.value * other
# 类方法
@classmethod
def get_pi(cls):
return cls.pi
# 静态方法
@staticmethod
def add(a, b):
return a + b
# 使用
util = MathUtil(5)
print(util.multiply(3)) # 输出:15(实例方法)
print(MathUtil.get_pi()) # 输出:3.14159(类方法)
print(MathUtil.add(2, 3)) # 输出:5(静态方法)五、对象的生命周期
5.1 对象的创建过程
1. 分配内存空间
2. 调用__init__方法初始化
3. 返回对象引用示例:
class Demo:
def __init__(self, name):
print("对象正在创建...")
self.name = name
print("对象创建完成!")
obj = Demo("测试对象")
# 输出:
# 对象正在创建...
# 对象创建完成!5.2 对象的使用
class Person:
def __init__(self, name):
self.name = name
def work(self):
print(f"{self.name}在工作")
# 创建对象
p = Person("张三")
# 使用对象
p.work() # 调用方法
print(p.name) # 访问属性5.3 对象的销毁
class Demo:
def __del__(self):
print("对象被销毁了")
def create_demo():
d = Demo()
print("函数结束")
create_demo()
# 输出:
# 函数结束
# 对象被销毁了六、动态添加属性和方法
6.1 动态添加属性
class Person:
def __init__(self, name):
self.name = name
p = Person("张三")
# 动态添加属性
p.age = 18
p.city = "北京"
print(p.name) # 输出:张三
print(p.age) # 输出:18
print(p.city) # 输出:北京6.2 动态添加方法
class Person:
def __init__(self, name):
self.name = name
def new_method(self):
print(f"{self.name}的新方法")
# 动态添加方法
Person.new_func = new_method
p = Person("张三")
p.new_func() # 输出:张三的新方法6.3 删除属性
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
p = Person("张三", 18)
# 删除属性
del p.age
print(p.name) # 输出:张三
print(p.age) # 报错:AttributeError七、实例:学生类
7.1 完整示例
class Student:
"""学生类"""
# 类属性
school = "Python学院"
total_students = 0
def __init__(self, name, age, grade):
"""初始化学生"""
self.name = name
self.age = age
self.grade = grade
Student.total_students += 1
def introduce(self):
"""自我介绍"""
print(f"大家好,我是{self.name},今年{self.age}岁,{self.grade}年级")
def study(self, subject):
"""学习"""
print(f"{self.name}正在学习{subject}")
@classmethod
def get_total_students(cls):
"""获取学生总数"""
return cls.total_students
@classmethod
def change_school(cls, new_school):
"""更换学校"""
cls.school = new_school
@staticmethod
def calculate_average(scores):
"""计算平均分"""
return sum(scores) / len(scores)
# 使用示例
s1 = Student("张三", 18, "大一")
s2 = Student("李四", 19, "大二")
s3 = Student("王五", 20, "大三")
s1.introduce()
s2.study("Python编程")
print(f"学生总数:{Student.get_total_students()}")
print(f"学校:{s1.school}")
average = Student.calculate_average([85, 90, 78, 92, 88])
print(f"平均分:{average}")八、常见错误与注意事项
8.1 常见错误
- 忘记self参数:
class Person:
def say_hello(): # 错误:缺少self
print("你好!")- 类方法错误使用:
class MyClass:
def method(cls): # 错误:应该使用@classmethod装饰器
pass- 混淆类属性和实例属性:
class Counter:
count = 0 # 类属性
def increment(self):
count += 1 # 错误:应该使用self.count8.2 注意事项
- 类名使用大驼峰命名
- 实例方法必须有self参数
- 类方法使用@classmethod装饰器
- 静态方法使用@staticmethod装饰器
- 避免动态修改类属性,以免影响其他对象
九、课后练习
练习题
编程题
- 定义一个
Circle类,包含半径属性和计算面积、周长的方法 - 定义一个
Rectangle类,包含长和宽属性和计算面积、周长的方法 - 添加类方法和静态方法
- 定义一个
编程题
- 定义一个
Book类,包含书名、作者、价格属性 - 添加实例方法:显示书籍信息、打折
- 添加类方法:统计创建的书籍数量
- 添加静态方法:判断价格是否合理
- 定义一个
编程题
- 定义一个
BankAccount类 - 包含账号、余额属性
- 添加存款、取款、查询余额方法
- 使用类属性记录账户总数
- 定义一个
分析题
- 分析以下代码的输出结果
class A: x = 1 def __init__(self): self.x = 2 a = A() print(A.x) print(a.x)
十、本集总结
核心知识点回顾
- 类定义:使用
class关键字定义类 - 对象创建:使用
类名()创建对象 - 类属性:所有对象共享,通过类名或对象名访问
- 实例属性:每个对象独立,通过对象名访问
- 实例方法:第一个参数是
self,操作对象数据 - 类方法:使用
@classmethod,操作类数据 - 静态方法:使用
@staticmethod,不访问对象或类数据 - 对象生命周期:创建、使用、销毁
下集预告
下一集我们将学习**构造方法__init__**,深入了解如何正确初始化对象。
学习建议: 多编写不同类型的类,熟练掌握类属性、实例属性、实例方法、类方法、静态方法的使用场景。理解面向对象编程的核心思想。