Python 面向对象编程
面向对象编程(OOP)是一种程序设计思想。本章将介绍类和对象的核心概念。
类和对象基础
什么是类?
类是一种抽象的数据类型,它定义了一类事物的共同属性和行为。
什么是对象?
对象是类的实例,是具体的存在。
定义类
class Person:
"""人类"""
# 类属性(所有实例共享)
species = "智人"
# 初始化方法
def __init__(self, name, age):
# 实例属性
self.name = name
self.age = age
# 实例方法
def say_hello(self):
print(f"你好,我叫{self.name},今年{self.age}岁")
# 私有方法(以双下划线开头)
def __private_method(self):
print("这是私有方法")
# 魔术方法
def __str__(self):
return f"Person: {self.name}, {self.age}"
创建对象
person = Person("张三", 20)
print(person.name) # 张三
print(person.age) # 20
person.say_hello() # 你好,我叫张三,今年20岁
print(person) # Person: 张三, 20
self 参数
self 指向当前对象本身,类似于其他语言中的 this。
class Dog:
def __init__(self, name):
self.name = name
def bark(self):
# self 指向调用此方法的对象
print(f"{self.name} 叫了一声")
初始化方法 init
__init__ 在创建对象时自动调用,用于初始化对象的属性。
class Car:
def __init__(self, brand, color):
self.brand = brand
self.color = color
self.speed = 0
def drive(self):
print(f"{self.color}的{self.brand}汽车正在行驶")
car = Car("比亚迪", "红色")
car.drive() # 红色的比亚迪汽车正在行驶
属性
实例属性
每个对象独有的属性:
class Person:
def __init__(self, name):
self.name = name # 实例属性
person1 = Person("张三")
person2 = Person("李四")
print(person1.name) # 张三
print(person2.name) # 李四
类属性
所有对象共享的属性:
class Person:
species = "智人" # 类属性
def __init__(self, name):
self.name = name
print(Person.species) # 智人
person = Person("张三")
print(person.species) # 智人(通过实例访问类属性)
属性访问优先级
实例属性 > 类属性
class Person:
name = "人类" # 类属性
def __init__(self, name):
self.name = name # 实例属性
person = Person("张三")
print(person.name) # 张三(优先访问实例属性)
print(Person.name) # 人类(访问类属性)
使用 property 装饰器
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
@property
def area(self):
return 3.14 * self._radius ** 2
circle = Circle(5)
print(circle.radius) # 5
print(circle.area) # 78.5
circle.radius = 10
print(circle.area) # 314.0
方法类型
实例方法
class Person:
def __init__(self, name):
self.name = name
def say_hello(self): # 实例方法
print(f"你好,我叫{self.name}")
类方法
使用 @classmethod 装饰器,第一个参数是类本身:
class Person:
count = 0 # 类属性
def __init__(self, name):
self.name = name
Person.count += 1
@classmethod
def get_count(cls):
return cls.count
print(Person.get_count()) # 0
person = Person("张三")
print(Person.get_count()) # 1
静态方法
使用 @staticmethod 装饰器,不需要 self 或 cls 参数:
class Math:
@staticmethod
def add(a, b):
return a + b
result = Math.add(3, 5) # 8
print(Math.add(1, 2)) # 3
访问权限
公有属性和方法
class Person:
def __init__(self, name):
self.name = name # 公有属性
def public_method(self): # 公有方法
print("公有方法")
私有属性和方法
使用双下划线 __ 前缀:
class Person:
def __init__(self, name):
self.__name = name # 私有属性
def __private_method(self): # 私有方法
print("私有方法")
def public_method(self):
# 可以在类内部访问私有成员
print(f"姓名:{self.__name}")
self.__private_method()
person = Person("张三")
person.public_method() # 姓名:张三 私有方法
# person.__name # 错误:无法直接访问
# person.__private_method() # 错误:无法直接访问
访问私有属性(不推荐)
# 使用 name mangling
person._Person__name # 张三
person._Person__private_method() # 私有方法
保护属性
使用单下划线 _ 前缀,表示protected(受保护):
class Person:
def __init__(self, name):
self._name = name # 保护属性
person = Person("张三")
print(person._name) # 可以访问,但不推荐
继承
基本语法
# 父类
class Animal:
def __init__(self, name):
self.name = name
def eat(self):
print(f"{self.name}在吃饭")
def sleep(self):
print(f"{self.name}在睡觉")
# 子类
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # 调用父类的初始化方法
self.breed = breed # 子类新增属性
def bark(self): # 子类新增方法
print(f"{self.name}叫了一声")
def eat(self): # 重写父类方法
print(f"{self.name}正在吃狗粮")
dog = Dog("旺财", "金毛")
dog.eat() # 旺财正在吃狗粮(重写的方法)
dog.sleep() # 旺财在睡觉(继承的方法)
dog.bark() # 旺财叫了一声(子类新增的方法)
多继承
class Flyable:
def fly(self):
print("可以飞")
class Swimmable:
def swim(self):
print("可以游泳")
class Duck(Animal, Flyable, Swimmable):
pass
duck = Duck("鸭子")
duck.eat()
duck.fly()
duck.swim()
方法解析顺序(MRO)
class A:
pass
class B(A):
pass
class C(A):
pass
class D(B, C):
pass
print(D.__mro__) # (<class '__main__.D'>, <class '__main__.B'>, <class '__main__.C'>, <class '__main__.A'>, <class 'object'>)
多态
同一接口,不同实现:
class Animal:
def speak(self):
pass
class Dog(Animal):
def speak(self):
print("汪汪")
class Cat(Animal):
def speak(self):
print("喵喵")
class Cow(Animal):
def speak(self):
print("哞哞")
# 多态调用
animals = [Dog(), Cat(), Cow()]
for animal in animals:
animal.speak()
# 输出:
# 汪汪
# 喵喵
# 哞哞
特殊方法(魔术方法)
| 方法 | 描述 | 示例 |
|---|---|---|
__init__ | 初始化方法 | 对象创建时调用 |
__str__ | 字符串表示 | print(obj) 时调用 |
__repr__ | 调试字符串 | repr(obj) 时调用 |
__len__ | 长度 | len(obj) 时调用 |
__add__ | 加法 | obj1 + obj2 时调用 |
__eq__ | 相等 | obj1 == obj2 时调用 |
__lt__ | 小于 | obj1 < obj2 时调用 |
示例
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 2
def __getitem__(self, index):
if index == 0:
return self.x
elif index == 1:
return self.y
else:
raise IndexError("索引超出范围")
v1 = Vector(1, 2)
v2 = Vector(3, 4)
print(v1) # Vector(1, 2)
print(v1 + v2) # Vector(4, 6)
print(v1 == v2) # False
print(len(v1)) # 2
print(v1[0]) # 1
抽象类和接口
使用 abc 模块创建抽象类:
from abc import ABC, abstractmethod
class Shape(ABC):
@abstractmethod
def area(self):
pass
@abstractmethod
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)
rect = Rectangle(5, 3)
print(rect.area()) # 15
print(rect.perimeter()) # 16
# 抽象类不能直接实例化
# shape = Shape() # 错误
小结
本章我们学习了:
- 类和对象的概念
- 类的定义和对象的创建
- 初始化方法
__init__ - 属性(实例属性、类属性)
- 方法类型(实例方法、类方法、静态方法)
- 访问权限(公有、私有、保护)
- 继承和多继承
- 多态
- 特殊方法(魔术方法)
- 抽象类
练习
- 创建一个学生类,包含姓名、学号、成绩属性
- 创建一个银行账户类,支持存款、取款、查询余额
- 实现一个图形类层次结构(圆形、矩形、三角形)
- 实现一个栈数据结构(压入、弹出、查看栈顶)