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函数调用时使用。
示例
py 复制代码
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 NotImplemented
        return (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中的参数一个一个的传递,而不是传递一个list
        return NotImplemented

    def __sub__(self, other):
        if isinstance(other, Container):
            return Container(*(self.container[:-1] if len(self.container) >= len(other.container) else self.container))
        return NotImplemented

    def __mul__(self, other):
        if isinstance(other, int):
            return Container(*(self.container * other))
        return NotImplemented

    def __truediv__(self, other):
        if isinstance(other, int) and other != 0:
            return Container(*(x / other for x in self.container))
        return NotImplemented

    def __mod__(self, other):
        if isinstance(other, int):
            return Container(*(x % other for x in self.container))
        return NotImplemented

    def __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__
python 复制代码
class Person:
    __init(self,*args)__:
      pass


# 创建 Student 类的实例
p = Person()
p.name = '子羽'  
print(p.name)
使用__slots__

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

python 复制代码
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 函数装饰器

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

示例
python 复制代码
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 装饰器,然后在该方法内部定义获取属性值的逻辑。下面是一个简单的例子:

python 复制代码
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

# 创建 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 模块定义枚举类。

示例
python 复制代码
from enum import Enum, auto

class Color(Enum):
    RED = auto() # 默认从 1 开始
    GREEN = auto()
    BLUE = auto()
    YELLOW = 5
    purple = 6

print(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__

示例
python 复制代码
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面向对象编程中的一些高级特性,包括类的内部变量、特殊方法、装饰器、枚举类和元类。这些高级特性能够帮助你编写更加灵活和强大的代码。如果你有任何疑问或想法,欢迎在评论区留言讨论。

相关推荐
bluebonnet272 分钟前
【Rust练习】22.HashMap
开发语言·后端·rust
糖豆豆今天也要努力鸭3 分钟前
torch.__version__的torch版本和conda list的torch版本不一致
linux·pytorch·python·深度学习·conda·torch
何大春19 分钟前
【弱监督语义分割】Self-supervised Image-specific Prototype Exploration for WSSS 论文阅读
论文阅读·人工智能·python·深度学习·论文笔记·原型模式
在下不上天28 分钟前
Flume日志采集系统的部署,实现flume负载均衡,flume故障恢复
大数据·开发语言·python
SEVEN-YEARS31 分钟前
深入理解TensorFlow中的形状处理函数
人工智能·python·tensorflow
EterNity_TiMe_36 分钟前
【论文复现】(CLIP)文本也能和图像配对
python·学习·算法·性能优化·数据分析·clip
Suyuoa1 小时前
附录2-pytorch yolov5目标检测
python·深度学习·yolo
Iced_Sheep1 小时前
干掉 if else 之策略模式
后端·设计模式
XINGTECODE1 小时前
海盗王集成网关和商城服务端功能golang版
开发语言·后端·golang
程序猿进阶1 小时前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露