在 Python 类中,主要有以下几种类型的函数,每种都有不同的用途和特性:

## 1. 实例方法 (Instance Methods)

最常见的类型,第一个参数是 `self`,指向实例本身。

```python
class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
    # 实例方法
    def introduce(self):
        return f"我叫{self.name},今年{self.age}岁"
    
    def have_birthday(self):
        self.age += 1
        return self.age

# 使用
person = Person("张三", 25)
print(person.introduce())  # 我叫张三,今年25岁
person.have_birthday()
print(person.introduce())  # 我叫张三,今年26岁
```

## 2. 类方法 (Class Methods)

使用 `@classmethod` 装饰器,第一个参数是 `cls`,指向类本身。

```python
class Person:
    species = "人类"
    
    def __init__(self, name):
        self.name = name
    
    @classmethod
    def get_species(cls):
        return cls.species
    
    @classmethod
    def create_anonymous(cls):
        """类方法作为替代构造函数"""
        return cls("匿名用户")
    
    @classmethod
    def from_birth_year(cls, name, birth_year):
        """另一个替代构造函数"""
        from datetime import datetime
        age = datetime.now().year - birth_year
        instance = cls(name)
        instance.age = age
        return instance

# 使用
print(Person.get_species())  # 人类

anonymous = Person.create_anonymous()
print(anonymous.name)  # 匿名用户

person = Person.from_birth_year("李四", 1990)
print(f"{person.name} 大约 {person.age} 岁")
```

## 3. 静态方法 (Static Methods)

使用 `@staticmethod` 装饰器,不需要 `self` 或 `cls` 参数。

```python
class MathUtils:
    @staticmethod
    def add(x, y):
        return x + y
    
    @staticmethod
    def is_adult(age):
        return age >= 18
    
    @staticmethod
    def validate_email(email):
        import re
        pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
        return re.match(pattern, email) is not None

# 使用
print(MathUtils.add(5, 3))  # 8
print(MathUtils.is_adult(20))  # True
print(MathUtils.validate_email("test@example.com"))  # True
```

## 4. 属性方法 (Property Methods)

使用 `@property` 装饰器,将方法作为属性访问。

```python
class Circle:
    def __init__(self, radius):
        self._radius = radius
    
    @property
    def radius(self):
        """获取半径"""
        return self._radius
    
    @radius.setter
    def radius(self, value):
        """设置半径,确保为正数"""
        if value <= 0:
            raise ValueError("半径必须为正数")
        self._radius = value
    
    @radius.deleter
    def radius(self):
        """删除半径时的操作"""
        print("删除半径")
        del self._radius
    
    @property
    def diameter(self):
        """直径(只读属性)"""
        return self._radius * 2
    
    @property
    def area(self):
        """面积(只读属性)"""
        return 3.14159 * self._radius ** 2

# 使用
circle = Circle(5)
print(circle.radius)    # 5
print(circle.diameter)  # 10
print(circle.area)      # 78.53975

circle.radius = 10      # 调用setter
print(circle.area)      # 314.159

# circle.radius = -5    # 抛出 ValueError
```

## 5. 私有方法 (Private Methods)

以双下划线 `__` 开头的方法,只能在类内部访问。

```python
class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # 私有属性
    
    def deposit(self, amount):
        """公开方法"""
        self.__validate_amount(amount)
        self.__balance += amount
    
    def withdraw(self, amount):
        """公开方法"""
        self.__validate_amount(amount)
        if amount <= self.__balance:
            self.__balance -= amount
            return True
        return False
    
    def __validate_amount(self, amount):
        """私有方法,只能在类内部调用"""
        if amount <= 0:
            raise ValueError("金额必须为正数")
    
    def get_balance(self):
        return self.__balance

# 使用
account = BankAccount(1000)
account.deposit(500)
print(account.get_balance())  # 1500

# account.__validate_amount(100)  # 错误!无法访问私有方法
```

## 6. 特殊方法 (Magic/Dunder Methods)

以双下划线开头和结尾的方法,用于运算符重载等特殊操作。

```python
class Vector:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    def __str__(self):
        return f"Vector({self.x}, {self.y})"
    
    def __repr__(self):
        return f"Vector({self.x}, {self.y})"
    
    def __add__(self, other):
        return Vector(self.x + other.x, self.y + other.y)
    
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    
    def __len__(self):
        """返回向量的模(长度)的整数部分"""
        return int((self.x**2 + self.y**2)**0.5)
    
    def __getitem__(self, index):
        if index == 0:
            return self.x
        elif index == 1:
            return self.y
        else:
            raise IndexError("向量只有两个分量")

# 使用
v1 = Vector(3, 4)
v2 = Vector(1, 2)

print(v1)           # Vector(3, 4)
print(v1 + v2)      # Vector(4, 6)
print(v1 == v2)     # False
print(len(v1))      # 5
print(v1[0])        # 3
```

总结对比:

类型 装饰器 第一个参数 访问方式 主要用途
实例方法 self 实例.method() 操作实例数据
类方法 @classmethod cls 类.method() 或 实例.method() 操作类属性,替代构造函数
静态方法 @staticmethod 类.method() 或 实例.method() 工具函数,与类相关但不依赖实例或类
属性方法 @property self 实例.property 像属性一样访问的方法
私有方法 无(命名约定) self 只能在类内部访问 内部实现细节
特殊方法 self 自动调用 运算符重载,特殊行为

这些不同类型的函数让 Python 的面向对象编程更加灵活和强大。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐