小记Python中一些常用的魔术方法

简介: 小记Python中一些常用的魔术方法

init()

结构和作用与PHP中的__construct大同小异

函数结构

def init(self, [*args]):# code is there

self.args = args

......

函数作用

对类中的属性进行一个初始化

说明

在内存空间开辟完成后, 会对类中的属性进行一个初始化。在面对继承了超类的子类时可以不用重写__init__方法, 在实例化子类的同时会自动调用超类中的__init__方法。

new()

在接触到__new__之前先接触了__init__魔术方法, 以为__init__就是在魔术方法中最先会被执行的那个(初始化类属性)。

后面了解到了__new__这个魔术方法,以为它就是PHP中__wakeup + __construct的一个集合体, 但是在仔细了解过后才发现它的功能不仅限于此。

函数结构:

def new(cls, [*args]):# code is there

instance = super().new(cls)

return instance

至少要有一个cls属性来接收实例化后的类

函数作用:

对类进行一个实例化, 开辟内存空间, 主要用来控制对实例的创建

说明

实例化对象, 并在内存中开辟空间, 实例化的对象可以是其他的类。相对于__init__的对象初始化, __new__则是对对象的一个创建。

如果类中同时存在__new__魔术方法和__init__魔术方法, __new__方法将先于__init__执行(第一顺位执行); 如果要得到当前类的实例, 应当在当前类的__new__方法中调用当前类的父类的__new__方法, 对其中的__new___进行重写。如果当前类直接继承自object的话则应当 return object.new(cls);

在创建一个对象时, 首先执行类中的__new__方法, 通常执行的结构是

super(ClassName, Type).__new__(Type, [*args...])

而后再通过类中的__init__去初始化类中的属性

repr()

作用同__str__, 区别在于使用场景, __str__在终端输出, __repr__在交互式终端输出

函数结构

def repr(self):# code is there

return something

函数作用

按照需求在打印对象时返回指定的字符串。

说明

在没有定义此函数时, 直接打印对象会返回一个<__main__.ClassName object at 0xaddress>格式的字符串, 此处调用的就是在Object类中写好的__repr__方法, 在类中定义的__repr__实际上就是对object中__repr__方法的一种重写。

如果同时存在__str__和__repr__函数, 则在交互式终端时优先执行__repr__函数, __str__函数不执行。

str()

同__repr__

函数结构

def str(self):# code is there

return something

函数作用

按照需求在终端打印对象时返回指定的字符串

说明

如果同时存在__str__和__repr__函数, 则在终端时优先执行__str__函数, __repr__函数不执行。

image.png

del()

作用同php中的__destruct函数

函数结构

def del(self):# code is there

......

函数作用

当对象被手动或者自动销毁时触发

说明

Python中的GC机制与PHP中的相似, 都是引用计数为0自动回收内存, 只不过Python在回收资源时是按照字典顺序进行内存回收, 而不是创建顺序。所以当系统回收资源是会按照类名A-Za-z的顺序依次进行,且此流程无法掌控。

在循环引用__del__魔术方法的时候, 容易造成垃圾内存导致不可回收。消耗系统资源, 但Python中的GC机制可以通过设置gc.set_debug(gc.DEBUG_LEAK)来对循环引用的内存泄露进行检查,确保不会出现内存泄露的情况。

call()

作用同php中的__invoke()

函数结构

def call(self, [*args]):# code is there

return something

函数作用

当对象被当作函数被调用的时候触发

说明

当类中实现了__call__方法时, ObjectName() 等价于 ObjectName.call()

getattr()

同php中的__get()

函数结构

def getattr(self, [*args]):# code is there

......

函数作用

当获取不存在的对象属性时触发

说明

当属性在__dict__中不被定义导致查找失败的话, 那么在最后就会尝试去调用__getattr__方法作为一个最后被调用的方法。如果类中并没有实现此魔术方法则会抛出AttributeError的异常。

在某些时候或许需要实现一个外部传参的动态定义,此时使用__getattr__来对属性进行定义可以极大的简化此实现过程。

示例


def load(name):
    # 动态实现的code
    return 'Content of ' + name
class Lazy2(object):
    def __init__(self):
        self.__data = {}
    def __getattr__(self, name):
        if name not in self.__data:
            self.__data[name] = load(name)
        return self.__data[name]
    def __setattr__(self, name, value):
        if not name.startswith('_'):
            raise AttributeError("can't set attribute")
        object.__setattr__(self, name, value)
lazy2 = Lazy2()
print(lazy2.first)  # 定义了一个first的属性, 属性值和属性名以字典的格式存放在__data中
print(lazy2.__dict__)

setattr()

区别于php中的__set(), python中的__setattr__只要是对类中的属性进行赋值就会被触发,包括__init__中对属性进行初始化时也一样。

函数结构

def setattr(self, key, value): # 除去self以外 至少需要两个参数# code is there

......

函数作用

在对类中的属性进行赋值时触发

说明

如果在类中实现了此方法,则一定要在方法中实现对属性的注册功能, 因为在重写了此方法后对属性进行赋值时, 值并不会自动写入到__dict__中。

且在实现__setattr__方法时要注意不要造成死循环

示例

class test:
    def __init__(self, name):
        self.name = name
    def __setattr__(self, key, value):
        self.value = value  # 此处如果在__setattr__方法中又对属性进行了赋值操作则又会触发一遍__setattr__方法,导致死循环
        # 正确操作应该将变量注册到__dict__中
        self.__dict__[key] = value

delattr()

函数结构

def delattr(self, [*args]):# code is there

......

函数作用

在属性被删除的时候调用

说明

在__delattr__方法中也需要避免死循环的问题

示例


class test:
    def __init__(self, name):
        self.name = name
  def __delattr__(self, item):
        # 正确写法
        object.__delattr__(self, item)
        # or
      self.__dict__.pop(item)
        # 死循环, 
        # 当递归次数达到最大次数后会抛出RecursionError: maximum recursion depth exceeded while calling a Python object的异常
        # 默认递归最大次数 -> 1000
      del self.item
目录
相关文章
|
6月前
|
Python
你真的会面向对象吗!解密Python“魔术方法”
你真的会面向对象吗!解密Python“魔术方法”
65 0
|
8月前
|
开发者 Python
Python教程:你一定要知道的26个Python魔术方法(快记下来)
Python中的魔术方法是指以双下划线 __ 开头和结尾的特殊方法,也被称为特殊方法或魔术方法。这些方法在类中具有特殊的用途,它们可以让你自定义类的行为,使得你的对象可以像内置类型一样工作。
80 3
|
9月前
|
数据库 Python
Python常见的魔术方法和魔术属性(一)
Python常见的魔术方法和魔术属性(一)
|
9月前
|
Python
Python常见的魔术方法和魔术属性(二)
Python常见的魔术方法和魔术属性(二)
|
9月前
|
Python
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
python基础篇:python面向对象有哪些魔术方法?具体有什么用?
46 1
|
9月前
|
Java 程序员 索引
Python中魔术方法汇总
Python中魔术方法汇总
99 0
|
9月前
|
Python
Python高级专题 - 类型转换的魔术方法
Python高级专题 - 类型转换的魔术方法
57 1
|
9月前
|
存储 程序员 索引
python面向对象编程,什么是魔术方法(magic method),它们有什么作用?
python面向对象编程,什么是魔术方法(magic method),它们有什么作用?
154 0
|
9月前
|
Java Shell 程序员
Python 进阶指南(编程轻松进阶):十七、Python 风格 OOP:属性和魔术方法
Python 进阶指南(编程轻松进阶):十七、Python 风格 OOP:属性和魔术方法
49 0
|
存储 C语言 Python
Python魔术方法大全3
在Python中,所有以“__”双下划线包起来的方法,都统称为“Magic Method”(魔术方法),例如类的初始化方法 init ,Python中所有的魔术方法均在官方文档中有相应描述,这边给大家把所有的魔术方法汇总了一下,希望对大家的学习有所帮助。
109 0

热门文章

最新文章