类方法与静态方法
除了普通实例方法,Python 类还可以定义类方法(classmethod)和静态方法(staticmethod)。它们各自解决不同的问题,理解它们的区别能帮助你设计更清晰的类接口。
实例方法
普通方法通过实例调用,第一个参数 self 是实例引用:
class Dog(object):
def __init__(self, name):
self.name = name
def bark(self): # 实例方法
return "%s says woof!" % self.name
d = Dog("Fido")
print d.bark() # Fido says woof!
类方法 @classmethod
类方法的第一个参数是类本身(通常命名为 cls),通过类或实例都可以调用:
class Dog(object):
species = "Canis lupus familiaris"
def __init__(self, name):
self.name = name
@classmethod
def create_stray(cls): # cls 是 Dog 类
return cls("Stray Dog")
@classmethod
def get_species(cls):
return cls.species
d = Dog.create_stray() # 通过类调用
print d.name # Stray Dog
print d.get_species() # 通过实例调用也可以
print Dog.get_species() # Canis lupus familiaris
类方法常用于:
- 替代构造方法(工厂方法):提供多种创建实例的方式
- 访问类变量:操作与类相关而非实例相关的数据
class Date(object):
def __init__(self, year, month, day):
self.year = year
self.month = month
self.day = day
@classmethod
def from_string(cls, s):
"""从 'YYYY-MM-DD' 字符串创建日期。"""
parts = s.split("-")
return cls(int(parts[0]), int(parts[1]), int(parts[2]))
@classmethod
def today(cls):
"""创建今天的日期。"""
import time
t = time.localtime()
return cls(t.tm_year, t.tm_mon, t.tm_mday)
d1 = Date(2024, 1, 15)
d2 = Date.from_string("2024-01-15")
d3 = Date.today()
from_string 和 today 是工厂方法——它们提供不同于 __init__ 的实例创建方式,同时返回正确的类型(如果用继承,cls 会是子类)。
静态方法 @staticmethod
静态方法不接收隐式的第一个参数(没有 self 或 cls),只是"住在类里的普通函数":
class MathUtils(object):
@staticmethod
def add(x, y):
return x + y
@staticmethod
def is_prime(n):
if n < 2:
return False
for i in range(2, int(n ** 0.5) + 1):
if n % i == 0:
return False
return True
print MathUtils.add(3, 5) # 8
print MathUtils.is_prime(17) # True
# 也可以通过实例调用(但不推荐)
utils = MathUtils()
print utils.add(3, 5) # 8
静态方法常用于:
- 工具函数:与类概念相关但不需要访问类或实例的函数
- 组织命名空间:把相关函数放在类下,避免全局命名空间污染
三者对比
| 特性 | 实例方法 | 类方法 | 静态方法 |
|---|---|---|---|
| 装饰器 | 无 | @classmethod | @staticmethod |
| 第一个参数 | self(实例) | cls(类) | 无 |
| 访问实例属性 | 是 | 否 | 否 |
| 访问类属性 | 通过 self | 直接 | 通过类名 |
| 调用方式 | obj.method() | Class.method() 或 obj.method() | Class.method() 或 obj.method() |
实际应用
单例模式(类方法):
class Singleton(object):
_instance = None
@classmethod
def get_instance(cls):
if cls._instance is None:
cls._instance = cls()
return cls._instance
s1 = Singleton.get_instance()
s2 = Singleton.get_instance()
print s1 is s2 # True
验证工具(静态方法):
class Validator(object):
@staticmethod
def is_email(s):
import re
return re.match(r"[^@]+@[^@]+\.[^@]+", s) is not None
@staticmethod
def is_phone(s):
return s.isdigit() and len(s) == 11
print Validator.is_email("test@example.com") # True
print Validator.is_phone("13800138000") # True
选择建议
- 需要访问实例属性 → 实例方法
- 需要访问类属性或创建实例 → 类方法
- 不需要访问类或实例,只是组织命名空间 → 静态方法
- 静态方法也可以用模块级函数替代,选择取决于团队约定