python中的魔法函数
在python中存在一些 以下划线开头的函数 ,比如创建类时用到的 __init__
,单例设计模式用到的 __new__
等,它们统称为魔法函数。
为什么叫做魔法函数? 因为这些函数 使用简单,能够使作用对象具备 额外属性,让作用对象看起来像被施了魔法一样。
1.魔法函数的特性
- 1.魔法函数是 独立的存在,无需继承 就可以添加到 任何类 中,使用时 无需显式调用。
比如__init--
:
class Dog(object):
"""Dog类"""
def __init__(self, name):
self.name = name
print("{}汪汪汪!".format(self.name) )
dog = Dog("旺财")
# 输出
旺财汪汪汪!
上述语句定义了一个简单的 Dog类
,并用变量 dog
进行实例化,那么python解释器是怎样根据上述代码创建 dog实例
的呢?
1)在内存中为dog实例 分配空间
2) 调用 __init__
方法 为dog实例初始化
dog = Dog("旺财")
会将 变量dog 的 内存地址 传递给 __init__中的self
,并将“旺财”传递给形参 name
,从而进行 dog实例 的初始化。对于 __init__
,它没有从任何类继承,我们也没有显示调用它,只要我们在类中定义了 __init__
方法,这一些列过程就能在python解释器中自发完成。
- 2.魔法函数能够是作用对象具备 额外属性
来看下面的代码:
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
company = Company(["neko", "clare", "kuro"])
for com in company:
print(com)
# 输出
TypeError: 'Company' object is not iterable
我们想通过 for 循环输出每一个员工,但报错 Company类不是可迭代的类型
。可以看出员工列表存储在 实例属性 self.employee中,所以可以这样:
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
company = Company(["neko", "clare", "kuro"])
#利用变量elem来引用实例属性
elem = company.employee
for com in elem:
print(com)
#输出
neko
clare
jija
再来思考下,报错的是 Company是不可迭代类型, 那么 把Company变为可迭代的类型 是不是就能直接输出了呢?
class Company(object):
def __init__(self, employee_list):
self.employee = employee_list
# 不属于company,也不属于object,起到增强属性的作用
def __getitem__(self, item):
return self.employee[item]
company = Company(["neko", "clare", "jija"])
for com in elem:
print(com)
print(company[:2])
# 输出
neko
clare
jija
['neko', 'clare']
可以看到,通过魔法函数 __getitem__
成功的让 Company类具备可迭代的属性,甚至能使用 切片 操作!
通过魔法函数可以让作用对象具备额外属性,从而让代码更加灵活。
2.常用的魔法函数
如下图:
可以看到 __getitem__
属于序列相关的魔法函数,能够使作用对象 具备序列相关特性,序列本身就属于 可迭代类型 ,切片也是序列的一个常用方法,所以上面的代码才能有那样的效果。
具体每个函数的作用,可以自己去尝试,或者遇到了现查。
小结
魔法函数能够使python代码更简洁、更python,数量掌握常用魔法函数是python进阶必不可少的一项技能,而且在看大牛的代码时会经常遇到,所以一起加油!