面向对象(一)
面向对象
-
概述
面向对象编程(Object-Oriented Programming, OOP)是一种编程范式,Python 完全支持 OOP。
-
四大基本特性
-
封装(Encapsulation)
- 将数据和操作数据的方法绑定在一起
- 隐藏对象的内部实现细节
- 通过访问控制限制对数据的直接访问
- 示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class BankAccount:
def __init__(self, account_holder, balance=0):
self._account_holder = account_holder # 保护属性
self.__balance = balance # 私有属性
def deposit(self, amount):
if amount > 0:
self.__balance += amount
def withdraw(self, amount):
if 0 < amount <= self.__balance:
self.__balance -= amount
def get_balance(self):
return self.__balance
-
继承(Inheritance)
- 子类继承父类的属性和方法
- 支持多重继承
- 可以重写(override)父类方法
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Animal:
def __init__(self, name):
self.name = name
def speak(self):
return "Some sound"
class Dog(Animal):
def speak(self):
return "Woof!"
class Cat(Animal):
def speak(self):
return "Meow!"
class RobotDog(Dog):
def speak(self):
return "Beep boop!"
-
多态(Polymorphism)
- 不同类的对象对同一消息做出不同响应
- 通过方法重写实现
- 示例
1
2
3
4
5
6
7
8
9
10def animal_sound(animal):
print(animal.speak())
dog = Dog("Buddy")
cat = Cat("Whiskers")
robot = RobotDog("Rex")
animal_sound(dog) # 输出: Woof!
animal_sound(cat) # 输出: Meow!
animal_sound(robot) # 输出: Beep boop!
-
抽象(Abstraction)
- 隐藏复杂实现细节,只暴露必要接口
- 通过抽象基类(ABC)实现
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21from abc import ABC, abstractmethod
class Shape(ABC):
def area(self):
pass
def perimeter(self):
pass
class Rectangle(Shape):
def __init__(self, width, height):
self.width = width
self.height = height
def area(self):
return self.width * self.height
def perimeter(self):
return 2 * (self.width + self.height)
-
-
高级特性
-
多重继承
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Flyable:
def fly(self):
return "I can fly!"
class Swimmable:
def swim(self):
return "I can swim!"
class Duck(Flyable, Swimmable):
pass
duck = Duck()
print(duck.fly()) # I can fly!
print(duck.swim()) # I can swim! -
方法解析顺序(MRO)
1
print(Duck.__mro__) # 显示方法解析顺序
-
类装饰器
1
2
3
4
5
6
7
8
9
10
11
12def add_method(cls):
def new_method(self):
return "This is a dynamically added method"
cls.new_method = new_method
return cls
class MyClass:
pass
obj = MyClass()
print(obj.new_method()) # This is a dynamically added method -
数据类(Python 3.7+)
1
2
3
4
5
6
7
8
9
10from dataclasses import dataclass
class Point:
x: float
y: float
z: float = 0.0 # 默认值
p = Point(1.5, 2.5)
print(p) # Point(x=1.5, y=2.5, z=0.0)
-
-
设计原则
- 单一职责原则(SRP): 一个类只负责一项职责
- 开放封闭原则(OCP): 对扩展开放,对修改封闭
- 里氏替换原则(LSP): 子类应该能够替换父类
- 接口隔离原则(ISP): 客户端不应被迫依赖不使用的接口
- 依赖倒置原则(DIP): 依赖抽象而非具体实现
类的语法
-
概述
类是 Python 面向对象编程(OOP)的核心概念,它允许用户创建自己的自定义数据类型,封装数据和功能。
-
基本概念
-
类的定义
1
2
3class MyClass:
"""这是一个简单的类示例"""
pass -
创建实例
1
my_instance = MyClass()
-
-
类的主要组成部分
-
构造函数
__init__
1
2
3
4class Person:
def __init__(self, name, age):
self.name = name # 实例属性
self.age = age -
实例方法
1
2
3
4
5
6
7class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def greet(self):
return f"Hello, my name is {self.name} and I'm {self.age} years old." -
类属性
1
2
3
4
5
6
7
8class Circle:
pi = 3.14159 # 类属性,所有实例共享
def __init__(self, radius):
self.radius = radius
def area(self):
return self.pi * self.radius ** 2 -
类方法
1
2
3
4
5
6
7class MyClass:
class_attribute = 0
def class_method(cls):
cls.class_attribute += 1
return cls.class_attribute -
静态方法
1
2
3
4class MathUtils:
def add(a, b):
return a + b
-
-
示例
小明手里有两张牌,左手♥K,右手♠A,问:小明交换两手的牌后,手里分别是什么?
思路:
- 先找到对象:小明、左手、♥K、♠A、右手
- 根据对象抽象出来的类:人、牌、手
- 写出对应的逻辑,反过来完善抽象出来的类
- 按照题目要求创建对应的对象,调用相关的方法
- 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56# 扑克牌
class Poker:
def __init__(self, color, number):
self.color = color
self.number = number
def __str__(self):
return '{}{}'.format(self.color, self.number)
# 创建两张牌
p1 = Poker('♥', 'K')
p2 = Poker('♠', 'A')
# 手的类
class Hand:
def __init__(self, poker=None):
self.poker = poker
def hold_poker(self, poker):
self.poker = poker
# 创建左右两只手的对象
left_hand = Hand(p1)
right_hand = Hand(p2)
# 人的类
class Person:
def __init__(self, name, left_hand, right_hand):
self.name = name
self.left_hand = left_hand
self.right_hand = right_hand
# 展示手里的牌
def show(self):
print('{}张开手'.format(self.name))
print('左手:{}'.format(self.left_hand.poker))
print('右手:{}'.format(self.right_hand.poker))
# 交换手里的牌
def swap(self):
self.left_hand.poker, self.right_hand.poker = self.right_hand.poker, self.left_hand.poker
print('{}交换两手的牌'.format(self.name))
# 创建小明对象
xiaoming = Person('小明', left_hand, right_hand)
# 展示手里的牌
xiaoming.show()
# 小明交换牌
xiaoming.swap()
# 再次展示手里的牌
xiaoming.show()
常见的内置函数
-
概述
Python 类中有许多特殊的内置函数(也称为"魔术方法"或"双下方法"),它们以双下划线开头和结尾。这些方法在特定情况下会被自动调用,用于实现类的各种行为。
-
对象生命周期相关
__new__(cls[, ...])
- 创建实例时调用的静态方法,在__init__
之前调用__init__(self[, ...])
- 构造函数,初始化对象时调用__del__(self)
- 析构函数,对象被销毁时调用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class MyClass:
def __new__(cls, *args, **kwargs):
print("创建实例 - __new__")
instance = super().__new__(cls)
return instance
def __init__(self, value):
print("初始化实例 - __init__")
self.value = value
def __del__(self):
print("销毁实例 - __del__")
obj = MyClass(10) # 输出: 创建实例 - __new__ 和 初始化实例 - __init__
del obj # 输出: 销毁实例 - __del__
-
字符串表示
__str__(self)
- 定义对象的字符串表示,用于str()
和print()
__repr__(self)
- 定义对象的官方字符串表示,用于repr()
和交互式解释器__format__(self, format_spec)
- 定义对象的格式化输出,用于format()
1
2
3
4
5
6
7
8
9
10
11
12
13
14class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __str__(self):
return f"{self.name} ({self.age}岁)"
def __repr__(self):
return f"Person('{self.name}', {self.age})"
p = Person("张三", 30)
print(str(p)) # 输出: 张三 (30岁)
print(repr(p)) # 输出: Person('张三', 30)
-
属性访问
__getattr__(self, name)
- 访问不存在的属性时调用__setattr__(self, name, value)
- 设置属性时调用__delattr__(self, name)
- 删除属性时调用__getattribute__(self, name)
- 访问任何属性时调用(优先级高于__getattr__
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class AttributeDemo:
def __init__(self):
self.data = {}
def __getattr__(self, name):
print(f"访问不存在的属性: {name}")
return None
def __setattr__(self, name, value):
print(f"设置属性: {name} = {value}")
super().__setattr__(name, value)
obj = AttributeDemo()
obj.existing = "值" # 触发 __setattr__
print(obj.existing) # 正常访问
print(obj.nonexistent) # 触发 __getattr__
-
容器类型模拟
__len__(self)
- 定义容器的长度,用于len()
__getitem__(self, key)
- 定义通过键访问元素,用于self[key]
__setitem__(self, key, value)
- 定义通过键设置元素,用于self[key] = value
__delitem__(self, key)
- 定义通过键删除元素,用于del self[key]
__contains__(self, item)
- 定义成员关系测试,用于in
操作符__iter__(self)
- 定义迭代器,用于iter()
和for
循环__next__(self)
- 定义迭代器的下一个值1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20class MyList:
def __init__(self, items):
self.items = list(items)
def __len__(self):
return len(self.items)
def __getitem__(self, index):
return self.items[index]
def __setitem__(self, index, value):
self.items[index] = value
def __contains__(self, item):
return item in self.items
lst = MyList([1, 2, 3])
print(len(lst)) # 输出: 3
print(lst[1]) # 输出: 2
print(3 in lst) # 输出: True
-
数值运算
__add__(self, other)
- 定义加法+
__sub__(self, other)
- 定义减法-
__mul__(self, other)
- 定义乘法*
__truediv__(self, other)
- 定义真除法/
__floordiv__(self, other)
- 定义地板除法//
__mod__(self, other)
- 定义取模%
__pow__(self, other[, modulo])
- 定义幂运算**
__and__(self, other)
- 定义按位与&
__or__(self, other)
- 定义按位或|
__xor__(self, other)
- 定义按位异或^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21class 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 __sub__(self, other):
return Vector(self.x - other.x, self.y - other.y)
def __mul__(self, scalar):
return Vector(self.x * scalar, self.y * scalar)
def __str__(self):
return f"Vector({self.x}, {self.y})"
v1 = Vector(2, 3)
v2 = Vector(1, 4)
print(v1 + v2) # 输出: Vector(3, 7)
print(v1 * 2) # 输出: Vector(4, 6)
-
比较操作
__eq__(self, other)
- 定义等于==
__ne__(self, other)
- 定义不等于!=
__lt__(self, other)
- 定义小于<
__le__(self, other)
- 定义小于等于<=
__gt__(self, other)
- 定义大于>
__ge__(self, other)
- 定义大于等于>=
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Book:
def __init__(self, title, pages):
self.title = title
self.pages = pages
def __eq__(self, other):
return self.pages == other.pages
def __lt__(self, other):
return self.pages < other.pages
def __le__(self, other):
return self.pages <= other.pages
book1 = Book("Python入门", 300)
book2 = Book("高级Python", 500)
print(book1 < book2) # 输出: True
print(book1 == book2) # 输出: False
-
其他重要方法
__call__(self[, ...])
- 使实例可以像函数一样被调用__enter__(self)
- 定义上下文管理器的进入行为,用于with
__exit__(self, exc_type, exc_value, traceback)
- 定义上下文管理器的退出行为__hash__(self)
- 定义对象的哈希值,用于hash()
和作为字典键__bool__(self)
- 定义对象的布尔值,用于bool()
和条件判断__dir__(self)
- 定义dir()
的行为,返回对象的属性列表1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class CallableDemo:
def __call__(self, *args):
print(f"被调用,参数: {args}")
callable_obj = CallableDemo()
callable_obj(1, 2, 3) # 输出: 被调用,参数: (1, 2, 3)
class ContextManagerDemo:
def __enter__(self):
print("进入上下文")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print("退出上下文")
with ContextManagerDemo() as cm:
print("在上下文中")