深入python 类和对象编程范式
概念
定义类
class MyClass:
# 类变量,所有实例共享
class_var = "This is a class variable."
def __init__(self, instance_var):
# 实例变量,每个实例独立
self.instance_var = instance_var
def method(self):
# 实例方法,可以访问实例变量
print(f"This is an instance method. Instance variable: {self.instance_var}")
对象的概念
对象是类的一个实例。当你创建一个类的实例时,实际上是根据该类的定义分配内存,并初始化该对象的属性。
创建对象
# 创建MyClass的一个实例
obj = MyClass("This is an instance variable.")
# 访问对象的属性
print(obj.instance_var) # 输出: This is an instance variable.
# 调用对象的方法
obj.method() # 输出: This is an instance method. Instance variable: This is an instance variable.
类的成员
1. 实例变量
实例变量是在__init__方法中定义的变量,它们属于每个实例,每个实例都有自己的一份副本。
2. 类变量
类变量是在类定义体中定义的变量,它们不属于任何一个实例,而是所有实例共享的。通常用于存储所有对象共有的信息。
3. 方法
方法是与类关联的函数,它们可以访问和修改实例变量。Python中的方法默认接受第一个参数self,它是指向实例本身的引用。
继承
基础示例
class Animal:
def speak(self):
raise NotImplementedError("Subclass must implement this abstract method")
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
# 创建Dog和Cat的实例
dog = Dog()
cat = Cat()
# 调用speak方法
print(dog.speak()) # 输出: Woof!
print(cat.speak()) # 输出: Meow!
在这个例子中,Dog和Cat都继承自Animal类,并且覆盖了speak方法。
特殊方法
常见的特殊方法
__init__(self, ...):初始化方法,当创建一个新实例时被调用。
__str__(self):返回一个描述对象的易读字符串。
__repr__(self):返回一个包含对象信息的字符串,主要用于调试。
__eq__(self, other):定义对象相等的条件。
__lt__(self, other):定义小于操作符 < 的行为。
__add__(self, other):定义加法操作的行为。
基础示例
class Point:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __str__(self):
return f"Point({self.x}, {self.y})"
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
def __eq__(self, other):
return self.x == other.x and self.y == other.y
def __add__(self, other):
return Point(self.x + other.x, self.y + other.y)
# 创建两个点
p1 = Point(1, 2)
p2 = Point(3, 4)
# 使用特殊方法
print(p1) # 输出: Point(1, 2)
print(repr(p1)) # 输出: Point(x=1, y=2)
print(p1 == p2) # 输出: False
print(p1 + p2) # 输出: Point(4, 6)
类和对象进阶示例
在这个示例中,我们将展示如何使用私有属性和属性访问器方法来保护类的内部状态。
class BankAccount:
def __init__(self, balance=0):
self.__balance = balance
def deposit(self, amount):
if amount > 0:
self.__balance += amount
else:
raise ValueError("Deposit amount must be positive.")
def withdraw(self, amount):
if amount > 0 and amount <= self.__balance:
self.__balance -= amount
else:
raise ValueError("Withdrawal amount must be positive and less than or equal to the current balance.")
def get_balance(self):
return self.__balance
# 创建账户实例
account = BankAccount()
# 存款
account.deposit(1000)
# 提款
account.withdraw(500)
# 获取余额
print(account.get_balance()) # 输出: 500
在这个例子中,我们使用双下划线前缀(__balance)来声明一个私有属性,外部代码无法直接访问或修改这个属性。我们提供了deposit、withdraw和get_balance方法来控制对这个属性的操作。
使用继承和多态
在这个示例中,我们将展示如何使用继承来创建具有共同特征的不同类,并通过多态来实现方法的重写。
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
raise NotImplementedError("Subclass must implement this abstract method")
class Dog(Animal):
def speak(self):
return f"{self.name} says Woof!"
class Cat(Animal):
def speak(self):
return f"{self.name} says Meow!"
# 创建动物实例
dog = Dog("Buddy")
cat = Cat("Whiskers")
# 调用speak方法
print(dog.speak()) # 输出: Buddy says Woof!
print(cat.speak()) # 输出: Whiskers says Meow!
# 多态示例
def animal_sound(animal):
print(animal.speak())
animal_sound(dog) # 输出: Buddy says Woof!
animal_sound(cat) # 输出: Whiskers says Meow!
在这个例子中,Dog和Cat类都继承自Animal类,并且覆盖了speak方法。animal_sound函数接收一个Animal类型的参数,并调用speak方法,这展示了多态的概念——不同类型的对象可以以相同的方式被对待。
使用特殊方法实现运算符重载
在这个示例中,我们将展示如何使用特殊方法来实现运算符重载,使自定义类能够像内置类型一样支持加法、减法等操作。
class Vector:
def __init__(self, x=0, y=0):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
# 创建向量实例
v1 = Vector(1, 2)
v2 = Vector(3, 4)
# 向量加法
result_add = v1 + v2
print(result_add) # 输出: Vector(4, 6)
# 向量减法
result_sub = v1 - v2
print(result_sub) # 输出: Vector(-2, -2)
在这个例子中,我们定义了Vector类,并实现了__add__和__sub__特殊方法,使得两个Vector对象可以相加或相减。
使用类方法和静态方法
在这个示例中,我们将展示如何使用类方法和静态方法来扩展类的功能。
class Employee:
num_of_employees = 0
raise_amount = 1.04
def __init__(self, first, last, pay):
self.first = first
self.last = last
self.email = f"{first}.{last}@company.com"
self.pay = pay
Employee.num_of_employees += 1
def fullname(self):
return f"{self.first} {self.last}"
def apply_raise(self):
self.pay = int(self.pay * self.raise_amount)
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
@classmethod
def from_string(cls, emp_str):
first, last, pay = emp_str.split("-")
return cls(first, last, pay)
@staticmethod
def is_workday(day):
if day.weekday() == 5 or day.weekday() == 6:
return False
return True
# 创建员工实例
emp_1 = Employee("John", "Doe", 60000)
emp_2 = Employee("Jane", "Smith", 70000)
# 使用类方法
Employee.set_raise_amount(1.05)
print(Employee.raise_amount) # 输出: 1.05
# 使用类方法从字符串创建实例
emp_str_1 = "Michael-Brown-70000"
new_emp = Employee.from_string(emp_str_1)
print(new_emp.email) # 输出: Michael.Brown@company.com
# 使用静态方法
import datetime
my_date = datetime.date(2024, 9, 16)
print(Employee.is_workday(my_date)) # 输出: True 或 False,取决于日期
在这个例子中,我们定义了Employee类,并实现了类方法和静态方法。类方法set_raise_amount用于设置所有员工的加薪比例,from_string用于从字符串创建员工实例,静态方法is_workday用于判断给定日期是否为工作日。
来源:测试开发学习交流