概述
1.什么是魔法函数
在python中,有的名称以双下划线开头同时以双下划线结尾这种形式,
我们只知道它是python自己定义的,同时我们也不应该去定义类似的函数。
我们将“__init__”这种形式的函数成为魔法函数。"__init__"是构造器,用来初始化对象。
魔法函数不需要去显式的调用,同时魔法函数不能自定义。
魔法函数会被python隐式的去被调用。
举个简单的例子:
现在我们需要遍历对象中的属性,传统做法是取属性然后去遍历。
classPerson(object):def __init__(self,p_list):
self.p_list=p_list
person= Person(["ming","ke","mao"])for em inperson.p_list:print(em)
我们可以使用__getitem__来更简单的实现。classNewPerson(object):def __init__(self,p_list):
self.p_list=p_listdef __getitem__(self, item):returnself.p_list[item]
newPerson= NewPerson(["ming","kebi","mao"])#这里就不需要取属性了。
for em innewPerson:print(em)
我们可以通过不添加__getitem__,来知道__getitem__是将对象转换成可迭代对象。
#‘NewPerson‘ object is not iterable
在python中,只有可迭代对象才可以进行遍历,而可迭代对象必须拥有item()或者__item__方法。
当python在进行循环的时候,会去看对象是否由item()方法,如果没有会去看是否与__getitem__魔法函数,否则就不能迭代。
2.python魔法函数对python语法的影响
魔法函数会影响python语法本身。
示例一:
classNewPerson(object):def __init__(self,p_list):
self.p_list=p_list
newPerson= NewPerson(["ming","kebi","mao"])print(len(newPerson)) #TypeError: object of type ‘NewPerson‘ has no len()
print(len(newPerson[:])) #TypeError: ‘NewPerson‘ object is not subscriptable
对象没有长度和不能切片可以理解。
示例二:
classNewPerson(object):def __init__(self,p_list):
self.p_list=p_listdef __getitem__(self, item):returnself.p_list[item]
newPerson= NewPerson(["ming","kebi","mao"])print(len(newPerson)) #TypeError: object of type ‘NewPerson‘ has no len()
print(len(newPerson[:])) #3
newPerson之所以能够切片是因为__getitem__返回的是一个list,而list肯定可以切片
newPerson在取值的时候调用了__gititem__这个魔法方法,从而返回list,所以newPerson[]有len
示例三:
classNewPerson(object):def __init__(self,p_list):
self.p_list=p_listdef __getitem__(self, item):returnself.p_list[item]def __len__(self):returnlen(self.p_list)
newPerson= NewPerson(["ming","kebi","mao"])print(len(newPerson)) #3 调用__len__
print(len(newPerson[:])) #3 调用__getitem__
现在我们帮这个对象实现了__len__这个方法,所以这个newPerson对象可以可以直接使用len()
此时newPerson[:]因为是取值,依旧使用的是__getitem__这个方法。
3.魔法函数一览
使用dir()或者__dir__可以或者一个对象已经定义的的魔法函数。
例如:dir(Person)
__class__ 等同于type,打印对象类似
__delattr__
__dict__ 等同于vars,以键值对的形式返回对象的属性信息
__dir__
__doc__ 帮助文档
__eq__
__format__
__ge__
__getattribute__
__gt__
__hash__
__init__ 构造器
__init_subclass__
__le__
__lt__
__module__
__ne__
__new__
__reduce__
__reduce_ex__
__repr__
__setattr__
__sizeof__
__str__
__subclasshook__
__weakref__
我们将魔法方法分为:非数学运算和数学运算两大类
1)非数学运算
(1)字符串
__repr__
__str__
(2)集合序列相关
__len__
__getitem__:将当前对象转换为可迭代对象,因而可以切片。
__setitem__
__delitem__
__contains__
(3)迭代相关
__iter__
__next__
(4)可调用
__call__
(5)with上下文管理器
__enter__
__exit__
(6)数值转换
__abs__
__bool__
__int__
__float__
__hash__
__index__
(7)元类相关
__new__
__init__
(8)属性相关
__getattr__:没有属性做什么
__setattr__
__getattribute__
__setattribute__
__dir__
(9)属性描述符
__get__
__set__
__delete__
(10)协程
__await__
__aiter__
__anext__
__aenter__
__aexit__
2)数学运算
(1)一元运算符
__neg__ (-)
__pos__ (+)
__abs__
(2)二元运算符
__lt__ (
__le__ (<=)
__eq__ (==)
__ne__ (!=)
__gt__ (>)
__ge__ (>=)
(3)算术运算符
__add__ (+)
__sub__ (-)
__mul__ (*)
__truediv__ (/)
__floordiv__ (//)
__mod__ (%)
__divmod__ 或divmod()
__pow__ 或pow() (**)
__round__ 或round()
(4)反向算术运算符
__radd__
__rsub__
__rmul__
__rtruediv__
__rfloordiv__
__rmod__
__rdivmod__
__rpow__
(5)增量赋值算术运算符
__iadd__
__isub__
__imul__
__ifloordiv__
__ipow__
(6)位运算符
__invert__ (~)
__lshift__ (<
__rshift__ (>>)
__and__ (&)
__or__ (|)
__xor__ (^)
(7)反向位运算符
__rlshift__
__rrshift__
__iand__
__ixor__
__ior__
(8)增量赋值运算符
__ilshift__
__irshift__
__iand__
__ixor__
__ior__
3)__str__、__repr__
classPerson(object):def __init__(self,p_list):
self.p_list=p_list
person= Person(["ming","UZI","karsa"])print(person) #<__main__.person object at>
print会隐式调用str,也就是__str__
现在可以修改一下__str__返回值。classPerson(object):def __init__(self,p_list):
self.p_list=p_listdef __str__(self):return ".".join(self.p_list) #默认return self
person = Person(["ming","UZI","karsa"])#本来是返回这个对象的内存地址,现在我们修改了返回值。
print(person) #ming.UZI.karsa
classPerson(object):def __init__(self,p_list):
self.p_list=p_list
person= Person(["ming","UZI","karsa"])
person#<__main__.person at>
隐式调用repr(person)classPerson(object):def __init__(self,p_list):
self.p_list=p_listdef __repr__(self):return "+".join(self.p_list)
person= Person(["ming","UZI","karsa"])
person#ming+UZI+karsa
反思:
我们在写代码的时候,比如定义a = 11,我们如果想获取它的绝对值,就会用abs(a)来进行获取。
此时我就会想为什么a就能用abs来获取绝对值了?因为它已经定义了
在init中定义了这个魔法方法,所以你才能够使用这些方法。
就像上面,如果我们没有定义__len__这个方法,那么按照常理是不能使用len(),
因为不支持,它是一个对象,对象里面原始定义也没有定义。
所以我们可以给它实现__len__这个魔法函数,person这个对象就可以使用了。
比如我们定义了一个类:
classNum(object):def __init__(self,value):
self.value=value
a= Num(1)print(abs(a)) #TypeError: bad operand type for abs(): ‘Num‘
现在a是一个新的类Num的对象,并不是int的对象,所以它是无法使用abs()的。
我们给它添加魔法函数__abs__之后就可以了。
classNum(object):def __init__(self,value):
self.value=valuedef __abs__(self):returnabs(self.value)
a= Num(1)print(abs(a))
比如我们再定义一个:
classMyVector(object):def __init__(self,x,y):
self.x=x
self.y=ydef __add__(self,other_instance):return MyVector(self.x + other_instance.x, self.y +other_instance.y)def __str__(self):return "x:{x}, y:{y}".format(x=self.x, y=self.y)
first_v= MyVector(1,2)
second_v= MyVector(3,4)print(first_v + second_v) #x:4, y:6
如果我们不定义__add__,那就是两个对象在加
最后
以上就是大胆西牛为你收集整理的python魔法数_魔法函数的全部内容,希望文章能够帮你解决python魔法数_魔法函数所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复