python 面向对象之魔术方法

1994 篇文章 51 订阅
1221 篇文章 21 订阅

相信很多使用 python 的小伙伴都有一个困惑,在看一些库的源码时,发现源码中有很多 __XX__(双下划线开头,双下划线结尾)的方法。

比如我们在定义类时,经常用到的初始化方法 __init__,在 python 中像 __init __ 这类双下划线开头和结尾的方法,我们把它统称为魔术方法(也有叫魔法方法和特殊方法的)。

今天就专门和大家一起来聊聊 python 中的魔术方法,首先我们来看看魔术方法有哪些特征。

  魔术方法的特征>>>>            
  • 魔术方法都是双下划线开头,双下划线结尾的方法
  • 魔术方法都是 python 内部事先定义的,是对象相关行为的底层实现方法
  • 魔术方法都是在特定的情况下自动化触发的,一般不会直接去调用。

 接下来我们一起看看 python 中场景的一些魔术方法......            
          

  1、__new__ 方>>>>            

相信大多的程序员,都听说过 new一个对象 这句话(如下图),

图片

在很多的编程语言中创建对象都是使用的 new 来创建的,那么在咱们 python 中呢?其实也有一个 new,它是一个魔术方法,接下来我们一起来看看。

  • 问题:python 创建一个对象的时候,调用的第一个方法是什么?

很多小伙伴会说是 __init__,其实不然,正确答案是:__new__ 方法

  • 问题:那么这个 __new__ 方法呢,它有什么作用?又在什么时候会调用呢?

接下来我们一起来看看下面这个案例段代码:

class Test(object):
    def __init__(self):
        print('-------init------方法')

    def __new__(cls, *args, **kwargs):
        print('------new方法-------')

t = Test()
print(t)

运行上面的代码,发现 __new__ 执行了,__init__ 没有执行,创建出来的对象变成了 None.

  • 为什么会出现这样的情况呢?

原因是我们重写了父类 object 中的 __new__ 方法,当我们没有自定义 __new__ 方法时,默认继承了 object 的 __new__ 方法,我们使用类创建对象时,底层会自动调用这个方法来完成对象的创建。那么我们自己定义了这个方法之后呢?

方法中没没有创建对象,也没有返回对象,所以最终创建的对象打印为 None,而 __init__ 方法是一个实例方法,是创建对象之后用来初始化对象的,但是 new 方法中并没有创建出来对象,所以 __init__ 方法也没有执行。

__new__ 一般情况下我们都不会自己去重定义,只有在有特定的需求时才会去用,比如要修改或者控制类创建对象行为时,如实现单例类等等。

  2、上下文管理器>>>>          

相信很多小伙伴都用过 python 中的 with,也都指定可以同它来操作文件,文件会自动关闭。那么大家有没有思考过一个问题,为什么 with 打开文件为何会自动关闭?

  • 问题:with 打开文件为何会自动关闭?

其实 with 操作文件不需要关闭的原因是,因为 with 启动的文件操作的上下文管理器协议。

  • 什么上下文管理器协议?

所谓的上下文管理器协议,是由两个魔术方法实现的。在 python 中只要任意一个类中实现了 __enter__ 和 __exit__ 这两个方法,那么这个类就实现了上下文管理器协议,这个类的对象就可以使用 with 来进行操作。

  • object.__enter__(self)

使用 with 操作实现上下文管理器协议的对象时,则会自动调用这个对象的 __enter__ 方法,with 语句将该方法非返回赋值给到 as 后面的变量。

object.__exit__(self, exc_type, exc_val, exc_tb)
​​

exc_type : # 异常类型
exc_val : # 异常值
exc_tb : # 异常回溯追踪

当 with 中的代码执行完毕之后,会自动调用 __exit__ 方法退出上下文管理器。如果该上下文退出时没有异常,三个参数都将为None。

如果提供了一个异常,并且该方法希望抑制该异常(即防止它被传播),它应该返回一个真值。

否则,在退出此方法后,异常将被正常处理。注意__exit__()方法不应该重新抛出传递进去的异常;这是调用者的责任。

  案例:  
手动实现操作文件的上下文管理器。。。  
​​​​​​
class OpenFile(object):
    '''手动实现文件操作的上下文'''
    def __init__(self,filename,method):
        #初始化打开文件
        self.file = open(filename,method)

    def __enter__(self):
        #启动上下文时,将打开的对象返回出去
        return self.file

    def __exit__(self, exc_type, exc_val, exc_tb):
        #退出上下文时,将文件关闭
        self.file.close()

with OpenFile('python.txt','w') as f:
    f.write('hello')

  3、__call__ 方法>>>>            

  • 问题:python 中万物皆对象,函数也是对象,为什么函数可以调用,而其他的对象不行?
     
  • 需求:如果想让类创建出来的对象,可以像函数一样被调用可以实现吗?
 我们只需要再类里面定义魔术方法 __call__ 方法即可实现,__call__ 中可以定义对象调用的逻辑。
​​​​​​
class Test(object):
def __call__(self):
print('触发了call方法')

t = Test()

t()

4、__str__ 方法>>>>              

  • 问题思考:交互环境下 print 打印的内容和和直接输入变量,返回的内容不一样这是为什么?
    • 使用 print 打印的时候触发的是 __str__ 方法
  • 注意点:
    • 重写 `str,必须要记得写 return。
    • return 返回的必须是一个字符串对象。
代码演示:
class Test(object):
    def __init__(self,name):
        self.name = name
    def __str__(self):
        return '触发了str方法'

python 的内置函数 str

  • 内置函数 str 转换一个对象时,触发对象对应 __str__ 的方法。
  • 内置函数 format 处理对象是,触发对象对应 __str__ 的方法。

  5、算术运算的实现>>>>           

图片

思考问题1:python 中不仅数值之间能相加,字符串和列表,元祖之间也能进行,这是怎么实现的?

同类型对象之间使用 + 号的时候,实际上是触发了 __add__ 魔术方法。

小案例验证:​​​​​​​

class Test(object):

    def __init__(self,name,age):
        self.name = name
        self.age = name

    def __add__(self, other):
        print('对象之间使用了+号')
        return self.age+other.age

xiaoming = Test('小明',18)
laowang = Test('老王',48)

print(xiaoming+laowang)

思考问题2:数值之间能用-进行运算,字符型、列表元祖为什么不行?

其实也是魔术方法来实现的,python 的 int 类中实现了 __sub__ 方法,字符串,列表等数据类型没有,所有的算术运算底层都是调用相应的魔术方法来实现的。

其他算术运算符对应的魔术方法:​​​​​​​
__add__(self, other)  定义加法的行为:+
__sub__(self, other)  定义减法的行为:-
__mul__(self, other)  定义乘法的行为:*
__truediv__(self, other)  定义真除法的行为:/
__floordiv__(self, other)  定义整数除法的行为://
__mod__(self, other)  定义取余算法的行为:%

P.s. 关于 python 中的魔术方法就暂时给大家介绍到这里,更多的魔术方法,大家可以自行扩展学习, 并请持续关注我们哦~~

行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 786229024,里面有各种测试开发资料和技术可以一起交流哦。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

在这里插入图片描述

软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 魔术方法Python中的特殊方法,它们以双下划线开头和结尾,例如__init__、__str__、__add__等。这些方法可以在类的实例化、运算符重载、属性访问等方面提供特殊的行为。 __init__方法是一个特殊的构造函数,用于初始化类的实例。__str__方法用于返回对象的字符串表示形式,可以通过print函数输出。__add__方法用于重载加法运算符,可以实现自定义的加法操作。其他常用的魔术方法还包括__eq__、__lt__、__gt__等,用于比较运算符的重载。 学习魔术方法可以让我们更好地理解Python面向对象编程的特性,提高代码的可读性和可维护性。 ### 回答2: 魔术方法Python中最有趣且也是最强大的概念之一。魔术方法(也称为特殊方法或双下划线方法)是一些特殊的方法,它们以双下划线(__)开头和结尾,并具有特定的名称。 这些特殊方法可以为我们提供许多有用的功能,例如重载操作符,处理类的属性,实现自定义迭代器,使用描述符等。 下面是一些常见的魔术方法: __init__:这是最常见的魔术方法。当创建一个实例时,它会被自动调用。它用于初始化对象的属性。 __str__:当你想要将一个对象转换成字符串时,这个方法会被调用。如果你不指定__str__方法Python默认会使用对象的类名和内存地址来表示对象。 __repr__:这个方法和__str__方法类似,也是用于将对象转换成字符串。但是__repr__方法在调试时有很大的作用,因为它返回的字符串可以用来唯一地标识对象。 __len__:这个方法可以返回对象的长度。例如,如果你想获取一个字符串的长度,你可以使用len("hello"),在底层,它实际上是调用了字符串对象的__len__方法。 __getattr__和__setattr__:这些方法允许你动态地获取和设置对象的属性。当你访问一个不存在的属性时,__getattr__方法会被调用。当你设置一个属性时,__setattr__方法会被调用。 __call__:这个方法允许你将对象作为函数调用。当你调用一个对象时,Python实际上是在调用对象的__call__方法。 除了上面列举的方法,还有许多其他的魔术方法,例如__cmp__,__hash__,__iter__等等。学习这些魔术方法将使你能够更好地理解Python面向对象编程模型。 总之,学习和理解魔术方法Python面向对象编程中的一个关键概念,因为它们可以帮助你实现更加灵活和强大的代码。如果你想成为一名Python高手,那么深入学习魔术方法是不可避免的。 ### 回答3: Python中的“魔术方法”指的是每个类中定义的特殊方法,它们以双下划线(__)开头和结尾,并且有着特定的用途。通过使用这些魔法方法,我们可以自定义类的行为,并为程序提供更高级别的功能。 以下是Python中常用的一些魔术方法: 1. __init__:这是最常用的魔术方法之一,它用于初始化一个类的对象,以及定义类的属性和方法。 2. __str__:此方法用于返回对象的字符串表示形式,类似于Java中的toString()方法。 3. __repr__:与__str__类似,但是返回的是对象的“官方”字符串表示形式,通常用于调试和开发。 4. __getattr__:当试图访问一个不存在的属性时,此方法被调用。 5. __setattr__:当尝试设置类的属性时,此方法被调用。 6. __delattr__:当尝试删除类的属性时,此方法被调用。 7. __call__:将对象作为函数调用时,此方法被调用。 8. __len__:返回对象的长度。 9. __getitem__:允许通过索引访问对象的元素。 10. __setitem__:允许通过索引设置对象的元素。 11. __delitem__:允许通过索引删除对象的元素。 通过了解和使用这些魔术方法,我们可以编写出更高效、更灵活、更具可读性的Python代码,并且实现类似于内置类型一样的功能。例如,我们可以实现一个自定义列表,类似于Python的list类型,然后使用上述魔术方法来访问、设置和删除元素。同时,我们还可以自定义变量和函数的行为,使我们的Python代码变得更具有表现力和弹性。 总之,了解和掌握Python魔术方法Python编程中必不可少的一部分,对于理解和编写实际应用程序非常有价值。在实践中,我们可以根据实际情况选择恰当的魔术方法,从而创建更灵活、更高效的Python类。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值