当前位置: 首页 > 科技观察

魔法方法推开Python进阶学习大门

时间:2023-03-21 14:39:11 科技观察

神奇方法开启Python进阶学习之门转载本文请联系PythonMind公众号。LovePythonPython是GuidovanRossum设计的一种让用户如沐春风的编程语言。2020年11月12日,这位64岁的Python之父宣布,他决定加入微软的DevDivTeam,以“确保更好地使用Python”,因为他的退休生活太无聊了。虽然国内有些声音在dissPython,认为它太过简单,只是一门脚本语言,但它的发明者对Python的狂热依然激励着我们坚持对Python的热爱。龟叔是所有编程语言发明者中头发最多的。奇迹时刻collection.len()是用面向对象语言写的,len(collection)是用Python语言写的。这种风格被称为Pythonic。从前者到后者,犹如变魔术一般,瞬间让人眼前一亮。这个魔法就是Python的魔法方法,或者说双下划线方法,是一种以双下划线开头,以双下划线结尾的特殊方法,比如obj[key],Python解释器实际上会把它转换成obj。__getitem__(key)运行,但是用户没有感知到。__getitem__和__len____getitem__用于获取数据,__len__用于返回长度。这两个魔术方法是Python的基础。我们可以通过一副牌来理解:importcollections#定义一副牌Card=collections.namedtuple('Card',['rank','suit'])classFrenchDeck:#sizeranks=[str(n)forninrange(2,11)]+list('JQKA')#suits='spadesdiamondsclubshearts'.split()def__init__(self):#生成一副牌self._cards=[Card(rank,suit)forsuitinself.suitsforrankinself.ranks]def__len__(self):returnlen(self._cards)def__getitem__(self,position):returnsself._cards[position]本来我们不能对这副牌做任何事情,但是因为__len__的实现,我们可以使用len()查看有多少张卡片的函数:>>>len(deck)52由于__getitem__的实现,我们可以使用方括号索引来获取值:>>>deck[0]Card(rank='2',suit='spades')可以切片:>>>deck[:3][Card(rank='2',suit='spades'),Card(rank='3',suit='spades'),Card(rank='4',suit='spades')]>>>deck[12::13][Card(rank='A',suit='spades'),Card(rank='A',suit='钻石'),Card(rank='A',suit='clubs'),Card(rank='A',suit='hearts')]可以迭代:>>>forcardindeck:#doctest:+ELLIPSIS...print(card)Card(rank='2',suit='spades')Card(rank='3',隋t='spades')Card(rank='4',suit='spades')...我发现没有,可以用魔术方法装B!别人写类的时候只能get和set,你写类也能显花样。Python解释器使用666Python魔术方法。一般不需要直接调用。Python会自行调整。例如,将len(my_object)写成my_object.__len__()是弄巧成拙的。魔术方法实现运算符前面的例子实现了值和长度,再看另一个例子,使用__repr__,__abs__,__bool__,__add__,__mul__实现运算符:frommathimporthypot#two-dimensionalvectorclassVector:def__init__(self,x=0,y=0):self.x=xself.y=y#expressiondef__repr__(self):return'Vector(%r,%r)'%(self.x,self.y)#absolutevaluedef__abs__(self):returnhypot(self.x,self.y)#Booleandef__bool__(self):returnbool(abs(self))#additiondef__add__(self,other):x=self.x+other.xy=self.y+其他.yreturnVector(x,y)#multiplicationdef__mul__(self,scalar):returnVector(self.x*scalar,self.y*scalar)__add__实现加法:>>>v1=Vector(2,4)>>>v2=Vector(2,1)>>>v1+v2Vector(4,5)__abs__实现绝对值:>>>v=Vector(3,4)>>>abs(v)5.0__mul__实现乘法:>>>v*3Vector(9,12)__repr__实现对象的字符串表示:Vector(4,5)否则得到的字符串可能是。__bool__implementsBooleanvalues:ifVector(4,5):returnTrue其他魔法方法一篇文章说不完魔法方法。我们将在后续文章中继续讨论如何使用和实现它们。Tips本节内容是我第一次看?时记录的知识点:collections.namedtuple可以用来创建只有几个属性没有方法的对象,比如beer_card=Card('7','diamonds')2.random.choice和random.sample的区别在于sample是返回序列,choice是返回元素。使用sample(list,1)[0]时,最好直接使用choice(list)。存在由Python解释器调用的特殊方法。PyVarObject是一种C语言结构,表示内存中的可变长度内置对象。list或str或bytearray的__len__实际上返回PyVarObject.ob_size属性,这比调用方法快得多。len之所以不是普通方法,是为了让python自带的数据结构走后门,abs也是一样。很多时候调用__init__方法的目的是在自己子类的__init__方法中调用超类的构造函数。abs,如果输入是整数或浮点数,则返回输入值的绝对值;如果输入是复数,则返回复数的模数。如果你在__repr__和__str__之间选择,__repr__更好,因为如果一个对象没有__str__函数,解释器将使用__repr__代替。python对象的一个??基本要求是它有一个合理的字符串表示,这就是为什么在数据模型中有特殊方法__repr__和__str__的原因。判断一个值x是真还是假,python调用了bool(x),后面调用的是x.__bool__()。如果不存在,则调用x.__len__(),返回0为False,非零为True。Python通过运算符重载的方式提供了丰富的数值类型,除了内置的,还有decimal.Decimal和fractions.Fraction。