9. 方法
方法是定义在类内部的函数,用于描述对象的行为。根据作用域和绑定方式的不同,Python中有三种常见的方法:实例方法、类方法和静态方法。
9.1 实例方法
实例方法的第一个参数必须是 self,它绑定到调用该方法的实例,操作实例变量。通过实例调用时,Python会自动将实例作为 self 传入。实例方法可以访问实例变量和类变量(通过 self.__class__ 或类名)。
调用方式:只能通过实例调用(obj.method())。
关键区别:依赖对象状态(通过 self 访问实例变量)。
示例1:
class Dog: def __init__(self, name): self.name = name def bark(self): print(f"{self.name} 汪汪叫!")dog = Dog("旺财")dog.bark() # 输出:旺财 汪汪叫!
示例2:实例方法与实例变量的交互
class BankAccount: def __init__(self, owner, balance=0): self.owner = owner # 实例变量 self.balance = balance # 实例变量 # 实例方法:操作实例变量 def deposit(self, amount): self.balance += amount return f"{self.owner} deposited ${amount}. New balance: ${self.balance}"# 创建对象account1 = BankAccount("Alice", 100)account2 = BankAccount("Bob", 50)# 调用实例方法print(account1.deposit(50)) # 输出: Alice deposited $50. New balance: $150print(account2.deposit(100)) # 输出: Bob deposited $100. New balance: $150# 实例方法无法通过类名直接调用(会报错)# BankAccount.deposit(100) # 错误!缺少self参数
✅验证:
9.2 类方法
类方法使用 @classmethod 装饰器定义,第一个参数是 cls,代表类本身。
类方法既可以由类调用,也可以由实例调用(Class.method() 或 obj.method()),但 cls 始终指向类。
类方法可以访问类变量,但不能直接访问实例变量(因为没有实例)。
关键区别:操作类变量,不依赖实例状态(通过cls访问类属性)。
示例1:
class Dog: species = "Canis familiaris" @classmethod def get_species(cls): return cls.speciesprint(Dog.get_species()) # 通过类调用:Canis familiarisdog = Dog()print(dog.get_species()) # 通过实例调用:Canis familiaris
类方法常用于创建工厂方法(返回类的实例)或访问/修改类属性。
示例2:类方法与类变量的交互
class Car: total_cars = 0 # 类变量 def __init__(self, model): self.model = model Car.total_cars += 1 # 通过类名修改类变量 # 类方法:重置类变量 @classmethod def reset_total(cls): cls.total_cars = 0# 创建对象car1 = Car("Toyota Camry")car2 = Car("Honda Civic")# 验证类变量print(Car.total_cars) # 输出: 2 (初始总数)# 调用类方法(通过类名)Car.reset_total()print(Car.total_cars) # 输出: 0 (重置成功)# 通过实例调用类方法(同样有效)car1.reset_total()print(Car.total_cars) # 输出: 0
✅ 验证:
total_cars 是类变量,通过 Car.total_cars 访问。
reset_total 是类方法,修改 cls.total_cars(cls 指向 Car 类)。
通过 car1.reset_total() 调用,cls 仍指向 Car 类。
实例方法 vs 类方法:关键区别总结
| | |
|---|
| self | cls |
| | |
| | 通过类名或实例调用(Class.method() 或 obj.method()) |
| 对象行为(如 deposit(), greet()) | |
| def withdraw(self, amount): | @classmethod def create_car(cls, model): |
错误常见点:在类方法中忘记 @classmethod 装饰器。
9.3 静态方法
静态方法使用 @staticmethod 装饰器定义,它既不需要 self 也不需要 cls 参数,可以看作是一个在类命名空间下的普通函数。静态方法不访问实例或类的属性(除非显式通过类名),通常用于实现一些与类相关但独立于具体实例的逻辑。
class MathUtil: @staticmethod def add(x, y): return x + yprint(MathUtil.add(3, 5)) # 输出:8
9.4 实例方法、类方法与静态方法的区别
为了更清晰地选择使用哪种方法,下面从定义、访问能力和典型用途等方面进行对比。
详细示例1:
class Student: school = "第一中学" # 类变量 def __init__(self, name, grade): self.name = name # 实例变量 self.grade = grade def display_info(self): # 实例方法,可访问实例变量和类变量 print(f"姓名:{self.name},年级:{self.grade},学校:{self.school}") @classmethod def change_school(cls, new_school): # 类方法,修改类变量 cls.school = new_school @classmethod def from_string(cls, info_str): # 类方法作为工厂方法,创建实例 name, grade = info_str.split(',') return cls(name, int(grade)) @staticmethod def is_valid_grade(grade): # 静态方法,验证年级是否有效 return 1 <= grade <= 12# 使用实例方法s1 = Student("小明", 5)s1.display_info() # 姓名:小明,年级:5,学校:第一中学# 使用类方法修改类变量Student.change_school("第二中学")s2 = Student("小红", 3)s2.display_info() # 姓名:小红,年级:3,学校:第二中学# 使用类方法创建对象s3 = Student.from_string("小刚,8")s3.display_info() # 姓名:小刚,年级:8,学校:第二中学# 使用静态方法print(Student.is_valid_grade(10)) # Trueprint(Student.is_valid_grade(15)) # False
详细示例2:综合应用实例变量、类变量、实例方法、类方法
class Library: # 类变量:所有图书馆共享的馆藏数量 total_books = 0 def __init__(self, name): self.name = name # 实例变量 self.books = [] # 实例变量(独立于其他图书馆) Library.total_books += 1 # 更新类变量 # 实例方法:添加书籍(操作实例变量) def add_book(self, book): self.books.append(book) return f"Added '{book}' to {self.name} library." # 类方法:获取所有图书馆总数(操作类变量) @classmethod def get_total_libraries(cls): return f"Total libraries: {cls.total_books}" # 类方法:创建新图书馆(工厂方法) @classmethod def create_public_library(cls, name): return cls(name) # 调用__init__创建新实例# 创建图书馆public_lib = Library("City Public Library")university_lib = Library("University Library")# 验证实例变量print(public_lib.name) # 输出: City Public Libraryprint(university_lib.books) # 输出: [] (独立实例变量)# 验证类变量print(Library.total_books) # 输出: 2 (类变量更新)print(public_lib.get_total_libraries()) # 输出: Total libraries: 2 (类方法)# 使用类方法创建新图书馆new_lib = Library.create_public_library("County Library")print(new_lib.name) # 输出: County Libraryprint(Library.total_books) # 输出: 3 (类变量更新)
✅ 验证:
total_books 类变量被正确更新(3个图书馆)。
public_lib.books 和 university_lib.books 是独立的列表。
create_public_library 作为类方法成功创建新实例。
10. 特殊方法(魔术方法)
Python中的特殊方法(也称为魔术方法)是以双下划线开头和结尾的方法,用于实现类的内置操作。通过重写这些方法,可以自定义对象的行为。
10.1 常用特殊方法
__init__(self, ...):构造函数,在对象创建时调用。
__str__(self):定义当使用 str() 或 print() 时返回的字符串。
__repr__(self):定义对象的“官方”字符串表示,通常用于调试,应尽可能还原对象创建方式。
__del__(self):析构函数,在对象被垃圾回收前调用。
__call__(self, ...):使对象可以像函数一样被调用。
__len__(self):定义 len() 函数的行为。
__getitem__(self, key):定义通过 obj[key] 访问元素的行为。
__setitem__(self, key, value):定义通过 obj[key] = value 赋值的行为。
__eq__(self, other):定义相等比较 ==。
__lt__(self, other):定义小于比较 <,等等。
10.2 示例
class Book: def __init__(self, title, author, pages): self.title = title self.author = author self.pages = pages def __str__(self): return f"《{self.title}》 by {self.author}" def __repr__(self): return f"Book('{self.title}', '{self.author}', {self.pages})" def __len__(self): return self.pages def __call__(self): print(f"开始阅读《{self.title}》...")book = Book("Python编程", "张三", 300)print(str(book)) # 《Python编程》 by 张三print(repr(book)) # Book('Python编程', '张三', 300)print(len(book)) # 300book() # 开始阅读《Python编程》...
通过实现特殊方法,我们可以让自定义类的对象表现得像内置类型一样自然。