python中 实例方法(普通方法)和 类方法 的核心差异
一、普通实例方法(没加 @classmethod
的情况)
假设你的代码原本是这样(普通实例方法):
class Jglc_Test_api:def login(self, session, login_data): # 第一个参数是 self# 登录逻辑...pass
self
是什么?
self
是实例对象本身的引用。调用这个方法时,必须先创建类的实例:
api = Jglc_Test_api() # 创建实例
api.login(session, data) # 用实例调用方法
限制:如果
login
不需要依赖“某个具体实例的状态”(比如不需要访问实例属性self.xxx
),只是操作类本身的逻辑(比如验证登录参数、调用接口),那么创建实例就显得多余。
二、为什么要加 @classmethod
?cls
是什么?
@classmethod
是 Python 的装饰器,用来定义类方法。此时方法的第一个参数必须是 cls
(全称 "class",但名字可以随便取,习惯用 cls
)。
1. 类方法的调用方式:不需要实例,直接用类调用
类方法可以直接通过类名调用,不需要先创建实例:
# 直接用类调用,不用创建 api 实例
Jglc_Test_api.login(session, data)
这对你的登录场景很友好——登录通常是“类级别的操作”(比如验证账号密码是否符合类的规则,或调用接口获取 token),不需要绑定某个具体的实例。
2. cls
的作用:指向类本身
cls
是类对象的引用,通过它可以访问:
类属性(比如
cls.base_url
,如果类里有base_url = "https://xxx"
);创建类的新实例(比如
new_api = cls(...)
)。
举个例子,假设你的类里有个类属性 base_url
,类方法可以这样用:
class Jglc_Test_api:base_url = "https://127.0.0.1:8088" # 类属性(所有实例共享)@classmethoddef login(cls, session, login_data):# 用 cls 访问类属性full_url = f"{cls.base_url}/secu-org/hswealth.sus/account/login/login.json"# 发送登录请求...response = session.post(full_url, json=login_data)return response.json()
这里 cls.base_url
直接拿到了类里定义的基础 URL,不需要通过实例访问。
三、类方法 vs 实例方法:什么时候用哪个?
类型 | 第一个参数 | 调用方式 | 适用场景 |
---|---|---|---|
实例方法 |
| 必须用实例调用( | 需要访问/修改实例的状态(比如 |
类方法 |
| 可以用类直接调用( | 操作类本身的逻辑(比如配置、工具方法) |
四、结合你的代码场景:为什么用类方法?
你的 login
方法是登录接口的工具方法,它的逻辑可能不需要依赖“某个具体的 Jglc_Test_api
实例”——比如:
不需要访问实例的属性(比如
self.token
,因为登录后会返回 token,不需要存在实例里);只需要类的公共配置(比如
base_url
);可以直接通过类调用,更方便(比如测试脚本里直接
Jglc_Test_api.login(...)
)。
五、延伸:静态方法(@staticmethod
)的区别
如果类方法里既不需要 cls
也不需要 self
,可以用 @staticmethod
定义静态方法(纯工具函数):
class Jglc_Test_api:@staticmethoddef validate_login_data(login_data):# 验证登录数据的格式(比如是否有 username/password)if not login_data.get("username") or not login_data.get("password"):raise ValueError("用户名或密码不能为空")return True
静态方法不需要 self
或 cls
,纯粹是类名空间下的工具函数,调用方式和类方法一样:Jglc_Test_api.validate_login_data(data)
。
总结
@classmethod
:定义类方法,不需要实例就能调用;
cls
:指向类本身,用来访问类属性或创建实例;你的代码:
login
是类级别的工具方法,不需要实例状态,所以用类方法更方便。
一句话记住:
实例方法属于“对象”,类方法属于“类”——当逻辑不需要绑定具体对象时,就用类方法!