Python 官方文档:入门教程 => 点击学习
这篇文章将为大家详细讲解有关python常用的魔法方法是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。一、Python魔法方法Python的魔法方法会在特定的情况下自动调用,且他们的方法名通常被双下划
这篇文章将为大家详细讲解有关python常用的魔法方法是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。
Python的魔法方法会在特定的情况下自动调用,且他们的方法名通常被双下划线包裹,之前我们学习的构造函数和析构函数就属于魔法方法
Python中同样有运算符重载,其实所有的运算符都是使用了对应的魔法方法来处理的对象的,魔法方法对应的操作符如下
我们来举一个简单的例子
class A: def __init__(self,x): self.x = x def __add__(self,other): return int(self.x)+int(other.x)a = A(3.3)b = A(5.2)print(a+b)
类似的还有反运算重载和增量复制运算,用处较少,不再解释
__str__(self)
:返回值是str类型的,当我们需要以字符串的形式输出对象时(调用print时),就会自动调用该方法,举个例子
class A: def __str__(self): return '我真帅'a = A()print(a)# 我真帅
__repr__(self)
:返回值是str类型的,当我们直接在shell中输入对象名并按下回车,就会自动调用该方法,他也有和__str__
一样的功能,但如果两者你都重写了,在使用print时,__str__
的优先级高,__repr__
是给机器看的,__str__
是给人看的,举个例子
>>> class A: def __str__(self): return '我真帅' def __repr__(self): return '我是世界第一帅'>>> a = A()>>> a我是世界第一帅>>> print(a)我真帅
__getattr__(self, name)
:定义当用户试图获取一个不存在的属性时的行为,其中name是属性名,是一个字符串,下同
__getattribute__(self, name)
:定义当该类的属性被访问时的行为,该方法默认返回该属性的值
__setattr__(self, name, value)
:定义当一个属性被设置时的行为,value是给该属性的值
__delattr__(self, name)
:定义当一个属性被删除时的行为
例如:
class A: def __init__(self): self.id = "Pyhon" def __getattr__(self,name): print(name+"这个属性不存在") def __getattribute__(self,name): print("我访问了"+name+"这个属性") return super().__getattribute__(name) def __setattr__(self,name,value): print("将属性"+name+"置为"+value) super().__setattr__(name,value) def __delattr__(self,name): print("将属性"+name+"删除了"); super().__delattr__(name) def fun(self): passa = A()a.namea.name = "老师"del a.namea.fun()# output:# 将属性id置为Pyhon# 我访问了name这个属性# name这个属性不存在# 将属性name置为老师# 将属性name删除了# 我访问了fun这个属性
结果可以看出,当我们访问一个属性的时候,先是调用了__getattribute__
,如果该属性不存在,则再调用__getattr__
使用这几个的方法的时候,要注意不要陷入无限递归,运算符重载的时候也容易犯这种错误,例如下面的错误
class A: def __init__(self): self.id = "Pyhon" def __setattr__(self,name,value): print("将属性"+name+"置为"+value) if(name == "id"): self.id = valuea = A()
执行这段程序的时候将陷入无限递归,原因是在__setattr__
中,直接给self对象的属性赋值,而这又会调用__setattr__
方法。
所以在__setattr__
中,我们通常会使用父类的__setattr__
方法来给self对象的属性赋值,这不会陷入无限递归,其他几个方法和运算符重载也是同理,上面程序订正后如下
class A: def __init__(self): self.id = "Pyhon" def __setattr__(self,name,value): print("将属性"+name+"置为"+value) if(name == "id"): super().__setattr__(name,value)a = A()# output# 将属性id置为Pyhon
__get__(self, instance, owner)
:通过其他实例对象来访问该类的实例对象时会调用该方法,返回该实例对象的引用。其中instance是访问该对象的实例对象的引用,下同,owner是访问该对象的类对象
__set__(self, instance, value)
:通过其他实例对象来给该类的实例对象赋值时会调用该方法。其中value是给该对象赋的值
__delete__(self, instance)
:通过其他实例对象来删除该类的实例对象时会调用该方法
class Fit: def __init__(self): self.height = 180 self.weight = 80 def __get__(self,instance,owner): print("get:",instance,owner) return [self.height,self.weight] def __set__(self,instance,value): print("set:",instance,value) self.height = value self.weight = value/2 def __delete__(self,instance): del self.height del self.weight print("delete:",instance)class Test: fit = Fit() t = Test()print (t.fit)t.fit = 190del t.fit# output:# get: <__main__.Test object at 0x0000023EFFA738C8> <class '__main__.Test'># [180, 80]# set: <__main__.Test object at 0x0000023EFFA738C8> 190# delete: <__main__.Test object at 0x0000023EFFA738C8>
通常情况下,上面几个魔法方法,当我们需要定义一个属性,且希望可以直接对该属性进行相应的操作,而不是通过调用方法的方式来进行操作时,我们可以定义一个该属性的类,实现上面几个魔法方法,将需要用到的属性作为其实例对象,这样就完成了,例如上面的Fit,其实就是体型类,而Test中有一个体型属性叫fit,我们在Fit中定义了一些对Fit的实例对象操作时执行的操作。
__len__(self)
:定义当该类的实例对象被len()调用时的行为
__getitem__(self, key)
:定义获取该类的实例对象中指定元素的行为,也就是说执行self[key]时的行为
__setitem__(self, key, value)
:定义设置该类的实例对象中指定元素的行为,相当于self[key] = value
__delitem__(self, key)
:定义删除该类的实例对象中指定元素的新闻,相当于del self[key]
class CountList: def __init__(self,*args): self.values = [x for x in args]#这是一个列表推导式,把args里的元素作为values的元素 self.count = {}.fromkeys(range(len(self.values)),0) def __len__(self): return len(self.values) def __getitem__(self,key): self.count[key] += 1; return self.values[key]c = CountList(1,3,5,7,9,11)print(c[1])print(c[1]+c[2])print(c.count)# output:# 3# 8# {0: 0, 1: 2, 2: 1, 3: 0, 4: 0, 5: 0}
该类中的count是记录对应元素被访问的次数,其他两个也差不多,不再举例了
迭代器,就是提供了迭代方法的容器,而所谓的迭代方法,就是下面这两个__iter__
和__next__
可迭代,就是提供了__iter__
方法的容器,我们之前讲的字符串,列表,元组,字典,集合都是可迭代的,但他们不是迭代器,可以使用Python的内置函数iter(iterable)
来获取他们相应的迭代器,而迭代器使用next(iterator)
可以获取下一个元素,而这两个方法其实就是调用了迭代器的__iter__
和__next__
__iter__(self)
:定义获取迭代器时的行为
__next__(self)
:定义获取迭代器对应的下一个元素时的行为
class Fb: def __init__(self,n = 20): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): t = self.a self.a = self.b self.b = t + self.b if(self.a <= self.n): return self.a else: raise StopIterationf = Fb()for i in f: print(i,end=' ')# output:1 1 2 3 5 8 13
其中 raise 是返回一个异常,上面的程序等价于下面这个
class Fb: def __init__(self,n = 20): self.a = 0 self.b = 1 self.n = n def __iter__(self): return self def __next__(self): t = self.a self.a = self.b self.b = t + self.b if(self.a <= self.n): return self.a else: raise StopIterationf = Fb()it = iter(f)while True: try: i = next(it) print(i, end=' ') except StopIteration: break;
这样我们就很清楚Python中for循环的原理了,先通过iter来获取迭代器对象,然后不断调用next来获取下一个元素赋值给i,直到遇到StopIteration异常
关于“Python常用的魔法方法是什么”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。
--结束END--
本文标题: Python常用的魔法方法是什么
本文链接: https://lsjlt.com/news/279126.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0