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

打印 上一主题 下一主题

主题 901|帖子 901|积分 2703

Python中的属性操作(如获取、设置和删除属性)是我们一样平常编程中非常常见的操作。
但你有没有想过,当我们写下obj.attr或obj.attr = value时,Python 内部究竟发生了什么?
本文将探究Python属性的工作原理,并通过简单的代码示例来更好地理解这些概念。
1. 属性的基本操作

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

  • 获取属性值:value = obj.attr
  • 设置属性值:obj.attr = value
  • 删除属性:  del obj.attr
这些操作看似简单,但它们的实现却依赖于Python的底层机制。
为了更好地理解这些机制,我们需要先相识形貌符的概念。
2. 形貌符:属性的核心机制

形貌符是Python中一个非常紧张的概念,它是实现属性功能的核心机制。
形貌符是一个对象,它通过实现特定的方法(如__get__、__set__和__delete__)来控制属性的访问、设置和删除。
比方,如下实现一个简单的形貌符类:
  1. class Descriptor:
  2.     def __get__(self, instance, owner):
  3.         return f"从 {instance} 获取属性值"
  4.     def __set__(self, instance, value):
  5.         print(f"设置 {instance} 的属性值: {value}")
  6.     def __delete__(self, instance):
  7.         print(f"从 {instance} 中删除属性值")
复制代码
我们可以将这个形貌符作为类属性使用:
  1. obj = MyClass()
  2. print(obj.attr)  # 调用 __get__
  3. obj.attr = "Hello"  # 调用 __set__
  4. del obj.attr  # 调用 __delete__
复制代码

在CPython中,形貌符通过tp_descr_get和tp_descr_set两个函数指针实现。
3. 属性的存储与查找

Python中的属性存储在对象的字典(__dict__)中,大概在类的字典中。
当我们访问属性时,Python会按照以下顺序查找:

  • 在实例的__dict__中查找
  • 如果未找到,按照方法分析顺序在类及其父类的__dict__中查找
  • 如果仍未找到,抛出AttributeError
好比:
  1. class Parent:
  2.     x = "Parent"
  3. class Child(Parent):
  4.     y = "Child"
  5. obj = Child()
  6. print(obj.x)  # 输出 "Parent",从父类中找到
  7. print(obj.y)  # 输出 "Child",从子类中找到
复制代码
4. 范例的属性管理

范例(如int、list)自己也有属性,这些属性的管理方式与普通对象类似,但有一些特殊之处。
由于范例自己是一个对象,它的范例是type,它是一个元范例
当我们访问范例属性时,Python会按照以下顺序查找:

  • 在范例的字典中查找
  • 如果未找到,按照 方法分析顺序 在元范例的字典中查找
这里有一个元范例的概念,所谓元范例,是指它的实例是一个范例
也就是说,正如用于创建对象一样,元范例是用于创建的。
Python有一个内置的元范例,称为type,它是全部内置范例中的元范例
好比我们在Python中创建一个类一样寻常使用下面的方式:
  1. class MyClass:
  2.     pass
复制代码
也可以改成下面这样,和上面是等价的。
  1. MyClass = type('MyClass', (), {})
复制代码
5. 自定义属性管理

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

  • __getattribute__:拦截全部属性访问
  • __getattr__:仅在属性未找到时被调用
  • __setattr__:拦截全部属性设置
  • __delattr__:拦截全部属性删除
下面示例中,自定义了属性的访问和设置。
  1. class MyClass:
  2.     def __getattribute__(self, name):
  3.         print(f"拦截所有属性的访问: {name}")
  4.         return super().__getattribute__(name)
  5.     def __getattr__(self, name):
  6.         print(f"拦截不存在属性的访问: {name}")
  7.         return f"属性 {name} 不存在"
  8.     def __setattr__(self, name, value):
  9.         print(f"设置属性值: {name} = {value}")
  10.         super().__setattr__(name, value)
  11. obj = MyClass()
  12. obj.x = "Hello"
  13. print(obj.x)  # 访问存在的属性
  14. print(obj.y)  # 访问不存在的属性
复制代码

设置属性(obj.x = "Hello")时,调用了 __setattr__;
访问存在的属性(print(obj.x))时,调用了__getattribute__;
访问不存在的属性(print(obj.y))时,调用了__getattribute__和__getattr__,
且是先调用__getattribute__。
6. 总结

Python的属性机制非常强大,它通过形貌符、特殊方法和底层的字节码操作实现了机动的属性管理。
通过理解这些机制,我们可以更好地设计类和对象,优化代码性能,并制止常见的陷阱。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

傲渊山岳

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表