Python 常用魔法方法(下)
Python 常用魔法方法(下)
回顾
魔法方法是 Python 内置方法, 不需要我们手动调用, 它存在的目的是给 解释器 调用的. 比如我们在写 "1 + 1 " 的时候, 这个 "+ " 就会自动调用内置的魔法方法 "__ add__" . 几乎每个魔法方法, 都有一个对应的内置函数或运算符. 当我们使用这些方法去操作数据时, 解释器会自动调用这些对应的魔法方法. 也可以理解为, 重写内置函数, 如果改变的话.
具体的魔法方法等. 可以去看 内置的 builtins.py 这个接口文档.
内置函数对应魔法方法: 如 next() 对应 __ next __ , 类名() 对应 __ call __ 等这样的映射关系 ....
这一块的上篇呢, 还主要分享 type 类和 object 类来阐明 "万物皆对象". object 类是所有类的 基类. 而 type 类则用来判断某个实例对象所属的 "父类" 是谁, 类似父类,不绝对准确, 用来理解. 比如, 123 是 "int" class; "123" 是 "str" class; "str" 的 type 就是 type; object 的类型也是 type, 但 object 是 type 类的基类.
上篇引出 type 类, 当时用了一些哲学概念上的, "一, 二, 三" 来比喻, 仔细一想, 表述不太对, "元类" 的概念没说
元类 (metaclass): 如果是 type类是用来 静态创建类, 则 metaclass 是用来创建类的行为.
这一块先不谈了, 不太敢妄言, 待之后仔细查完资料在总结吧.
本篇还是继续介绍常用的魔法方法. 上篇主要对 __ new __, __ __ init __, __ __ call __ , __ str __, __ __ del __ 初步认识, 并应用场景简单举了例子. go on...
补: 关于 __ new __:
- 通常与 __ init __, 被称为 "构造函数". _____ del __ 被称为 "析构函数".
- 我目前用的的例子, 就只用 "单例" 用到.
- new 方法还涉及到 metaclass 的知识, 平时也不太用得到, 姑且先不涉及了.
- 用于继承一个不可边类型对象类 (tuple, int, str...) 的构造器, 当一个实例被创建时的初始化方法.
魔法方法总结
常用
__ new__ (cls, ....) 实例化所调用, 返回一个实例对象,(若无, 则不会调 __ init __ 在单例场景中时有用过.
__ init __ (self,...) 类实例化时, 的初始化值设置.
__ del __ (self) 也称为析构器. 当一个实例被 del 的时候会被触发.
__ call __(self, ...) 将类实例对象, "装饰" 为像函数一行可调用, 即 obj(*args.), 在 装饰器 有用到.
__ str __ (self) 描述对象信息, 在 print(obj) 时被触发.
__ len __ (self) 在使用 len() 时被调用.
__ repr __ (self) 在使用 repr() 时被调用.
repr(), 返回一个对象的 string 格式, 就是在外面套一个 "", 跟 eval() 函数像是其逆.
# repr(obj) -> str
# eval(str) -> obj
>>> repr(123)
'123'
>>> repr([1,2,"cj", [1,[2]]])
"[1, 2, 'cj', [1, [2]]]"
t = repr({'a':123, 'b':{"c":4}})
>>> t
"{'a': 123, 'b': {'c': 4}}"
>>> eval(t)
{'a': 123, 'b': {'c': 4}}
__ bytes __ (self) 在使用 bytes() 时被调用.
__ hash __ (self) 在使用 hash() 时被调用. 返回可哈希对象的数值, 传不可哈希(如list) 则报错
__ bool __ (self) 在 bool() 时被调用.
__ format __ (self,...) 在使用 format() 被调用. 不过我更多使用 f"{变量名} hello" 这样的语法多一点.
....
属性的
__ getattr __(self, item) 试图获取一个不存在属性的行为. 曾用来, 用来做异常判断.
__ getattribute __(self, item) 该类属性被访问时的行为. 跟 getattr 其实不太好搭配.
__ setattr __(self, key, value) 当一个属性被设置时的行为, obj.name = "youge"
__ delattr __(self, item) 属性被删除时的行为.
__ dir __(self) 定义当 dir() 被调用时的行为
__ get__ (self, instance, owner) 定义当描述符的值被取得时的行为
__ set__ (self, instance, value) 定义当描述符的值被改变时的行为
__ delete __(self, instance) 定义当描述符的值被删除时的行为
...
比较的
__ lt__ (self, other) 小于号的行为:x < y 调用 x.__ lt __(y)
__ le__ (self, other) 小于等于号的行为:x <= y 调用 x.__ le__(y)
__ eq__ (self, other) 等于号的行为:x == y 调用 x.__ eq__(y)
__ ne__ (self, other) 不等号的行为:x != y 调用 x.__ ne__(y)
__ gt __ (self, other) 大于号的行为:x > y 调用 x.__ gt__(y)
__ ge __ (self, other) 大于等于号的行为:x >= y 调用 x.__ ge__(y)
...
算数的
__ add__(self, other) 定义加法的行为:+
__ sub__(self, other) 定义减法的行为:-
__ mul__(self, other) 定义乘法的行为:*
__ truediv__(self, other) 定义真除法的行为:/
__ floordiv__(self, other) 定义整数除法的行为://
__ mod__(self, other) 定义取模算法的行为:%
__ divmod__(self, other) 定义当被 divmod() 调用时的行为
__ pow__(self, other[, modulo]) 定义当被 power() 调用或 ** 运算时的行为
... 还有什么 位运算, 逆运算, 增量赋值 .. 各种计算符号, 都是一个个的魔法方法, 即都是可以改写的.
这些有啥用呢, 举个算数的, 通过重写, 可以自定义 运算符, 比如 1 +1 = 3 是可以的
# 重写 "+" 这个运算符, 即重写 __add__ 这个方法
class Num:
def __init__(self, value):
self.value = value
def __add__(self, other):
print(self.value + other + 1)
if __name__ == '__main__':
one = Num(1)
one + 1
# output
3
类型转换
__ complex__(self) 定义当被 complex() 调用时的行为(需要返回恰当的值)
__ int__(self) 定义当被 int() 调用时的行为
__ float__(self) 定义当被 float() 调用时的行为
__ round__(self[, n]) 定义当被 round() 调用时的行为
__ index__(self)
这一块了解就行, 建议不要乱改, 是关联的, 比如 index 被重写, 那 int 也有重写, 而且返回值也是要相同的.
上下文管理
__ enter__ (self)
定义当使用 with 语句时的初始化行为
__ enter__ 的返回值被 with 语句的目标或者 as 后的名字绑定
__ exit__ (self, exc_type, exc_value, traceback)
定义当一个代码块被执行或者终止后上下文管理器应该做什么
一般被用来处理异常,清除工作或者做一些代码块执行完毕之后的日常工作
容器类型
__ len__(self) 定义当被 len() 调用时的行为(返回容器中元素的个数)
__ getitem__(self, key) 定义获取容器中指定元素的行为,相当于 self[key]
__ setitem__(self, key, value) 定义设置容器中指定元素的行为,相当于 self[key] = value
__ delitem__(self, key) 定义删除容器中指定元素的行为,相当于 del self[key]
__ iter__(self) 定义当迭代容器中的元素的行为
__ reversed__(self) 定义当被 reversed() 调用时的行为
__ contains__(self, item) 定义当使用成员测试运算符(in 或 not in)时的行为
容器这个概念, 很直观有抽象, 是有点矛盾, 但 非常重要.
这里举个 迭代器 的栗子, 后面会单独来讲, 这里引入一波, 迭代器: 实现了 __ iter __ , __ next __ 的类 (容器)
class Iterator:
"""迭代器, 以list 作为底层结构"""
def __init__(self, lst):
self.lst = lst
self.index = 0
def __iter__(self):
return self
def __next__(self):
if self.index < len(self.lst):
# get current value
value = self.lst[self.index]
self.index += 1
else:
raise StopIteration
return value
# __next__ 为了能与 for 对应上
# __iter__ 迭代后返回自身
小结
- 每一个魔法方法, 几乎都跟咱用的 内置函数是有映射关系的
- 可以通过重写魔法方法来适应业务, 如运算符重载, 类属性判断, 异常检测等.
- 还是在于设计类这方面会很有用的.
本篇的目的是大致了解魔法方法, 留印象为主, 具体用啥, 再进行百度即可.而上篇呢重点是举了几个常用来重写魔法方法的应用场景, 当然也是我自己经验有限, 目前只用到的非常少吧.
Python 常用魔法方法(下)的更多相关文章
- python之魔法方法介绍
1.1. 简介 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加“魔法”的特殊方法. 它们经常是两个下划线包围来命名的(比如 __init__ , __lt__ ) ...
- python常用魔术方法概览
构造和初始化 __init__(self, args) 构造函数 __new__(cls) 传入的是类实例 __del__(self) 析构函数,调用 del cls 时会被调用 属性访问控制 __g ...
- Python魔法方法(magic method)细解几个常用魔法方法(下)
接上文,再介绍最后几个常用的魔法方法. 关于__dict__: 先上个例子: class Test(object): fly = True def __init__(self, age): self. ...
- Python魔法方法(magic method)细解几个常用魔法方法(上)
这里只分析几个可能会常用到的魔法方法,像__new__这种不常用的,用来做元类初始化的或者是__init__这种初始化使用的 每个人都会用的就不介绍了. 其实每个魔法方法都是在对内建方法的重写,和做像 ...
- python进阶之类常用魔法方法和魔法属性
前言 前面我们总结过了python的关键字.运算符.内置函数.语法糖等与python魔法方法之间的关系,现在我们更细一点,看看python的面向对象编程有哪些常用的魔法属性和魔法方法. 魔法属性 对于 ...
- 【Python】 魔法方法
魔法方法 这个名字真的很中二有没有 = =(或者说翻译气息太浓了,作为一个学外语的看到这种真是想吐槽的不行..) 从形式上来说,在方法的名字前后个加上两条下划线的就是魔法方法了 .从功能上说,所有魔法 ...
- python,魔法方法指南
1.简介 本指南归纳于我的几个月的博客,主题是 魔法方法 . 什么是魔法方法呢?它们在面向对象的Python的处处皆是.它们是一些可以让你对类添加“魔法”的特殊方法. 它们经常是两个下划线包围来命名的 ...
- Python的魔法方法 .
基本行为和属性 __init__(self[,....])构造函数 . 在实例化对象的时候会自动运行 __del__(self)析构函数 . 在对象被回收机制回收的时候会被调用 __str__(sel ...
- python中魔法方法__init__,__str__,__del__的详细使用方法
1. python中的魔法方法, 类似__init__, __str__等等,这些内置好的特定的方法进行特定的操作时会自动被调用 2. __init__的使用方法 class 类名(object): ...
- 21 python的魔法方法(转)
魔法方法 含义 基本的魔法方法 __new__(cls[, ...]) 1. __new__ 是在一个对象实例化的时候所调用的第一个方法2. 它的第一个参数是这个类,其他的参数是用来直接传递给 _ ...
随机推荐
- [国家集训队] happiness 题解
发现可以做如下建图: 对于前两组输入,从 \(s\) 向所有代表学生的点连一条边,容量为其学习文科的喜悦值:从所有代表学生的点向 \(t\) 连一条边,容量为其学习理科的最大值. 对于后四组输入,建两 ...
- 解决2023新版Edge浏览器页面加载不出来问题
如果你遇到2023新版Edge浏览器页面无法加载的问题,可以尝试以下几种解决方法: 检查网络连接:确保你的网络连接正常,可以尝试打开其他网页或使用其他应用程序进行网络测试. 清除浏览器缓存:打开Edg ...
- 【忍者算法】从快慢指针到倒数查找:优雅解决链表倒数问题|LeetCode第19题"删除链表的倒数第N个结点"
从快慢指针到倒数查找:优雅解决链表倒数问题 从生活场景说起 想象你在一个漫长的队伍中,想知道自己距离队尾还有多少人.一个巧妙的方法是:让你的朋友从你所在位置往后数N步,然后你和朋友一起向后走.当朋友走 ...
- [解决方案][docker] Http: server gave HTTP response to HTTPS client
前言 用centos运行docker不支持http,需要在daemon.json 里面配置一下 目录 没有daemon.json 需要添加这个文件 在daemon.json 增添配置 重启即可 一.l ...
- MySQL索引最左原则:从原理到实战的深度解析
MySQL索引最左原则:从原理到实战的深度解析 一.什么是索引最左原则? 索引最左原则是MySQL复合索引使用的核心规则,简单来说: "当使用复合索引(多列索引)时,查询条件必须从索引的最左 ...
- 在OCI上快速静默安装23ai数据库
拿到同事帮忙申请好的OCI环境[OEL 8.10]后,开始安装23ai数据库用于后续测试,本文选择快速静默安装模式. OCI环境都是opc用户登录的,执行高权限的操作均需要用到sudo命令. 首先创建 ...
- 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
在 AI 编程领域国内外有一堆能叫的上号的应用: Cursor Windsurf Trae 阿里的「通义灵码」 百度的「文心快码」 字节跳动的「MarsCode」 科大讯飞的「iFlyCode」 Gi ...
- 2个月搞定计算机二级C语言——真题(8)解析
1. 前言 本篇我们讲解2个月搞定计算机二级C语言--真题8 2. 程序填空题 2.1 题目要求 2.2 提供的代码 #include <stdio.h> #define N 3 #def ...
- 在 Go 中恰到好处的内存对齐
问题 type Part1 struct { a bool b int32 c int8 d int64 e byte } 在开始之前,希望你计算一下 Part1 共占用的大小是多少呢? func m ...
- docker学习 容器的启动过程
这一节我们来稍微了解下docker原理性的东西1 docker run -i -t ubuntu /bin/bash输入上面这行命令,启动一个ubuntu容器时,到底发生了什么?大致过程可以用下 ...