黑洞酷走
28.94M · 2026-03-22
前几天有个小伙伴问我:“Python中的@classmethod和@staticmethod到底有什么区别?感觉它们长得差不多,用起来也差不多啊!” 我告诉他:感觉差不多就是差很多,干程序必须得严谨呀兄弟。
这次,我们就搞定这两个的真正区别,以后就不会再迷茫了!
假设我们要做一个游戏,里面有个“英雄”类。每个英雄都有名字、等级和血量。我们可能会这样写:
class Hero:
def __init__(self, name, level, health):
self.name = name
self.level = level
self.health = health
现在问题来了:如果我们想从配置文件中创建英雄,或者根据某些规则创建特殊英雄,该怎么办呢?
这就是@classmethod和@staticmethod大显身手的时候了!
先简单的解释一下这个,@classmethod装饰的方法第一个参数是cls,代表类本身。这意味着它可以通过cls来访问类属性,甚至可以创建类的实例!
如果想看非常具体的官方文档的话,这里给大家教一个简单的操作:
打开你的pyCharm编辑器,找到你想看的这个函数,这里咱么就以@classmethod这个内置函数为例
光标变成蓝色了,相当于选中他了, 然后打开view→接着选择下图中用红框框住的选项,点一下,就会自动跳转到@classmethod函数的官方文档的位置,方便吧! view里面有很多功能,比如还有直接跳转到源码啥的,咱们要善于利用工具不是。
好了,我们接着看下面这个例子:
例子:
class Hero:
DEFAULT_LEVEL = 1
DEFAULT_HEALTH = 100
def __init__(self, name, level, health):
self.name = name
self.level = level
self.health = health
@classmethod
def from_config(cls, config_str):
# 从配置字符串解析数据
name, level, health = config_str.split(',')
# 使用cls()创建实例
return cls(name, int(level), int(health))
@classmethod
def create_default(cls, name):
# 使用类属性创建默认英雄
return cls(name, cls.DEFAULT_LEVEL, cls.DEFAULT_HEALTH)
使用方法:
# 从配置创建英雄
config = "孙悟空,5,200"
wukong = Hero.from_config(config)
# 创建默认英雄
new_hero = Hero.create_default("猪八戒")
划重点:@classmethod知道自己是哪个类的方法(通过cls参数),可以访问类属性,还能创建实例。就像一个有家族观念的人,知道自己从哪里来,能创造新生命。
@staticmethod装饰的方法则没有cls参数,它就像类里的一个普通函数,与类本身没有直接关系,不能访问类属性或实例属性。
继续看例子:
class Hero:
def __init__(self, name, level, health):
self.name = name
self.level = level
self.health = health
@staticmethod
def calculate_damage(attack_power, defense):
# 计算伤害的公式
return max(attack_power - defense, 0)
@staticmethod
def is_valid_name(name):
# 检查名字是否有效
return len(name) >= 2 and name.isprintable()
使用方法:
# 计算伤害(不需要英雄实例)
damage = Hero.calculate_damage(50, 30)
# 检查名字是否有效
valid = Hero.is_valid_name("唐三藏")
关键点:@staticmethod就像寄居在类里面的一个函数,它不关心自己是属于哪个类的,也不需要访问类或实例的任何属性。它只是个“租客”,不是“家庭成员”。
现在可能就会有个疑问:“那我到底该什么时候用@classmethod,什么时候用@staticmethod呢?”
记住这个简单的原则:
| 特性 | @classmethod | @staticmethod |
|---|---|---|
| 第一个参数 | cls(类本身) | 没有特殊参数 |
| 可以访问类属性 | 可以 | 不可以 |
| 可以访问实例属性 | 不可以(没有实例) | 不可以 |
| 可以创建实例 | 可以 | 不可以 |
| 与类状态相关度 | 高 | 低 |
如果你还是有点模糊,我想了个生活化的比喻:
记住这几个关键点: