Python类中方法种类介绍
类方法的种类及说明:
| 方法类型 | 说明/ 描述 |
|---|---|
| 1. 实例方法 | 1).无特定装饰器,第一个参数为 "self"(指向实例对象)。 2).可通过"self.属性名" 访问实例属性,也可通过"self.class.属性名"或"类名.属性名"访问类属性。 3).应通过 "实例.方法名()" 方式调用;使用"类名.方法名()"需手动传入实例self,不推荐。 |
| 2. 类方法 | 1). 使用"@classmethod"装饰,第一个参数为"cls"(指向类本身)。 2).可通过"cls.属性名" 访问类属性;无法直接访问实例属性(因不绑定具体实例)。 3).可通过"类.方法名()"或"实例.方法名()" 调用,两种方式均自动传递"cls"参数。 |
| 3. 静态方法 | 1). 使用 "@staticmethod"装饰,无强制参数(不绑定"cls" 或"self")。 2).通常不访问类或实例属性;如需访问类属性,可通过"类名.属性名",但不符合静态方法设计初衷。 3).可通过"类.方法名()"或"实例.方法名()"调用,无参数自动传递。 |
| 4. 抽象方法 | 1. 使用 `@abstractmethod` 装饰,必须定义在继承自 `abc.ABC` 的抽象基类中。 2.必须由子类实现,否则子类无法实例化。 3.可为实例方法(参数"self")或类方法(参数"cls"),具体由子类实现决定。 |
| 5. 魔术方法 | 1).以双下划线开头和结尾(如"init"、"str")。 2).由 Python 解释器自动调用,用于实现对象的初始化、表示、运算等底层行为。 3).不应手动直接调用,而应通过相应内置函数或操作符触发。 |
| 6. 特性方法 | 1).使用"@property"装饰,将方法转换为"只读属性"。 2).调用时无需括号,如 "obj.属性"。 3).可配合"@属性名.setter"和"@属性名.deleter"定义设置和删除逻辑,实现对属性的封装与控制。 |
下面给出示例解释
1. 实例方法示例
python
class Student:
class_attr = "学生类" # 类属性(所有实例共享)
def __init__(self, name):
self.name = name # 实例属性(每个实例独有)
def introduce(self): # 实例方法
# 可以访问实例属性和类属性
print(f"我叫{self.name},属于{self.class_attr}")
def get_class_attr(self):
# 三种访问类属性的方式(推荐使用前两种)
print(f"方式1: {self.__class__.class_attr}") # 通过__class__
print(f"方式2: {Student.class_attr}") # 通过类名
print(f"方式3: {self.class_attr}") # 通过self(会先在实例中查找)
# 调用
stu = Student("小明")
stu.introduce() # 正确调用方式
运行输出:
我叫小明,属于学生类
**说明,**易错点和注意事项:
1). 忘记写self参数会导致TypeError
错误示例: def introduce(): 缺少self参数
2). 通过类名调用实例方法时必须手动传入实例
正确但繁琐: Student.introduce(stu)
3). self.class_attr 会先在实例属性中查找,找不到才去类属性中查找
如果存在同名的实例属性,可能得到意外结果
2. 类方法示例
python
class Student:
count = 0 # 类属性
def __init__(self, name):
self.name = name
Student.count += 1 # 修改类属性
@classmethod
def get_count(cls): # 类方法
# cls 指向类本身,不是实例
return f"学生总数:{cls.count}" # 通过cls访问类属性
@classmethod
def from_string(cls, info_str): # 类方法作为工厂方法
# 常用于创建实例的替代构造方法
name = info_str.split(",")[0]
return cls(name) # 相当于调用 Student(name)
@classmethod
def try_access_instance_attr(cls):
# 这里无法访问实例属性,因为不知道是哪个实例
# print(self.name) # 错误!没有self
# print(cls.name) # 错误!类没有name属性
pass
# 调用
stu1 = Student("张三")
stu2 = Student("李四")
print(Student.get_count()) # 通过类调用
print(stu1.get_count()) # 通过实例调用(不推荐)
运行输出:
学生总数:2
学生总数:2
说明,易错点和注意事项:
1). 类方法无法访问实例属性,因为不绑定具体实例
2). 类方法中修改类属性会影响所有实例
3). 通过实例调用类方法虽然可行,但不推荐,容易引起混淆
4). 类方法常用于工厂模式、计数器、类级别配置等场景
3. 静态方法示例
python
class MathUtils:
PI = 3.14159 # 类属性
@staticmethod
def add(a, b): # 静态方法
# 不接收self或cls参数
return a + b
@staticmethod
def is_even(number):
return number % 2 == 0
@staticmethod
def calculate_circle_area(radius):
# 虽然可以通过类名访问类属性,但这不符合静态方法的设计初衷
# 静态方法应该是纯粹的工具函数,不依赖类状态
return MathUtils.PI * radius ** 2 # 不推荐这样做
@staticmethod
def bad_practice():
# 静态方法中不应该这样做:
# print(self.name) # 错误!没有self
# print(cls.PI) # 错误!没有cls
pass
# 调用
print(MathUtils.add(5, 3)) # 推荐:通过类调用
util = MathUtils()
print(util.add(2, 2)) # 可行但不推荐:通过实例调用
运行输出:
8
4
**说明,**易错点和注意事项:
1). 静态方法既不能访问实例属性,也不能直接访问类属性
2). 如果需要访问类属性,应该考虑使用类方法
3). 静态方法应该是无状态的工具函数
4). 通过实例调用静态方法可能让人误解该方法与实例状态有关
4. 抽象方法示例
python
from abc import ABC, abstractmethod
class Animal(ABC): # 抽象基类
def __init__(self, name):
self.name = name
@abstractmethod
def make_sound(self): # 抽象实例方法
# 只有方法定义,没有实现
pass
@classmethod
@abstractmethod
def animal_type(cls): # 抽象类方法
# 抽象方法也可以是类方法
pass
def normal_method(self):
# 抽象类中可以包含具体方法
return f"{self.name}是动物"
class Dog(Animal): # 具体子类
def make_sound(self): # 必须实现所有抽象方法
return "汪汪!"
@classmethod
def animal_type(cls):
return "哺乳动物"
# 使用
dog = Dog("旺财")
print(dog.make_sound())
运行输出:
汪汪!
**说明,**易错点和注意事项:
1). 忘记实现抽象方法会导致TypeError
2). 抽象类不能被实例化,只能被继承
3). @abstractmethod必须放在最内层装饰器位置
4). 抽象类中可以包含具体方法,子类可以直接继承使用
5). 抽象方法可以有实现,但通常不提供(通过super()调用)
错误示例:
animal = Animal("抽象动物") TypeError!
5. 魔术方法示例
运行输出:
汪汪!
**说明,**易错点和注意事项:
1). 忘记实现抽象方法会导致TypeError
2). 抽象类不能被实例化,只能被继承
3). @abstractmethod必须放在最内层装饰器位置
4). 抽象类中可以包含具体方法,子类可以直接继承使用
5). 抽象方法可以有实现,但通常不提供(通过super()调用)
错误示例:
animal = Animal("抽象动物") TypeError!
5. 魔术方法示例
python
class Book:
def __init__(self, title, author, pages=0): # 构造方法
# 在对象创建时自动调用
self.title = title
self.author = author
self.pages = pages
def __str__(self): # 字符串表示
# 被print()、str()调用
return f"《{self.title}》 - {self.author}"
def __repr__(self): # 解释器表示
# 在交互式环境中显示,被repr()调用
return f"Book('{self.title}', '{self.author}')"
def __len__(self): # 定义长度
# 被len()调用
return self.pages
def __add__(self, other): # 加法运算
# 被+操作符调用
if isinstance(other, Book):
return f"{self.title} & {other.title}"
return NotImplemented
def __eq__(self, other): # 相等判断
# 被==操作符调用
if isinstance(other, Book):
return self.title == other.title and self.author == other.author
return False
# 使用
book1 = Book("Python编程", "John", 300)
book2 = Book("算法导论", "Jane", 500)
print(book1) # 自动调用__str__
print(len(book1)) # 自动调用__len__
print(book1 + book2) # 自动调用__add__
print(book1 == book2) # 自动调用__eq__
运行输出:
《Python编程》 - John
300
Python编程 & 算法导论
False
**说明,**易错点和注意事项:
1). 魔术方法由Python自动调用,不应手动直接调用
2). 不同的魔术方法需要返回特定类型(如__len__返回整数)
3). 运算符重载时应考虑类型检查,对不支持的类型返回NotImplemented
4). 同时实现__str__和__repr__,__repr__应该包含重建对象的信息
5). 某些魔术方法需要成对实现(如__eq__和__ne__)
6. 特性方法示例
python
class Circle:
def __init__(self, radius):
# 使用_开头表示受保护的属性
self._radius = radius
self._diameter = radius * 2 # 缓存计算值
@property
def radius(self): # 只读属性
# 像属性一样访问:circle.radius
return self._radius
@property
def area(self): # 计算属性
# 每次访问时动态计算
return 3.14 * self._radius ** 2
@property
def diameter(self):
# 可以返回缓存值以提高性能
return self._diameter
@diameter.setter
def diameter(self, value): # setter方法
# 在赋值时进行验证和计算
if value <= 0:
raise ValueError("直径必须大于0")
self._radius = value / 2
self._diameter = value # 更新缓存
@radius.deleter
def radius(self): # deleter方法
# 定义删除属性时的行为
print("删除半径属性")
del self._radius
# 使用
circle = Circle(5)
print(circle.radius) # 像属性一样访问,无需括号
print(circle.area) # 自动计算
print(circle.diameter) # 使用缓存值
circle.diameter = 14 # 通过setter设置,会自动更新radius
print(circle.radius) # 输出: 7
# del circle.radius # 会调用deleter方法
运行输出:
5
78.5
10
7.0
**说明,**易错点和注意事项:
1). @property必须定义在@setter之前
2). setter和deleter的方法名必须与property方法名相同
3). 使用property后,方法调用不需要括号
4). 可以在setter中添加数据验证逻辑
5). 对于计算密集型属性,可以考虑缓存计算结果
6). 避免在property方法中进行耗时操作
附录
Python青少年简明教程:类和对象入门 https://blog.csdn.net/cnds123/article/details/141953553
Python面向对象程序设计讲座 https://blog.csdn.net/cnds123/article/details/108354860
Python中的property介绍 https://blog.csdn.net/cnds123/article/details/129420059