Python基础进阶4:常见魔法方法

你好,我是kelly。

在Python中,以"__"双下划线开头和结尾的方法,称为Magic Method(魔术方法)。

根据用途,将魔法方法划分为不同种类:

一、运算符重载

Python对象之间运算,比如四则运算,实际是使用了魔法方法,如下图所示,在ipython的命令行窗口下,按Tab强制提示时,会出现整数变量a的魔法方法__add__。

定义类的四则运算(__add__、__sub__、__mul__):

class Value(object):
    def __init__(self, x):
        self.x = x

    def __add__(self, other):
        return self.x + other.x

    def __sub__(self, other):
        return self.x - other.x

    def __mul__(self, other):
        return self.x * other.x


a = Value(10)
b = Value(20)
print(a + b)
print(a - b)
print(a * b)

结果:

30
-10
200

二、元类

定义类之后,当对类进行实例化时,

step1:先调用__new__创建一个实例

step2:再调用__init_对实例赋值初始化赋值

class Test(object):
    def __new__(cls, *args, **kwargs):
        print("调用__new__")
        return super(Test, cls).__new__(cls)
    
    def __init__(self, x, y):
        self.x = x
        self.y = y
        print("调用__init__")


Test(10, 100)

结果:

调用__new__
调用__init__

三、对象的字符串描述

__str__和__iter__均是输出对象的字符串表示:__str__在使用str()函数或者print()函数时,自动调用;而__iter__在使用iter()函数或者在命令行窗口输入对象名时,自动调用。

各自的触发场景

此外,

__str__:面向用户,显示的信息更人性化。

__repr__:面向开发、终端,显示的信息更全。

In [70]: now = datetime.datetime.now()

In [71]: import datetime

In [72]: now = datetime.datetime.now()

In [73]: str(now)
Out[73]: '2024-01-02 19:26:18.562440'

In [74]: repr(now)
Out[74]: 'datetime.datetime(2024, 1, 2, 19, 26, 18, 562440)'

四、让类实例像函数一样被调用

__call__函数可以让类实例可以像函数一样被调用。

class Test(object):
    def __call__(self, *args, **kwargs):
        print("__call__被调用了!")

obj = Test()
obj()

结果:

__call__被调用了!

五、对象属性

__len__函数让类实例可以使用len函数:

class Test(object):
    def __init__(self, x):
        self.x = x

    def __call__(self, *args, **kwargs):
        return "__call__被调用了!"

    def __len__(self):
        return len(self.x)


obj = Test([1, 2, 3, 4, 5])
print(obj())
print(len(obj))

结果:

__call__被调用了!
5

六、索引访问

当访问对象的属性不存在时,调用__getattr__。

__setattr__:顾名思义,对类实例执行设置操作时调用(属性赋值)。

__setitem__、__getitem__:使用索引方式对类实例进行赋值和获取操作时调用。

class Test(object):
    def __init__(self, x, y=None):
        print("begin __init__")
        self.x = x
        self.y = y
        print("end __init__")

    def __call__(self, *args, **kwargs):
        return "__call__被调用了!"

    def __len__(self):
        return len(self.x)

    def __getattr__(self, item):
        print("__getattr__被调用了!")

    def __setattr__(self, key, value):
        print("__setattr__被调用了!")
        super(Test, self).__setattr__(key, value)

    def __getitem__(self, item):
        print("__getitem__被调用了!")
        return self.x[item]

    def __setitem__(self, key, value):
        print("__setitem__被调用了!")
        self.x[key] = value

结果:

属性u不存在,__getattr__被调用。

1、类Test的__init__函数中存在2个属性赋值,__setattr__被调用2次。

2、属性z本来不存在,__setattr__被调用1次。

3、通过索引方式,对类实例进行索引取值操作,调用__getitem__函数。

4、通过索引方式,对类实例索引赋值操作,调用__setitem__函数。

本文原始版本发表链接:

https://mp.weixin.qq.com/s?__biz=MzI2Mjg3NTY5MQ==&mid=2247484723&idx=1&sn=8d9104afd64c66d43d59c3340394bf00&chksm=ea453a77dd32b3610308427a09ac95eb6bb58d9f0d4fba7e2443f965acabb97eeb0a3f223d5e#rd

kelly会在公众号「kelly学技术」不定期更新文章,感兴趣的朋友可以关注一下,期待与您交流。

--over--

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值