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__)来控制属性的访问、设置和删除。

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

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} 中删除属性值")

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

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

比如:

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中创建一个类一般使用下面的方式:

class MyClass:
pass

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

MyClass = type('MyClass', (), {})

5. 自定义属性管理

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

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

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

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

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

『Python底层原理』--Python属性的工作原理的更多相关文章

  1. 『无为则无心』Python面向对象 — 51、私有成员变量(类中数据的封装)

    目录 1.私有成员变量介绍 (1)私有成员变量概念 (2)私有成员变量特点 (3)私有成员变量体验 2.属性私有化工作原理 3.定义成员变量的标识符规范 4.私有成员变量的获取和设置方式 1.私有成员 ...

  2. 2018-2019-2 20165316 『网络对抗技术』Exp3:免杀原理与实践

    2018-2019-2 20165316 『网络对抗技术』Exp3:免杀原理与实践 一 免杀原理与实践说明 (一).实验说明 任务一:正确使用msf编码器,msfvenom生成如jar之类的其他文件, ...

  3. 2017-2018-2 20155303 『网络对抗技术』Exp3:免杀原理与实践

    2017-2018-2 20155303 『网络对抗技术』Exp3:免杀原理与实践 --------CONTENTS-------- 1. 免杀原理与实践说明 实验说明 基础问题回答 2. 使用msf ...

  4. 『无为则无心』Python面向对象 — 60、魔法属性

    目录 1.魔法属性__name__ 2.魔法属性__bases__ 3.魔法属性__mro__ 4.魔法属性__doc__ 5.魔法属性__module__ 和__class__ 6.魔法属性__di ...

  5. 『无为则无心』Python面向对象 — 46、类和对象

    目录 1.理解类和对象 2.类 3.对象 4.Python中的对象 5.类和对象的定义 (1)定义类 (2)创建对象 (3)练习 6.拓展:isinstance() 函数 1.理解类和对象 (1)类和 ...

  6. 『无为则无心』Python基础 — 3、搭建Python开发环境

    目录 1.Python开发环境介绍 2.Python解释器的分类 3.下载Python解释器 4.安装Python解释器 5.Python解释器验证 1.Python开发环境介绍 所谓"工欲 ...

  7. 『无为则无心』Python基础 — 4、Python代码常用调试工具

    目录 1.Python的交互模式 2.IDLE工具使用说明 3.Sublime3工具的安装与配置 (1)Sublime3的安装 (2)Sublime3的配置 4.使用Sublime编写并调试Pytho ...

  8. 『无为则无心』Python函数 — 34、lambda表达式

    目录 1.lambda的应用场景 2.lambda语法 3.快速入门 4.示例:计算a + b 5.lambda的参数形式 6.lambda的应用 lambda表达式的主要作用就是化简代码. 匿名函数 ...

  9. python中的函数、生成器的工作原理

    1.python中函数的工作原理 def foo(): bar() def bar(): pass python的解释器,也就是python.exe(c编写)会用PyEval_EvalFramEx(c ...

  10. JVM 的 工作原理,层次结构 以及 GC工作原理

    JVM Java 虚拟机 Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.JVM实现了Java语言最重要的特征:即平台无关性.原理:编译后的 ...

随机推荐

  1. Linx操作Nginx命令

    在 CentOS 上操作 Nginx 包括安装.启动.停止.重新加载配置等.以下是在 CentOS 上操作 Nginx 的常用命令: 安装 Nginx: sudo yum install nginx ...

  2. CentOS 更换国内源

    前言 centos默认为官方yum源,国内使用的下载速度完全随缘,且不稳定,一般都需要更换国内源 过程 了解版本 通过cat /etc/redhat-release 可以获取当前centos的版本 知 ...

  3. SpringBoot 整合Swagger2 踩坑记录

    SpringBoot 整合Swagger2 踩坑记录 Failed to start bean 'documentationPluginsBootstrapper'; nested exception ...

  4. Windows的树形目录结构

    一.文件.文件夹(目录).逻辑盘.路径的概念 · 文件:是操作系统用来存储和管理信息的基本单位.每个文件都有一个名称,叫文件名.文件名通常由‌基本文件名和‌扩展名两部分组成,其中基本文件名用于说明文件 ...

  5. 云数据备份 | CDN 日志备份最佳实践

    前言 ​ 内容分发网络(Content Delivery Network,CDN),是在现有 Internet 中增加的一层新的网络架构,可以有效降低用户访问延迟,提升可用性. CDN 按照小时粒度对 ...

  6. 在 VS Code 中可以免费使用 GitHub Copilot了!

    今天,有一个重大的好消息要分享给大家: 从现在开始,我们可以在 Visual Studio Code 中,免费使用强大的 GitHub Copilot 进行开发啦! 每个人都可以享受到 AI 加持下的 ...

  7. 中电金信召开“源启 AI+”人工智能应用场景与发展培训暨业务研讨会

    近年来,国务院国资委把加快发展人工智能放在国资央企全局工作中统筹谋划,作为产业焕新行动和启航行动部署的主要方向,制定印发行动计划,组织召开中央企业人工智能专题推进会,开展"AI+" ...

  8. PySAGES结合CUDA SPONGE增强采样

    技术背景 在前面的一篇博客中,我们介绍过PySAGES这个增强采样软件的基本安装和使用方法.该软件类似于Plumed是一个外挂增强采样软件,但是PySAGES是基于Python语言和Jax框架来实现的 ...

  9. maven maven-surefire-plugin的乱码问题

    今天项目中出现奇怪问题,在eclipse中直接运行TestNG时,全部都OK,但是执行mvn test时却失败.观察其输出日志,发现有乱码,怀疑是乱码导致. 最终在官网发现蛛丝马迹. maven-su ...

  10. MySql 建表出现的问题 : [ERR] 1064 - You have an error in your SQL syntax; check the manual.......

    使用 MySql 建表出现的问题 在使用 Navicat Premium 运行 sql 语句进行建表时,MySQL 报错如下: 1064 - You have an error in your SQL ...