python笔记 4 - classmethod装饰器
·
@classmethod 是 Python 中的一个装饰器,用于定义类方法。类方法的第一个参数是类本身(通常命名为 cls),而不是实例(self)。它可以通过类直接调用,也可以通过实例调用。
1. 基本语法
class NewClass:
@classmethod
def new_class_method(cls, arg1, arg2):
# cls 指向类本身(而不是实例)
print(f"这是类方法,类名: {cls.__name__}")
return arg1 + arg2
print(NewClass.new_class_method(1,2))
执行以上代码结果:
这是类方法,类名: NewClass
3
2. 与实例方法、静态方法的对比
|
方法 类型 |
第一个 参数 |
调用方式 | 能否访问/修改类属性 | 能否访问/修改实例属性 |
|---|---|---|---|---|
|
实例 方法 |
self |
实例调用, 也可类调用(需传实例) |
可以(通过 self.__class__) |
可以 |
|
类 方法 |
cls |
类或实例调用 | 可以 | 不可以(没有 self) |
|
静态 方法 |
无 | 类或实例调用 | 不可以(除非显式传入) | 不可以 |
3. 类方法调用
class Dog:
species = "犬科类" # 类属性
@classmethod
def get_species(cls):
return cls.species
@classmethod
# 工厂方法:根据名字创建实例, 等价于 Dog(name)
def create_from_name(cls, name):
return cls(name)
def __init__(self, name):
self.name = name
# 通过类调用
print(Dog.get_species())
# 通过实例调用
d = Dog("旺财")
print(f"类别:{d.get_species()}")
print(f"名字:{d.name}")
# 作为替代构造函数
dog = Dog.create_from_name("狗蛋")
print(f"类别:{dog.get_species()}")
print(f"名字:{dog.name}")
4. 典型使用场景
4.1 工厂方法(替代构造函数)
当需要多种方式创建实例时,类方法非常有用。
import datetime
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
@classmethod
def from_birth_year(cls, name, birth_year): #
current_year = datetime.datetime.now().year
age = current_year - birth_year
return cls(name, age) # 调用构造函数
@classmethod
def from_string(cls, data_str):
# 从 "name,age" 字符串创建
name, age = data_str.split(',')
return cls(name, int(age))
def printInfo(self):
print(f"姓名:{self.name}, 年龄:{self.age}")
# 使用
p1 = Person("张三", 18)
p2 = Person.from_birth_year("李四", 2018)
p3 = Person.from_string("王五,25")
p1.printInfo()
p2.printInfo()
p3.printInfo()
执行结果如下:
姓名:张三, 年龄:18
姓名:李四, 年龄:8
姓名:王五, 年龄:25
4.2 访问/修改类属性
类方法可以安全地操作类变量,即使在继承时也能正确引用子类。
class Base:
count = 0
@classmethod
def increment(cls):
cls.count += 1
print(f"{cls.__name__} count = {cls.count}")
class Child(Base):
pass
Base.increment()
Child.increment()
4.3 实现多态工厂(根据子类返回不同实例)
class Person:
@classmethod
def create(cls, action):
if action == "学习":
return Student()
elif action == "教书":
return Teacher()
else:
return cls()
class Student(Person):
pass
class Teacher(Person):
pass
a = Person.create("学习")
print(type(a))
b = Person.create("教书")
print(type(b))
c = Person.create("治病")
print(type(c))
4.4 用于配置或全局状态的访问
class Config:
_settings = {"host": "epics", "port": 5064}
@classmethod
def get(cls, key):
return cls._settings.get(key)
@classmethod
def set(cls, key, value):
cls._settings[key] = value
Config.set("IP","192.168.0.1")
print(f"Host:{Config.get('host')}, IP:{Config.get('IP')},Port:{Config.get('port')}")
运行结果:
Host:epics, IP:192.168.0.1,Port:5064
5. 继承中的行为
类方法会遵循继承链,cls 始终指向实际调用它的类。
class Base:
@classmethod
def identify(cls):
return cls.__name__
class Child(Base):
pass
print(Base.identify())
print(Child.identify())
运行结果:
Base
Child
6. 类方法 vs 静态方法:如何选择?
- 需要访问类本身或类属性 → 使用 @classmethod
- 需要访问实例属性 → 使用实例方法
- 不需要任何类或实例上下文,只是逻辑分组 → 使用 @staticmethod
7. classmethod的完整实例
class Student:
def __init__(self, name, age, grade):
self.name = name
self.age = age
self.grade = grade
def printInfo(self):
print(f"{self.name}-{self.age}-{self.grade}")
@classmethod
def from_json(cls, json_str):
import json
data = json.loads(json_str)
return cls(data['name'], data['age'], data['grade'])
@classmethod
def from_csv(cls, csv_line):
title, author, price = csv_line.strip().split(',')
return cls(title, author, int(price))
# 使用
json_data = '{"name": "张三", "age": "18", "grade": 2}'
stu1 = Student.from_json(json_data)
csv_data = "李四, 16 , 3"
stu2 = Student.from_csv(csv_data)
stu1.printInfo()
stu2.printInfo()
执行结果:
张三-18-2
李四- 16 -3更多推荐



所有评论(0)