『Python底层原理』--Python属性的工作原理

Python中的属性操作(如获取、设置和删除属性)是我们日常编程中非常常见的操作。

但你有没有想过,当我们写下obj.attrobj.attr = value时,Python 内部究竟发生了什么?

本文将探讨Python属性的工作原理,并通过简单的代码示例来更好地理解这些概念。

1. 属性的基本操作

Python中,属性基本操作主要有三种:

  1. 获取属性值:value = obj.attr
  2. 设置属性值:obj.attr = value
  3. 删除属性: del obj.attr

这些操作看似简单,但它们的实现却依赖于Python的底层机制。

为了更好地理解这些机制,我们需要先了解描述符的概念。

2. 描述符:属性的核心机制

描述符Python中一个非常重要的概念,它是实现属性功能的核心机制。

描述符 是一个对象,它通过实现特定的方法(如__get____set____delete__)来控制属性的访问、设置和删除。

例如,如下实现一个简单的描述符类:

python 复制代码
class Descriptor:
    def __get__(self, instance, owner):
        return f"从 {instance} 获取属性值"

    def __set__(self, instance, value):
        print(f"设置 {instance} 的属性值: {value}")

    def __delete__(self, instance):
        print(f"从 {instance} 中删除属性值")

我们可以将这个描述符 作为类属性使用:

python 复制代码
obj = MyClass()
print(obj.attr)  # 调用 __get__
obj.attr = "Hello"  # 调用 __set__
del obj.attr  # 调用 __delete__

CPython中,描述符通过tp_descr_gettp_descr_set两个函数指针实现。

3. 属性的存储与查找

Python中的属性存储在对象的字典(__dict__)中,或者在类的字典中。

当我们访问属性时,Python会按照以下顺序查找:

  1. 在实例的__dict__中查找
  2. 如果未找到,按照方法解析顺序在类及其父类的__dict__中查找
  3. 如果仍未找到,抛出AttributeError

比如:

python 复制代码
class Parent:
    x = "Parent"


class Child(Parent):
    y = "Child"


obj = Child()
print(obj.x)  # 输出 "Parent",从父类中找到
print(obj.y)  # 输出 "Child",从子类中找到

4. 类型的属性管理

类型(如intlist)本身也有属性,这些属性的管理方式与普通对象类似,但有一些特殊之处。

因为类型本身是一个对象,它的类型是type,它是一个元类型

当我们访问类型属性时,Python会按照以下顺序查找:

  1. 在类型的字典中查找
  2. 如果未找到,按照 方法解析顺序 在元类型的字典中查找

这里有一个元类型 的概念,所谓元类型 ,是指它的实例 是一个类型

也就是说,正如 用于创建对象 一样,元类型 是用于创建的。

Python有一个内置的元类型,称为type,它是所有内置类型中的元类型

比如我们在Python中创建一个类一般使用下面的方式:

python 复制代码
class MyClass:
    pass

也可以改成下面这样,和上面是等价的。

python 复制代码
MyClass = type('MyClass', (), {})

5. 自定义属性管理

Python允许我们通过定义特殊方法来自定义属性的行为,这些方法包括:

  • __getattribute__:拦截所有属性访问
  • __getattr__:仅在属性未找到时被调用
  • __setattr__:拦截所有属性设置
  • __delattr__:拦截所有属性删除

下面示例中,自定义了属性的访问和设置。

python 复制代码
class MyClass:
    def __getattribute__(self, name):
        print(f"拦截所有属性的访问: {name}")
        return super().__getattribute__(name)

    def __getattr__(self, name):
        print(f"拦截不存在属性的访问: {name}")
        return f"属性 {name} 不存在"

    def __setattr__(self, name, value):
        print(f"设置属性值: {name} = {value}")
        super().__setattr__(name, value)


obj = MyClass()
obj.x = "Hello"
print(obj.x)  # 访问存在的属性
print(obj.y)  # 访问不存在的属性

设置属性obj.x = "Hello")时,调用了 __setattr__

访问存在的属性print(obj.x))时,调用了__getattribute__

访问不存在的属性print(obj.y))时,调用了__getattribute____getattr__

且是先调用__getattribute__

6. 总结

Python的属性机制非常强大,它通过描述符、特殊方法和底层的字节码操作实现了灵活的属性管理。

通过理解这些机制,我们可以更好地设计类和对象,优化代码性能,并避免常见的陷阱。

相关推荐
维度攻城狮2 分钟前
实现在Unity3D中仿真汽车,而且还能使用ros2控制
python·unity·docker·汽车·ros2·rviz2
简简单单做算法6 分钟前
基于mediapipe深度学习和限定半径最近邻分类树算法的人体摔倒检测系统python源码
人工智能·python·深度学习·算法·分类·mediapipe·限定半径最近邻分类树
hvinsion1 小时前
基于PyQt5的自动化任务管理软件:高效、智能的任务调度与执行管理
开发语言·python·自动化·自动化任务管理
飞飞翼3 小时前
python-flask
后端·python·flask
林九生4 小时前
【Python】Browser-Use:让 AI 替你掌控浏览器,开启智能自动化新时代!
人工智能·python·自动化
猿界零零七4 小时前
执行paddle.to_tensor得到全为0
python·paddle
青花瓷5 小时前
智谱大模型(ChatGLM3)PyCharm的调试指南
人工智能·python·大模型·智谱大模型
独好紫罗兰5 小时前
洛谷题单2-P5715 【深基3.例8】三位数排序-python-流程图重构
开发语言·python·算法
mqiqe6 小时前
Spring MVC 页面跳转方案与区别
python·spring·mvc
小白的高手之路6 小时前
torch.nn.Conv2d介绍——Pytorch中的二维卷积层
人工智能·pytorch·python·深度学习·神经网络·机器学习·cnn