聊聊Python中的魔术方法(一)

简介: 聊聊Python中的魔术方法(一)

Python中的魔术方法是非常有意思的一部分,通过魔术方法可以做到去自定义化一个类的默认行为,比如相加或者相减,可以把一个对象变为可以迭代的对象,可以控制属性的设置和获取,可以使用with来进行上下文控制。

在Python中的魔术方法是类中的以双下划线开头和结尾的方法,通过较少的代码量,就可以实现非常强大的功能。这里根据Python的中魔术方法被调用的时机,将魔术方法简单分为三种,在类的实例化和销毁的过程中的魔术方法、对象之间使用运算符运算时参与的魔术方法和获取对象属性和数据时调用的魔术方法。

实例化过程中和对象销毁时

在一类魔术方法主要有以下几个

class A:
    @classmethod
    def __new__(cls, *args, **kwargs):
        ...
    def __init__(self):
        ...
    def __enter__(self):
        ...
    def __exit__(self, exc_type, exc_val, exc_tb):
        ...
    def __del__(self):
        ...
    def __call__(self):
        ...

在上面的几个魔术方法中,除了__new__方法是一个类方法,其余的都为实例方法。既然将他们归为生命周期中,是因为这些方法会在类(对象实例)执行过程中的不同时机进行运行。对于一个常规的类,在他从被实例化到被销毁的全过程中,他们的调用顺序是这样的__new__ > __init__ > __del__。而对于其余的两个魔术方法只有在进入上下文管理(使用with语句)时才会被调用,具体的调用时机如下所示。

with A() as a:
    print('在调用A()时回调用__enter__方法')
    pass
print('在这里运行__exit__方法')

__enter____exit__方法常用作一些文件管理中,比如__enter__中将文件打开,__exit__中将文件关闭,这样在使用的时候,就可以使用with来实现自动打开文件和关闭文件了。

class File:
    def __init__(self,path):
        self.path = path
    def __enter__(self):
        self.fp = open(self.path)
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.fp.close()
with File('1.txt') as fp:
    # do something

除了实现自动打开和自动关闭文件之外,这种方式还可以用来自动管理各种连接,比如数据连接,在__enter__中打开数据库连接__exit__中关闭数据库连接。

  • __del__方法不止在程序退出对象销毁时被调用,当主动通过del去删除一个对象的时候,也会被调用。这个函数通常是做一些收尾工作,比如将用不到变量del掉,等等。
  • __init__方法又叫实例化方法,是因为在类实例化的时候这个方法会被调用。通过self.的方式可以将一些变量绑定到对象上,这些绑定的对象将存储在对象的__dict__字典中。
  • __new__方法一般情况下不会用到,只有当你需要控制类的实例化过程的时候才会用得到,比如一些特殊用途的类,比如用来做ORM(数据库连接映射)的时候才会需要自定义类的实例化过程,再比如实现一些单例模式的时候也会用得到这个方法。
  • __call__方法严格意义上可能不算生命周期类的魔术函数,他的作用是可以将一个实例化的对象直接当成一个函数来进行调用。
a = A()
a()  # 这里就是因为__call__的存在,所以可以直接调用

运算时

在Python中一切皆为对象,在Python中常见的数字比如12,他们是属于int类型的对象,当他们之间进行运算时,比如加法运算。其实这背后是调用了int这个对象的__add__魔术方法。通过改变__add__方法就可以控制加法运算,除了加法运算,Python中的其他「所有」运算都是可以通改变运算符对应的魔术方法来改变其默认行为的。换句话说,Python的所有运算符都是可以自定义的,这也被称为运算符重载。由于和运算符相关的魔术方法太多,这里只讲两个的使用这类魔术方法实现的方法。

  • __truesection__对应的运算符是/符号。这本身是一个除法符号,但这个符号和路径里面的分隔符是一样的/test/a,通过对其对应的魔术方法重载,就可以做到使用/符号来直接进行路径的拼接。作为演示,这里实现了一个极其简单的版本,更加完整的实现方式可以参考Python标准库里面的pathlib的实现。
import os
class Path:
    def __init__(self,path):
        self.path = path
    def __truesection__(self,other):
        return Path(os.path.join(str(self.path),str(other)))
    def __str__(self):
        return self.path
p = Path('test')
print(p / 'a')  # /test/a
  • __contains__对应的运算符是in成员运算符,在判断一个元素是否在一个对象中时,就可以重载该运算符的魔术方法。
class Numbers:
    numbers = []
    def add(self, x):
        self.numbers.append(x)
    def pop(self):
        self.numbers.pop()
    def __contains__(self,x):
        return x in self.numbers
box = Numbers()
box.add(1)
box.add(2)
box.add(3)
print(1 in box)  # True

数据获取时

未完待续...

相关文章
|
3月前
|
Python
你真的会面向对象吗!解密Python“魔术方法”
你真的会面向对象吗!解密Python“魔术方法”
40 0
|
5月前
|
开发者 Python
Python教程:你一定要知道的26个Python魔术方法(快记下来)
Python中的魔术方法是指以双下划线 __ 开头和结尾的特殊方法,也被称为特殊方法或魔术方法。这些方法在类中具有特殊的用途,它们可以让你自定义类的行为,使得你的对象可以像内置类型一样工作。
59 3
|
6月前
|
数据库 Python
Python常见的魔术方法和魔术属性(一)
Python常见的魔术方法和魔术属性(一)
|
6月前
|
Python
Python常见的魔术方法和魔术属性(二)
Python常见的魔术方法和魔术属性(二)
|
6月前
|
Python
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
35 1
|
6月前
|
Java 程序员 索引
Python中魔术方法汇总
Python中魔术方法汇总
71 0
|
6月前
|
Python
Python高级专题 - 类型转换的魔术方法
Python高级专题 - 类型转换的魔术方法
45 1
|
6月前
|
Java Shell 程序员
Python 进阶指南(编程轻松进阶):十七、Python 风格 OOP:属性和魔术方法
Python 进阶指南(编程轻松进阶):十七、Python 风格 OOP:属性和魔术方法
45 0
|
6月前
|
存储 程序员 索引
python面向对象编程,什么是魔术方法(magic method),它们有什么作用?
python面向对象编程,什么是魔术方法(magic method),它们有什么作用?
133 0
|
Java PHP Python
小记Python中一些常用的魔术方法
小记Python中一些常用的魔术方法
46 0
下一篇
无影云桌面