文章目录
- 前言
- 一、简介
- 二、基本操作
-
- [2.1 类的定义](#2.1 类的定义)
- [2.2 类的基本示例](#2.2 类的基本示例)
- [2.3 访问属性和方法](#2.3 访问属性和方法)
- [2.4 私有属性和方法](#2.4 私有属性和方法)
- [2.5 继承](#2.5 继承)
- [2.6 方法重写和扩展](#2.6 方法重写和扩展)
- [2.7 特殊方法(魔术方法)](#2.7 特殊方法(魔术方法))
- [2.8 属性装饰器](#2.8 属性装饰器)
- 三、面向对象编程的优势
前言
本文主要介绍了面向对象编程的基本概念和三大特性。
一、简介
面向对象编程(OOP)是一种对现实世界进行理解和抽象的编程范式。在面向对象的思想中,一切皆对象。Python 是一门支持面向对象的语言,面向对象编程本质上是一种封装代码的方式,使代码更易于维护、扩展和复用。
- 面向对象相关概念
- 类:描述具有相同属性和方法的对象的集合,是一个创建对象的模板。
- 对象:类的实例化结果。
- 方法:类中定义的函数。
- 类变量:定义在类中且在方法之外的变量,在所有实例化对象中共享。
- 实例变量:每个对象独有的变量。
- 局部变量:方法中定义的变量,只在方法内有效。
- 面向对象三大特性
- 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式,提高复用性和安全性。
- 继承:一个类继承基类便可拥有基类的属性和方法,提高代码复用性。
- 多态:父类定义的引用变量可以指向子类的实例对象,提高程序扩展性。
二、基本操作
2.1 类的定义
Python 中使用 class 关键字定义类,基本语法如下:
python
python
class 类名:
# 类变量(类属性)
类变量名 = 值
# 构造方法
def __init__(self, 参数):
# 实例变量(实例属性)
self.实例变量名 = 值
# 实例方法
def 方法名(self, 参数):
# 方法体
pass
# 类方法
@classmethod
def 类方法名(cls, 参数):
pass
# 静态方法
@staticmethod
def 静态方法名(参数):
pass
2.2 类的基本示例
python
python
class Cat:
"""猫类"""
# 类变量 - 所有猫共享的属性
species = 'Felis catus' # 物种
count = 0 # 统计创建的猫的数量
# 构造方法 - 在创建对象时自动调用
def __init__(self, name, age=1):
"""
初始化猫对象
:param name: 猫的名字
:param age: 猫的年龄,默认为1
"""
# 实例变量 - 每个猫独有的属性
self.name = name # 名字
self.age = age # 年龄
self.__weight = 2.5 # 私有属性:体重(kg)
# 每创建一个猫,计数器加1
Cat.count += 1
# 实例方法 - 第一个参数必须是self
def eat(self, food):
"""猫吃东西的方法"""
self.food = food # 设置食物属性
print(f'{self.name}正在吃{food}')
self.__weight += 0.1 # 吃完体重增加
return f'{self.name}吃完了{food}'
def meow(self):
"""猫叫的方法"""
return f'{self.name}说:喵喵~'
def get_weight(self):
"""获取体重(公有方法访问私有属性)"""
return f'{self.name}的体重是{self.__weight}kg'
def set_weight(self, weight):
"""设置体重(公有方法修改私有属性)"""
if weight > 0:
self.__weight = weight
return f'设置成功,当前体重{self.__weight}kg'
else:
return '体重必须大于0'
# 类方法 - 第一个参数必须是cls
@classmethod
def get_species(cls):
"""获取物种信息"""
return f'所有猫都属于物种:{cls.species}'
@classmethod
def create_baby_cat(cls, name):
"""创建一个刚出生的猫"""
return cls(name, age=0)
# 静态方法 - 不需要self或cls参数
@staticmethod
def animal_info():
"""提供猫科动物的静态信息"""
return '猫科动物(Felidae)是哺乳纲食肉目的一科'
2.3 访问属性和方法
python
python
# 1. 访问类变量(不需要创建对象)
print('=' * 50)
print('类变量访问:')
print(f'猫的物种:{Cat.species}')
print(f'已创建的猫数量:{Cat.count}')
# 2. 创建对象(实例化)
print('\n' + '=' * 50)
print('创建对象:')
cat1 = Cat('Tom', 3) # 创建名为Tom的3岁猫
cat2 = Cat('Kitty') # 创建名为Kitty的猫(使用默认年龄1岁)
print(f'已创建的猫数量:{Cat.count}') # 应该显示2
# 3. 访问实例属性和方法
print('\n' + '=' * 50)
print('实例属性和方法:')
# 访问实例属性
print(f'猫1的名字:{cat1.name}')
print(f'猫1的年龄:{cat1.age}')
# 调用实例方法
result = cat1.eat('鱼')
print(result)
print(cat1.meow())
# 4. 访问类方法
print('\n' + '=' * 50)
print('类方法:')
print(Cat.get_species()) # 通过类名访问
print(cat1.get_species()) # 通过对象访问
# 5. 访问静态方法
print('\n' + '=' * 50)
print('静态方法:')
print(Cat.animal_info())
# 6. 使用类方法创建对象
print('\n' + '=' * 50)
print('使用类方法创建对象:')
baby_cat = Cat.create_baby_cat('Baby')
print(f'新生猫的名字:{baby_cat.name}')
print(f'新生猫的年龄:{baby_cat.age}')
2.4 私有属性和方法
Python 中通过在属性或方法名前加双下划线 __ 来定义私有成员,外部不能直接访问:
python
python
class BankAccount:
"""银行账户类"""
def __init__(self, owner, initial_balance=0):
self.owner = owner # 公有属性:账户持有人
self.__balance = initial_balance # 私有属性:余额
self.__password = '123456' # 私有属性:密码
def __verify_password(self, password):
"""私有方法:验证密码"""
return password == self.__password
def deposit(self, amount, password):
"""存款方法"""
if not self.__verify_password(password):
return '密码错误,存款失败'
if amount > 0:
self.__balance += amount
return f'存款成功!当前余额:{self.__balance}元'
else:
return '存款金额必须大于0'
def withdraw(self, amount, password):
"""取款方法"""
if not self.__verify_password(password):
return '密码错误,取款失败'
if 0 < amount <= self.__balance:
self.__balance -= amount
return f'取款成功!当前余额:{self.__balance}元'
else:
return '余额不足或金额无效'
def get_balance(self, password):
"""查询余额"""
if not self.__verify_password(password):
return '密码错误,无法查询'
return f'当前余额:{self.__balance}元'
# 使用示例
print('=' * 50)
print('银行账户示例:')
account = BankAccount('张三', 1000)
print(f'账户持有人:{account.owner}')
# 正确的方式访问私有属性
print(account.deposit(500, '123456')) # 密码正确
print(account.withdraw(300, '123456')) # 密码正确
print(account.get_balance('123456')) # 密码正确
# 错误的方式(会报错或无法访问)
try:
print(account.__balance) # 报错:AttributeError
except AttributeError as e:
print(f'错误:{e}')
try:
account.__verify_password('123456') # 报错:AttributeError
except AttributeError as e:
print(f'错误:{e}')
2.5 继承
Python 支持单继承和多继承:
python
python
# 基类(父类)
class Animal:
"""动物基类"""
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self, food):
return f'{self.name}正在吃{food}'
def sleep(self):
return f'{self.name}正在睡觉'
def make_sound(self):
return '动物发出声音'
# 单继承
class Dog(Animal):
"""狗类 - 继承自动物类"""
def __init__(self, name, age, breed):
# 调用父类的构造方法
super().__init__(name, age)
# 添加狗特有的属性
self.breed = breed # 品种
self.__loyalty = 100 # 私有属性:忠诚度
# 重写父类方法
def make_sound(self):
return f'{self.name}汪汪叫!'
# 添加子类特有的方法
def fetch(self, item):
return f'{self.name}正在捡{item}'
def guard(self):
self.__loyalty += 10
return f'{self.name}正在看家,忠诚度提升到{self.__loyalty}'
# 单继承示例
print('=' * 50)
print('单继承示例:')
dog = Dog('旺财', 3, '金毛')
print(dog.eat('骨头')) # 继承自父类的方法
print(dog.sleep()) # 继承自父类的方法
print(dog.make_sound()) # 重写后的方法
print(dog.fetch('飞盘')) # 子类特有的方法
print(dog.guard()) # 子类特有的方法
print(f'品种:{dog.breed}') # 子类特有的属性
# 多继承
class Flyable:
"""可飞行的能力"""
def __init__(self, max_height):
self.max_height = max_height
def fly(self):
return f'最高可飞到{self.max_height}米'
class Swimmable:
"""可游泳的能力"""
def swim(self):
return '在水中游泳'
class Duck(Animal, Flyable, Swimmable):
"""鸭子类 - 多重继承"""
def __init__(self, name, age, max_height=100):
# 调用Animal的构造方法
Animal.__init__(self, name, age)
# 调用Flyable的构造方法
Flyable.__init__(self, max_height)
# 不需要调用Swimmable的构造方法(它没有__init__)
def make_sound(self):
return f'{self.name}嘎嘎叫!'
def all_abilities(self):
"""展示所有能力"""
abilities = [
self.make_sound(),
self.eat('虫子'),
self.fly(),
self.swim()
]
return abilities
# 多继承示例
print('\n' + '=' * 50)
print('多继承示例:')
duck = Duck('唐老鸭', 2, 50)
print(duck.make_sound()) # 重写的方法
print(duck.eat('小鱼')) # 继承自Animal
print(duck.fly()) # 继承自Flyable
print(duck.swim()) # 继承自Swimmable
print('\n展示所有能力:')
for ability in duck.all_abilities():
print(f'- {ability}')
# 方法解析顺序(MRO)
print('\n方法解析顺序:')
print(Duck.__mro__) # 显示类的继承顺序
2.6 方法重写和扩展
python
python
class Vehicle:
"""交通工具基类"""
def __init__(self, brand, model, speed=0):
self.brand = brand
self.model = model
self.speed = speed
def start(self):
return f'{self.brand} {self.model}启动'
def stop(self):
self.speed = 0
return f'{self.brand} {self.model}停止'
def get_info(self):
return f'品牌:{self.brand},型号:{self.model},当前速度:{self.speed}km/h'
class Car(Vehicle):
"""汽车类"""
def __init__(self, brand, model, fuel_type):
super().__init__(brand, model)
self.fuel_type = fuel_type # 燃料类型
self.__fuel_level = 100 # 私有属性:油量
# 扩展父类方法而不是完全重写
def start(self):
if self.__fuel_level > 0:
result = super().start() # 调用父类的start方法
return f'{result},油量:{self.__fuel_level}%'
else:
return '油量不足,无法启动'
# 重写父类方法
def get_info(self):
# 先获取父类的信息
base_info = super().get_info()
# 添加子类的信息
return f'{base_info},燃料类型:{self.fuel_type},油量:{self.__fuel_level}%'
# 添加子类特有的方法
def refuel(self, amount):
if amount > 0:
self.__fuel_level = min(100, self.__fuel_level + amount)
return f'加油成功,当前油量:{self.__fuel_level}%'
return '加油量无效'
# 方法重写和扩展示例
print('=' * 50)
print('方法重写和扩展示例:')
car = Car('Toyota', 'Camry', '汽油')
print(car.start())
print(car.get_info())
print(car.refuel(30))
2.7 特殊方法(魔术方法)
python
python
class Student:
"""学生类 - 演示特殊方法"""
def __init__(self, name, score):
self.name = name
self.score = score
# 字符串表示方法
def __str__(self):
return f'学生:{self.name},分数:{self.score}'
def __repr__(self):
return f'Student("{self.name}", {self.score})'
# 比较运算符重载
def __eq__(self, other):
if isinstance(other, Student):
return self.score == other.score
return False
def __lt__(self, other):
if isinstance(other, Student):
return self.score < other.score
return NotImplemented
def __gt__(self, other):
if isinstance(other, Student):
return self.score > other.score
return NotImplemented
# 算术运算符重载
def __add__(self, other):
if isinstance(other, (int, float)):
return Student(self.name, self.score + other)
return NotImplemented
# 调用对象时执行的方法
def __call__(self):
return f'{self.name}被调用啦!'
# 特殊方法示例
print('=' * 50)
print('特殊方法示例:')
s1 = Student('小明', 90)
s2 = Student('小红', 85)
print(str(s1)) # 调用__str__
print(repr(s1)) # 调用__repr__
print(s1 == s2) # 调用__eq__
print(s1 > s2) # 调用__gt__
print(s1 < s2) # 调用__lt__
s3 = s1 + 5 # 调用__add__
print(s3)
print(s1()) # 调用__call__
2.8 属性装饰器
python
python
class Person:
"""人类 - 演示属性装饰器"""
def __init__(self, name, age):
self._name = name # 受保护的属性
self._age = age
@property
def name(self):
"""获取name属性"""
return self._name
@name.setter
def name(self, value):
"""设置name属性"""
if not value or not value.strip():
raise ValueError("姓名不能为空")
self._name = value.strip()
@property
def age(self):
"""获取age属性"""
return self._age
@age.setter
def age(self, value):
"""设置age属性"""
if not isinstance(value, int):
raise TypeError("年龄必须是整数")
if value < 0 or value > 150:
raise ValueError("年龄必须在0-150之间")
self._age = value
@property
def info(self):
"""只读属性"""
return f'{self._name},{self._age}岁'
# 属性装饰器示例
print('=' * 50)
print('属性装饰器示例:')
person = Person('张三', 25)
print(person.name) # 使用property访问
print(person.age) # 使用property访问
print(person.info) # 只读属性
person.name = '李四' # 使用setter设置
person.age = 30 # 使用setter设置
print(person.info)
try:
person.name = '' # 会触发验证错误
except ValueError as e:
print(f'错误:{e}')
try:
person.age = 200 # 会触发验证错误
except ValueError as e:
print(f'错误:{e}')
三、面向对象编程的优势
- 代码复用:通过继承可以复用已有代码 模块化:将相关功能封装在类中,使代码结构更清晰
- 易维护:修改一个类的实现不会影响其他代码
- 可扩展:通过继承和多态轻松扩展功能 数据安全:通过封装保护数据,防止意外修改
- 通过合理使用面向对象编程,可以创建更健壮、更易维护的Python应用程序。