学无止境

少年辛苦终身事,莫向光阴惰寸功。——唐·杜荀鹤《题弟侄书堂》


Python面向对象高级特性详解

类属性

  • 类属性写在类下面
  • 0、类属性可以通过:
  • 类名.属性  或者  对象名.属性
    
  • 1、如何改变类属性的值
  •  类的属性修改要通过类名.属性=新值来修改
    
  • 2、如果有多个对象,类属性有什么变化

1. 对象生命周期方法

1.1 __del__方法

__del__方法是对象的析构方法,在对象被销毁时调用。

class ResourceManager:
    def __init__(self, name):
        self.name = name
        print(f"{self.name} 资源被创建")
    
    def __del__(self):
        print(f"{self.name} 资源被销毁")
        # 清理资源的代码

# 示例使用
def test_resource():
    r = ResourceManager("测试资源")
    # 当r离开作用域时,__del__会被调用
    
test_resource()
# 输出:
# 测试资源 资源被创建
# 测试资源 资源被销毁

1.2 引用计数管理

import sys

class Counter:
    def __init__(self, value):
        self.value = value

# 检查对象引用计数
obj = Counter(42)
print(f"引用计数: {sys.getrefcount(obj) - 1}")  # 减1是因为getrefcount本身会创建一个临时引用

# 创建新引用
obj2 = obj
print(f"新增引用后计数: {sys.getrefcount(obj) - 1}")

2. 面向对象的四大特征

2.1 封装(Encapsulation)

2.1.1 私有属性和方法

class BankAccount:
    def __init__(self):
        self.__balance = 0  # 私有属性
    
    def __validate_amount(self, amount):  # 私有方法
        return amount > 0
    
    def deposit(self, amount):
        if self.__validate_amount(amount):
            self.__balance += amount
            return True
        return False
    
    def get_balance(self):
        return self.__balance

# 使用示例
account = BankAccount()
account.deposit(100)
print(account.get_balance())  # 100
# print(account.__balance)  # AttributeError

2.1.2 属性访问器(Property)

class Person:
    def __init__(self):
        self.__age = 0
    
    @property
    def age(self):
        return self.__age
    
    @age.setter
    def age(self, value):
        if 0 <= value <= 150:
            self.__age = value
        else:
            raise ValueError("Invalid age")

person = Person()
person.age = 25  # 使用setter
print(person.age)  # 使用getter

2.2 继承(Inheritance)

2.2.1 基本继承

class Animal:
    def __init__(self, name):
        self.name = name
    
    def speak(self):
        pass

class Dog(Animal):
    def speak(self):
        return f"{self.name} says Woof!"

class Cat(Animal):
    def speak(self):
        return f"{self.name} says Meow!"

2.2.2 方法重写和super()

class Vehicle:
    def __init__(self, brand):
        self.brand = brand
    
    def start(self):
        return f"{self.brand} vehicle is starting"

class Car(Vehicle):
    def __init__(self, brand, model):
        super().__init__(brand)
        self.model = model
    
    def start(self):
        base_start = super().start()
        return f"{base_start} with {self.model} model"

2.2.3 多重继承

class Flying:
    def fly(self):
        return "Flying high!"

class Swimming:
    def swim(self):
        return "Swimming deep!"

class Duck(Flying, Swimming):
    def __init__(self, name):
        self.name = name
    
    def move(self):
        return f"{self.name} can {self.fly()} and {self.swim()}"

# 查看方法解析顺序
print(Duck.__mro__)

2.3 多态(Polymorphism)

def animal_sound(animal):
    return animal.speak()

# 多态使用示例
dog = Dog("Buddy")
cat = Cat("Whiskers")

print(animal_sound(dog))  # Buddy says Woof!
print(animal_sound(cat))  # Whiskers says Meow!

3. 类方法和静态方法

3.1 类方法

class DateUtil:
    date_format = "%Y-%m-%d"
    
    @classmethod
    def parse_date(cls, date_string):
        """解析日期字符串"""
        import datetime
        return datetime.datetime.strptime(date_string, cls.date_format)
    
    @classmethod
    def change_format(cls, new_format):
        """修改日期格式"""
        cls.date_format = new_format

# 使用类方法
date = DateUtil.parse_date("2023-01-01")

3.2 静态方法

class MathUtil:
    @staticmethod
    def is_even(number):
        return number % 2 == 0
    
    @staticmethod
    def is_prime(number):
        if number < 2:
            return False
        for i in range(2, int(number ** 0.5) + 1):
            if number % i == 0:
                return False
        return True

# 使用静态方法
print(MathUtil.is_even(4))  # True
print(MathUtil.is_prime(7))  # True

4. 特殊方法

4.1 __call__方法

class Multiplier:
    def __init__(self, factor):
        self.factor = factor
    
    def __call__(self, value):
        return self.factor * value

# 使用可调用对象
double = Multiplier(2)
print(double(5))  # 10

4.2 新式类与经典类

# Python 3中所有类都是新式类
class NewStyleClass:
    pass

# 查看基类
print(NewStyleClass.__bases__)  # (<class 'object'>,)

# 方法解析顺序
print(NewStyleClass.__mro__)

5. 最佳实践建议

5.1 封装使用建议

  1. 始终使用私有属性来保护数据
  2. 提供公共的访问器方法
  3. 使用property装饰器来控制属性访问

5.2 继承使用建议

  1. 优先使用组合而不是继承
  2. 避免深层继承结构
  3. 明确使用super()调用父类方法

5.3 方法选择建议

  1. 实例方法:需要访问实例状态时使用
  2. 类方法:需要访问类状态时使用
  3. 静态方法:不需要访问实例或类状态时使用