Python从设计之初就已经是一门面向对象的语言,正因为如此,在Python中创建一个类和对象是很容易的。
目录
1. 面向对象技术简介
1.1 面向对象编程概述
面向对象编程(Object-Oriented Programming,简称OOP)是一种以对象为基础的编程范式,它将数据和操作数据的方法组合成一个独立的单元——对象。Python作为一门现代编程语言,从设计之初就支持面向对象编程。
面向对象编程的核心思想是将现实世界中的事物抽象为程序中的对象。每个对象都包含两个主要特征:
-
属性:描述对象的状态(在编程中表现为变量)
-
方法:描述对象的行为(在编程中表现为函数)
1.2 面向对象的基本概念
1.2.1 类(Class)
类是创建对象的模板,它定义了对象将拥有的属性和方法。类可以看作是对象的蓝图或原型。例如,"汽车"类可以定义所有汽车共有的属性和行为。
1.2.2 对象(Object)
对象是类的实例。根据类创建对象的过程称为实例化。例如,根据"汽车"类可以创建"我的宝马"这个具体对象。
1.2.3 封装(Encapsulation)
封装是将数据(属性)和操作数据的方法绑定在一起的机制,同时对外隐藏实现的细节。在Python中,封装主要通过命名约定来实现:
-
单下划线开头
_var
:表示受保护的(protected)成员 -
双下划线开头
__var
:表示私有的(private)成员
1.2.4 继承(Inheritance)
继承允许一个类(子类)继承另一个类(父类)的属性和方法。这实现了代码的重用和层次化分类。例如,"电动汽车"类可以继承"汽车"类。
1.2.5 多态(Polymorphism)
多态指不同类的对象对同一消息做出不同响应。Python中的多态主要通过方法重写和鸭子类型实现。
1.3 面向对象的优势
-
模块化:将系统分解为多个独立的对象,便于开发和维护
-
重用性:通过继承机制可以重用已有代码
-
扩展性:通过多态可以方便地扩展系统功能
-
维护性:封装使得修改内部实现不影响外部使用
-
灵活性:多态提供了设计上的灵活性
1.4 Python中的面向对象特性
Python的面向对象实现有以下特点:
-
一切皆对象,包括类本身也是对象
-
动态性:可以在运行时修改类和对象
-
支持多重继承
-
使用特殊方法(魔术方法)实现运算符重载
-
通过描述符协议控制属性访问
2. 类定义
2.1 类的基本结构
在Python中,使用class
关键字定义类:
class ClassName:
"""类的文档字符串"""
class_attribute = value # 类属性
def __init__(self, parameters):
"""构造函数"""
self.instance_attribute = parameters # 实例属性
def instance_method(self, parameters):
"""实例方法"""
# 方法体
2.2 构造函数__init__
__init__
方法是Python中的构造函数,在创建对象时自动调用。它的第一个参数必须是self
,表示对象本身。
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
print(f"{name}对象被创建")
2.3 类属性与实例属性
-
类属性:属于类本身的属性,所有实例共享
-
实例属性:属于具体实例的属性
class Dog:
species = "Canis familiaris" # 类属性
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age
2.4 类的方法
类中的方法分为:
-
实例方法:第一个参数为
self
,操作实例属性 -
类方法:使用
@classmethod
装饰器,第一个参数为cls
,操作类属性 -
静态方法:使用
@staticmethod
装饰器,不接收特殊参数
class MyClass:
class_var = "类变量"
def instance_method(self):
print("实例方法")
@classmethod
def class_method(cls):
print("类方法")
@staticmethod
def static_method():
print("静态方法")
2.5 访问控制
Python没有严格的访问控制,但通过命名约定实现:
-
var
:公开成员 -
_var
:受保护成员(约定) -
__var
:私有成员(名称修饰)
class AccessExample:
def __init__(self):
self.public_var = "公开"
self._protected_var = "受保护"
self.__private_var = "私有"
def show_access(self):
print(f"内部访问: {self.public_var}")
print(f"内部访问: {self._protected_var}")
print(f"内部访问: {self.__private_var}")
# 测试访问
obj = AccessExample()
# 公开变量
print("=== 公开变量 ===")
print(obj.public_var) # 正常访问
obj.public_var = "新公开值"
print(obj.public_var)
# 受保护变量
print("\n=== 受保护变量 ===")
print(obj._protected_var) # 可以访问但会收到警告
obj._protected_var = "新受保护值"
# 私有变量
print("\n=== 私有变量 ===")
try:
print(obj.__private_var) # 直接访问失败
except AttributeError as e:
print(f"错误: {e}")
# 通过名称修饰访问(不推荐)
print(obj._AccessExample__private_var) # 可以访问但不应该这样做
# 内部访问
print("\n=== 内部方法访问 ===")
obj.show_access()
3. 类对象
3.1 实例化对象
使用类名加括号创建对象,会自动调用__init__
方法:
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
p = Point(3, 4) # 创建Point对象
3.2 访问对象属性
使用点号.
访问对象属性和方法:
print(p.x) # 输出: 3
print(p.y) # 输出: 4
3.3 修改对象属性
可以直接修改对象的属性:
p.x = 5
print(p.x) # 输出: 5
3.4 动态添加属性
Python允许在运行时动态添加属性:
p.z = 10 # 动态添加z属性
3.5 对象的方法调用
调用对象方法与访问属性类似:
class Counter:
def __init__(self):
self.count = 0
def increment(self):
self.count += 1
c = Counter()
c.increment() # 调用方法
3.6 对象的生命周期
Python对象生命周期包括:
-
创建:
__new__
和__init__
-
使用:方法调用和属性访问
-
销毁:
__del__
方法
class LifeCycle:
def __init__(self):
print("对象初始化")
def __del__(self):
print("对象销毁")
obj = LifeCycle() # 输出: 对象初始化
del obj # 输出: 对象销毁
4. 类的方法
4.1 实例方法
实例方法是最常见的方法类型,第一个参数为self
:
class Rectangle:
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
rect = Rectangle(5, 4)
print(rect.area()) # 输出: 20
4.2 类方法
使用@classmethod
装饰器定义,第一个参数为cls
:
class Pizza:
radius = 10
@classmethod
def get_area(cls):
return 3.14 * cls.radius ** 2
print(Pizza.get_area()) # 输出: 314.0
4.3 静态方法
使用@staticmethod
装饰器定义,不需要特殊参数:
class MathUtils:
@staticmethod
def add(a, b):
return a + b
print(MathUtils.add(3, 5)) # 输出: 8
4.4 方法重载
Python不支持传统的方法重载,但可以通过默认参数和可变参数实现类似功能:
class OverloadExample:
def method(self, x, y=None):
if y is None:
return x * 2
return x + y
obj = OverloadExample()
print(obj.method(5)) # 输出: 10
print(obj.method(2, 3)) # 输出: 5
4.5 特殊方法(魔术方法)
Python提供了许多特殊方法,用于实现特定功能:
class Vector:
def __init__(self, x, y):
self.x = x
self.y = y
def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(4, 5)
print(v1 + v2) # 输出: Vector(6, 8)
5. 继承
5.1 单继承
子类继承父类的所有属性和方法:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"我是{self.name}"
class Dog(Animal):
def speak(self):
return f"{self.name}说: 汪汪!"
dog = Dog("旺财")
print(dog.speak()) # 输出: 旺财说: 汪汪!
5.2 方法重写
子类可以重写父类的方法:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"我是{self.name}"
class Dog(Animal):
def speak(self):
return f"{self.name}说: 汪汪!"
class Cat(Animal):
def speak(self):
return f"{self.name}说: 喵喵~"
dog = Dog("旺财")
print(dog.speak()) # 输出: 旺财说: 汪汪!
cat = Cat("咪咪")
print(cat.speak()) # 输出: 咪咪说: 喵喵~
5.3 调用父类方法
使用super()
函数调用父类方法:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"我是{self.name}"
class Dog(Animal):
def speak(self):
return f"{self.name}说: 汪汪!"
class Bird(Animal):
def __init__(self, name, can_fly):
super().__init__(name)
self.can_fly = can_fly
def speak(self):
base_sound = super().speak()
return f"{base_sound} 我能飞!" if self.can_fly else f"{base_sound} 我不能飞"
dog = Dog("旺财")
print(dog.speak()) # 输出: 旺财说: 汪汪!
bird = Bird("凤凰", "皇冠")
print(bird.speak())
5.4 继承中的属性查找
Python使用MRO(Method Resolution Order)决定属性查找顺序:
class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return f"我是{self.name}"
class Dog(Animal):
def speak(self):
return f"{self.name}说: 汪汪!"
class Bird(Animal):
def __init__(self, name, can_fly):
super().__init__(name)
self.can_fly = can_fly
def speak(self):
base_sound = super().speak()
return f"{base_sound} 我能飞!" if self.can_fly else f"{base_sound} 我不能飞"
dog = Dog("旺财")
print(dog.speak()) # 输出: 旺财说: 汪汪!
bird = Bird("凤凰", "皇冠")
print(bird.speak())
print(Bird.__mro__) # 查看方法解析顺序
5.5 抽象基类
使用abc
模块定义抽象基类:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
def perimeter(self):
pass
class Circle(Shape):
def __init__(self, radius):
self.radius = radius
def area(self):
return 3.14 * self.radius ** 2
def perimeter(self):
return 2 * 3.14 * self.radius
6. 多继承
6.1 多继承语法
class DerivedClass(Base1, Base2, Base3):
pass
6.2 钻石继承问题
class A:
def method(self):
print("A的方法")
class B(A):
def method(self):
print("B的方法")
class C(A):
def method(self):
print("C的方法")
class D(B, C):
pass
d = D()
d.method() # 输出取决于MRO顺序
print(D.__mro__) # 查看方法解析顺序
6.3 方法解析顺序(MRO)
Python使用C3线性化算法确定方法查找顺序:
print(D.__mro__)
6.4 多继承的最佳实践
-
使用Mixin类
-
避免复杂的继承层次
-
明确指定方法调用
class Mixin1:
def feature1(self):
print("特性1")
class Mixin2:
def feature2(self):
print("特性2")
class MyClass(Mixin1, Mixin2):
pass
7. 方法重写
7.1 完全重写
子类完全重新实现父类方法:
class Parent:
def method(self):
print("父类方法")
class Child(Parent):
def method(self):
print("子类新实现")
7.2 扩展父类方法
使用super()
扩展而非替换父类方法:
class Child(Parent):
def method(self):
super().method()
print("子类新增功能")
7.3 重写特殊方法
class CustomList(list):
def __str__(self):
return f"自定义列表: {super().__str__()}"
7.4 重写类方法
class Parent:
@classmethod
def class_method(cls):
print("父类类方法")
class Child(Parent):
@classmethod
def class_method(cls):
super().class_method()
print("子类类方法")
8. 类属性与方法
8.1 类属性
类属性属于类本身,所有实例共享:
class Employee:
company = "ABC公司" # 类属性
def __init__(self, name):
self.name = name # 实例属性
8.2 类方法
类方法操作类属性:
class Employee:
raise_amount = 1.04
@classmethod
def set_raise_amount(cls, amount):
cls.raise_amount = amount
8.3 静态方法
静态方法与类和实例无关:
class DateUtils:
@staticmethod
def is_workday(day):
return day.weekday() < 5
8.4 属性装饰器
使用@property
创建计算属性:
class Circle:
def __init__(self, radius):
self.radius = radius
@property
def diameter(self):
return self.radius * 2
@diameter.setter
def diameter(self, value):
self.radius = value / 2
# 创建圆形对象
circle = Circle(5)
# 访问直径(自动计算)
print(f"半径: {circle.radius}") # 输出: 半径: 5
print(f"直径: {circle.diameter}") # 输出: 直径: 10
# 通过直径设置半径
circle.diameter = 14
print(f"新半径: {circle.radius}") # 输出: 新半径: 7
print(f"新直径: {circle.diameter}") # 输出: 新直径: 14
8.5 描述符协议
class PositiveNumber:
def __set_name__(self, owner, name):
self.name = name
def __get__(self, instance, owner):
return instance.__dict__[self.name]
def __set__(self, instance, value):
if value <= 0:
raise ValueError("必须是正数")
instance.__dict__[self.name] = value
class Order:
quantity = PositiveNumber()
def __init__(self, quantity):
self.quantity = quantity
# 正常创建订单
order1 = Order(5)
print(order1.quantity) # 输出: 5
# 尝试创建非法订单
try:
order2 = Order(-3) # 触发ValueError
except ValueError as e:
print(f"错误: {e}") # 输出: 错误: 必须是正数
# 尝试修改为非法值
try:
order1.quantity = -2 # 触发ValueError
except ValueError as e:
print(f"错误: {e}") # 输出: 错误: 必须是正数