当前位置: 首页 > news >正文

Python教程(十二):面向对象高级编程详解

目录

    • 专栏列表
    • 前言
    • 变量命名规则说明:
    • 一、类的内部变量和特殊方法
      • 1.1 内部变量
        • 示例
        • 测试结果:
      • 1.2 `__slots__`
        • 未使用`__slots__`
        • 使用`__slots__`
    • 二、装饰器
      • 2.1 函数装饰器
        • 示例
      • 2.2 @property
        • 示例
    • 三、枚举类
      • 3.1 枚举类概述
      • 3.2 枚举类定义
        • 示例
    • 四、元类
      • 4.1 什么是元类
      • 4.2 自定义元类
        • 示例
    • 结语

专栏列表

  • Python教程(一):环境搭建及PyCharm安装
  • Python 教程(二):语法与数据结构
  • Python 教程(三):字符串特性大全
  • Python 教程(四):Python运算符合集
  • Python 教程(五):理解条件语句和循环结构
  • Python 教程(六):函数式编程
  • Python 教程(七):match…case 模式匹配
  • Python 教程(八):高级特性【高逼格代码】
  • Python 教程(九):内置模块与第三方模块
  • Python教程(十):面向对象编程(OOP)
  • Python教程(十一):单元测试与异常捕获

在这里插入图片描述

正文开始如果觉得文章对您有帮助,请帮我三连+订阅,谢谢💖💖💖


前言

在学习了Python的基本面向对象编程(OOP)概念之后,本篇文章将深入探讨Python中的高级OOP特性。这些特性包括类的内部变量、特殊方法(Magic Methods)、装饰器、枚举类以及元类。通过对这些高级特性的介绍和实例演示,帮助你更好地掌握Python的面向对象编程。

变量命名规则说明:

单下划线、双下划线、头尾双下划线

  • _foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *

  • __foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的。

  • __foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

一、类的内部变量和特殊方法

1.1 内部变量

内部变量(Internal Variables)是指以双下划线开头(__)的变量,它们主要用于防止变量在子类中被意外覆盖。这种命名方式会触发Python的名称改写机制(Name Mangling),使变量名变得难以在类外部访问。

  • __init__ 的特殊方法(构造方法),在生成对象时调用,这个我们已经在前文介绍过了
  • __del__ : 析构函数,释放对象时使用
  • __repr__ : 打印,转换
  • __setitem__ : 按照索引赋值
  • __getitem__: 按照索引获取值
  • __len__: 获得长度
  • __cmp__: 比较运算
  • __call__: 函数调用
  • __add__: 加运算
  • __sub__: 减运算
  • __mul__: 乘运算
  • __truediv__: 除运算
  • __mod__: 求余运算
  • __pow__: 乘方
  • __str__:定义对象的字符串表示,print函数调用时使用。
示例

class Container:def __init__(self, *args):self.container = list(args)  # 初始化容器,接受可变数量的参数def __del__(self):print(f"对象 {id(self)} 正在被销毁。")def __repr__(self):return f"Container({self.container})"def __setitem__(self, key, value):self.container[key] = value  # 索引赋值def __getitem__(self, key):return self.container[key]  # 索引获取def __len__(self):return len(self.container)  # 获取容器长度def __cmp__(self, other):if not isinstance(other, Container):return NotImplementedreturn (self.container > other.container) - (self.container < other.container)def __call__(self, *args):print(f"Container 对象被调用,参数为:{args}")def __add__(self, other):if isinstance(other, Container):return Container(*(self.container + other.container)) # * 是用作解包操作,将list中的参数一个一个的传递,而不是传递一个listreturn NotImplementeddef __sub__(self, other):if isinstance(other, Container):return Container(*(self.container[:-1] if len(self.container) >= len(other.container) else self.container))return NotImplementeddef __mul__(self, other):if isinstance(other, int):return Container(*(self.container * other))return NotImplementeddef __truediv__(self, other):if isinstance(other, int) and other != 0:return Container(*(x / other for x in self.container))return NotImplementeddef __mod__(self, other):if isinstance(other, int):return Container(*(x % other for x in self.container))return NotImplementeddef __pow__(self, power):return Container(*(x ** power for x in self.container))def __str__(self):return f"Container 对象: {self.container}"# 测试代码
if __name__ == "__main__":c1 = Container(1, 2, 3)c2 = Container(4, 5)print(f"c1: {c1}")  # 使用 __str__print(f"c2: {c2}")c1[1] = 20  # 使用 __setitem__print(f"c1 修改后: {c1}")print(c1[1])  # 使用 __getitem__print(len(c1))  # 使用 __len__c3 = c1 + c2  # 使用 __add__print(f"c1 + c2: {c3}")c4 = c1 - c2  # 使用 __sub__print(f"c1 - c2: {c4}")c5 = c1 * 2  # 使用 __mul__print(f"c1 * 2: {c5}")c6 = c1 / 2  # 使用 __truediv__print(f"c1 / 2: {c6}")c7 = c1 % 3  # 使用 __mod__print(f"c1 % 3: {c7}")c8 = c1 ** 2  # 使用 __pow__print(f"c1 ** 2: {c8}")c1(123)  # 使用 __call__
测试结果:

在这里插入图片描述

1.2 __slots__

__slots__是一个特殊的类属性,用于控制类实例的动态属性的添加。默认情况下,Python的类是基于字典的,这意味着每个实例可以动态地添加任意数量的属性。但是,使用__slots__可以限制实例可以拥有的属性,只允许在__slots__中明确定义的属性。

使用__slots__有以下几个主要好处:

  1. 节省内存:通过限制属性的数量,可以减少内存的使用,因为不需要为每个实例创建一个字典来存储属性。
  2. 提高性能:访问预定义的属性比动态属性访问更快,因为预定义属性可以直接通过索引访问。
  3. 避免意外添加属性:使用__slots__可以确保类的实例不会意外地添加未定义的属性。
未使用__slots__
class Person:__init(self,*args)__:pass# 创建 Student 类的实例
p = Person()
p.name = '子羽'  
print(p.name)
使用__slots__

在定义类时,你可以在类定义的顶部添加一个特殊的__slots__属性,其值为一个包含允许属性名的元组或列表。

class Student:__slots__ = ('name', 'age', 'grade')  # 只允许 name, age, grade 三个属性# 创建 Student 类的实例
s = Student()
s.name = 'Alice'  # 正确,因为 'name' 在 __slots__ 中
s.age = 20        # 正确,因为 'age' 在 __slots__ 中
s.grade = 'A'    # 正确,因为 'grade' 在 __slots__ 中# 尝试添加未在 __slots__ 中定义的属性
s.address = '123 Main St'  # 抛出 AttributeError

在上面的例子中,尝试给s添加一个不在__slots__列表中的属性address将会抛出AttributeError

二、装饰器

2.1 函数装饰器

装饰器是一个高阶函数,用于在不改变原函数代码的情况下,动态地增加功能。装饰器通常用于日志记录、性能测试、事务处理等。

示例

def my_decorator(func):def wrapper(world):print("日志记录开始.")func(world)print("日志记录结束")return wrapper@my_decorator
def say_hello(world):print(f"Hello {world}!")say_hello('子羽')

在这里插入图片描述

2.2 @property

@property 是 Python 中的一个装饰器,用于将一个方法转变为属性访问的形式。这使得你可以使用点符号(.)来访问一个方法,就像访问一个普通的属性一样。
@property 通常用于当你想要属性值的获取有特定的逻辑处理时,例如,当你需要在获取属性值之前进行验证或计算。

示例

使用 @property 非常简单,你只需要在方法前加上 @property 装饰器,然后在该方法内部定义获取属性值的逻辑。下面是一个简单的例子:

class Circle:def __init__(self, radius):self._radius = radius  # 私有属性,用来存储圆的半径@propertydef radius(self):"""获取圆的半径"""return self._radius@radius.setterdef radius(self, value):"""设置圆的半径,可以包含验证逻辑"""if value < 0:raise ValueError("半径不能为负数")self._radius = value# 创建 Circle 类的实例
circle = Circle(5)# 使用 @property 获取属性
print(circle.radius)  # 输出: 5# 使用 @setter 设置属性
circle.radius = 10
print(circle.radius)  # 输出: 10# 尝试设置非法的半径值
circle.radius = -1  # 抛出 ValueError

三、枚举类

3.1 枚举类概述

枚举(Enum)是一种特殊的类,用于表示一组相关的常量值。枚举类中的每个成员都是唯一的,可以使用名称或值进行访问。

3.2 枚举类定义

可以使用Python的 enum 模块定义枚举类。

示例
from enum import Enum, autoclass Color(Enum):RED = auto() # 默认从 1 开始GREEN = auto()BLUE = auto()YELLOW = 5purple = 6print(Color.RED)  # 输出: Color.RED
print(Color.GREEN.name)  # 输出: GREEN
print(Color.GREEN.value)  # 输出: 2
print(Color.YELLOW.name)  # 输出: YELLOW
print(Color.YELLOW.value)  # 输出: 5

在这里插入图片描述

四、元类

4.1 什么是元类

元类(Metaclass)是用于创建类的类。默认情况下,Python中的所有类都是由 type 元类创建的。通过自定义元类,可以改变类的创建行为。

4.2 自定义元类

自定义元类需要继承自 type,并重写其方法,如 __new____init__

示例
class MyMeta(type):def __new__(cls, name, bases, dct):print(f"创建新类 :{name}")return super().__new__(cls, name, bases, dct)def __init__(cls, name, bases, dct):print(f"初始化类: {name}")super().__init__(name, bases, dct)class MyClass(metaclass=MyMeta):def __init__(self):print("创建 Myclass 类的示例")obj = MyClass()

在这里插入图片描述

结语

通过本篇文章,我们深入探讨了Python面向对象编程中的一些高级特性,包括类的内部变量、特殊方法、装饰器、枚举类和元类。这些高级特性能够帮助你编写更加灵活和强大的代码。如果你有任何疑问或想法,欢迎在评论区留言讨论。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • haproxy的安装和服务信息
  • 管好“黄金数据”,浪潮海岳助力企业释放主数据潜能
  • LVS集群中的负载均衡技术
  • springboot怎么使用Redisson
  • C#表达式编程指南: 执行表达式、解释表达式、生成表达式,翻译表达式的详解与示例
  • 【5G NAS】全球唯一临时标识符GUTI介绍
  • 准确率、召回率、f1指标计算的区别
  • MySQL:约束
  • 二十九、MongoDB(1)
  • 万界星空科技QMS系统:全面升级企业质量管理的利器
  • 用C34PRO打造一套高端性能主机
  • JavaFX布局-ButtonBar
  • 【Android】安卓四大组件之Service用法
  • QT生成.exe文件无法在未安装QT的电脑上运行的解决办法
  • CP AUTOSAR标准之DefaultErrorTracer(AUTOSAR_SWS_DefaultErrorTracer)(更新中……)
  • [译]如何构建服务器端web组件,为何要构建?
  • 【编码】-360实习笔试编程题(二)-2016.03.29
  • Babel配置的不完全指南
  • css布局,左右固定中间自适应实现
  • java取消线程实例
  • Linux Process Manage
  • Linux学习笔记6-使用fdisk进行磁盘管理
  • nfs客户端进程变D,延伸linux的lock
  • pdf文件如何在线转换为jpg图片
  • PHP的类修饰符与访问修饰符
  • Python学习之路13-记分
  • SSH 免密登录
  • VUE es6技巧写法(持续更新中~~~)
  • 从零开始在ubuntu上搭建node开发环境
  • 缓存与缓冲
  • 判断客户端类型,Android,iOS,PC
  • 译有关态射的一切
  • 译自由幺半群
  • nb
  • 7行Python代码的人脸识别
  • 阿里云ACE认证学习知识点梳理
  • ​Base64转换成图片,android studio build乱码,找不到okio.ByteString接腾讯人脸识别
  • # include “ “ 和 # include < >两者的区别
  • # 服务治理中间件详解:Spring Cloud与Dubbo
  • #php的pecl工具#
  • (02)vite环境变量配置
  • (30)数组元素和与数字和的绝对差
  • (Java数据结构)ArrayList
  • (pojstep1.1.1)poj 1298(直叙式模拟)
  • (Ruby)Ubuntu12.04安装Rails环境
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (离散数学)逻辑连接词
  • (企业 / 公司项目)前端使用pingyin-pro将汉字转成拼音
  • (详细版)Vary: Scaling up the Vision Vocabulary for Large Vision-Language Models
  • (已解决)Bootstrap精美弹出框模态框modal,实现js向modal传递数据
  • (转) Android中ViewStub组件使用
  • (转)用.Net的File控件上传文件的解决方案
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .JPG图片,各种压缩率下的文件尺寸