python 3.x 魔法函数

魔法函数

  • 什么是魔法函数???

    • python中定义以双下划线开始且以双下划线结束的函数,通常称谓魔法函数  
    • 魔法函数可以让我们随意调用.类的魔法函数不是某个类独有的,而是任何类都可以调用,来增强类的特性. 
    • 魔法函数直接影响python语法的本身.
    • 魔法函数实际上影响python中的内置函数的调用
 1 """
 2     普通方法遍历员工名
 3 """
 4 
 5 
 6 class Company(object):
 7     def __init__(self, employee_list):
 8         self.employee_list = employee_list
 9 
10 
11 company = Company(["tom", "jayden", "python"])
12 
13 # 遍历所有的员工名
14 # 结果:
15 #       tom
16 #       jayden
17 #       python
18 for employee in company.employee_list:
19     print(employee)

 

 

 1 """
 2     使用魔法函数来完成员工名的遍历
 3 
 4     __getitem__()魔法函数作用:
 5         将一个类变成可迭代的对象.
 6 
 7     当for...in...遍历一个对象的时候,python解释器会查找该对象下是否有魔法函数__getitem__(),
 8     如果有python解释器调用__getitem__()魔法函数,并且for...in...会从头到尾去增加参数item的值(0,1,2...),
 9     直到__getitem__()魔法函数抛出异常时,for...in...循环结束.
10     如果该对象下没有__getitem__()函数,会抛出异常,TypeError: xxx object is not iterable
11 """
12 
13 
14 class Company(object):
15     def __init__(self, employee_list):
16         self.employee_list = employee_list
17 
18     def __getitem__(self, item):
19         # 参数item是序列的索引
20         return self.employee_list[item]
21 
22 
23 company = Company(["tom", "jayden", "python"])
24 
25 # 结果:
26 #       tom
27 #       jayden
28 #       python
29 for employee in company: # company是可迭代对象
30     print(employee)

 

 1 """
 2     魔法函数直接影响python语法的本身.
 3     魔法函数实际上影响python中的内置函数的调用
 4 """
 5 
 6 
 7 class Company(object):
 8     def __init__(self, employee_list):
 9         self.employee_list = employee_list
10 
11     def __getitem__(self, item):
12         # 参数item是序列的索引
13         return self.employee_list[item]
14 
15 
16 company = Company(["tom", "jayden", "python"])
17 
18 # 结果:
19 #       tom
20 #       jayden
21 #       python
22 for employee in company:  # 通过魔法函数__getitem__()将company变成可迭代对象(影响python语法的本身.)
23     print(employee)
24 
25 # 如果将对象中的魔法函数__getitem__()去除,再运行此代码会报错
26 # TypeError: 'Company' object is not subscriptable
27 # 证明出: 魔法函数影响python语法的本身
28 company1 = company[:2]
29 
30 # 结果:
31 #       tom
32 #       jayden
33 for company in company1:
34     print(company)
35 
36 # 结果: 2
37 # 如果将对象中的魔法函数__getitem__()去除,再运行此代码会报错
38 # TypeError: object of type 'Company' has no len()
39 # 证明出: 魔法函数实际上影响python中的内置函数的调用
40 print(len(company1))

 

 

  • python的数据模型以及数据模型对象python的影响

    • python数据模型:  
      • 实际上在python本身的一种叫法里面魔法函数这个名词用的比较少,    
      • 只是网络上现在很多人喜欢把双下划线的函数叫做魔法函数.
      • 实际上魔法函数是python数据模型的一个概念而已.
      • 理解python的数据模型对理解python的一个设计理念非常重要.

 

  • 魔法函数一览

    • 非数学运算:  

      • 字符串表示:    
        • __repr__ : 开发模式下调用(单独执行一个对象,如: company = Company() --> company      
        • __str__ : 对对象进行字符串格式化时调用.如: print(company) --> 隐含执行print(str(company))      
      • 集合序列相关:    
        • __len__      
        • __getitem__      
        • __setitem__      
        • __delitem__      
        • __contains__      
      • 迭代相关:    
        • __iter__
        • __next__      
      • 可调用:    
        • __call__      
      • with上下文管理器:    
        • __enter__      
        • __exit__      
      • 数值转换:    
        • __abs__      
        • __bool__      
        • __int__
        • __float__      
        • __hash__
        • __index__      
      • 元类相关:    
        • __new__
        • __init__      
      • 属性相关:    
        • __getattr__      
        • __setattr__      
        • __getattribute__
        • __setattribute__      
        • __dir__      
      • 属性描述符:    
        • __get__      
        • __set__
        • __delete__      
      • 协成:    
        • __await__      
        • __aiter__      
        • __anext__      
        • __aenter__      
        • __aexit__      

 

    • 数学运算:  

      • 一元运算符:    
        • __neg__(-): 负数      
        • __pos__(+): 正数      
        • __abs__ : 绝对值  
      • 二元运算符:    
        • __lt__(<)      
        • __le__(<=)      
        • __eq__(==)      
        • __ne__(!=)
        • __gt__(>)      
        • __ge__(>=)  
      • 算术运算符:    
        • __add__(+)      
        • __sub__(-)      
        • __mul__(*)      
        • __truediv__(/)      
        • __floordiv__(//)      
        • __mod__(%)      
        • __divmod__(divmod())      
        • __pow__(** 或 pow())      
        • __round__(round())      
      • 反向算术运算符:    
        • __radd__(+)      
        • __rsub__(-)      
        • __rmul__(*)      
        • __rtruediv__(/)      
        • __rfloordiv__(//)      
        • __rmod__(%)      
        • __rdivmod__(divmod())      
        • __rpow__(** 或 pow())      
      • 增量赋值算术运算符:    
        • __iadd__(+)      
        • __isub__(-)      
        • __imul__(*)      
        • __itruediv__(/)      
        • __ifloordiv__(//)      
        • __imod__(%)      
        • __ipow__(** 或 pow())      
      • 位运算符:    
        • __invert__(~)      
        • __lshift__(<<)      
        • __rshift__(>>)
        • __and__(&)      
        • __or__(|)      
        • __xor__(^)      
      • 反向位运算符:    
        • __rlshift__(<<)      
        • __rrshift__(>>)      
        • __rand__(&)      
        • __ror__(|)      
        • __rxor__(^)      
      • 增量赋值位运算符:    
        • __ilshift__(<<)      
        • __irshift__(>>)        
        • __iand__(&)      
        • __ior__(|)      
        • __ixor__(^)      

 

  • 随便举个例子说明魔法函数的重要性(len()函数)

    • len()函数的特殊性:  
      • 当在调用len()方法的时候会隐含的调用对象的内置函数__len__().    
      • 但是实际上len()方法做得远远不止这些,为什么???    
      • 如果计算某一个列表长度的时候,每一次都去遍历列表来获取长度的话,效率会比较低.    
      • 然而当len()方法里面用的是python中的内置类型(list,dict,set),对len()方法进行操作时,    
      • len()方法在python中会走一个捷径,那是什么捷径呢???    
      • python中list,dict,set这种原身的数据结构实际上都是用c语言来实现的,所以说它们的性能非常高.    
      • 当对这些内置数据类型做len()计算时,len()会直接读取c语言里的一个数据.就是列表的长度.    
      • 所以说在使用len()方法的时候,len()方法实际上直接走捷径,直接读取长度数据,而不是去变量数据.    
      • 所以说使用python的时候,尽量使用python的原身数据类型,    
      • 原身的数据类型,第一性能很高,第二对类型做长度统计的时候,由于python内部做优化.    
      • 所以说性能远远比我们自己用纯python来实现的高.    
    • for...in...遍历自定义类的流程:  
      • python解释器在遇到for...in...语句时,内部会做很多的工作,    
      • 比如在一个类中添加两个魔法函数__iter__(),__getitem__()时,    
      • python解释器会先调用__iter__()获取一个迭代器,然后对该类的实例对象进行遍历.    
      • 如果没有__iter__()函数,会调用__getitem__()函数,然后小心翼翼的处理好异常.    

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

********

posted on 2019-04-03 09:41  jaydenjune  阅读(71)  评论(0)    收藏  举报

导航