跳到主要内容

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() # 错误

小结

本章我们学习了:

  1. 类和对象的概念
  2. 类的定义和对象的创建
  3. 初始化方法 __init__
  4. 属性(实例属性、类属性)
  5. 方法类型(实例方法、类方法、静态方法)
  6. 访问权限(公有、私有、保护)
  7. 继承和多继承
  8. 多态
  9. 特殊方法(魔术方法)
  10. 抽象类

练习

  1. 创建一个学生类,包含姓名、学号、成绩属性
  2. 创建一个银行账户类,支持存款、取款、查询余额
  3. 实现一个图形类层次结构(圆形、矩形、三角形)
  4. 实现一个栈数据结构(压入、弹出、查看栈顶)