一:魔法函数特点
1、 魔法函数也就是魔术方法,是python定义的方法,不属于某个类,不是因为继承而拥有的方法,每一个类都可以添加魔法函数,以双下划线开头和双下划线结尾,例如__getitem__,python内置的魔法函数有很多
2、魔术方法的名称不能随意更改
3、魔术方法对当前这个类进行了功能拓展
4、魔术方法可以更改当前这个类的类型
二:部分魔法函数案例讲解
案例1 __getitem__魔法函数:
例如下面的的类,仅在构造函数里面传入一个列表,如果想对这个实例化对象循环读取值是会报错的
class Student:
def __init__(self,student_list):
self.student_list = student_list
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
for item in student:
print(item)
运行结果如下:
Traceback (most recent call last):
File "F:/myfile/python/code/python3进阶/chapter06/getattr.py", line 32, in <module>
for item in student:
TypeError: 'Student' object is not iterable
提示Student不是一个可迭代的对象,那如何让他变成可迭代呢,getitem这个魔法函数就可以实现,修改如下:
class Student:
def __init__(self,student_list):
self.student_list = student_list
#魔法函数
def __getitem__(self, item):
return self.student_list[item]
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
for item in student:
print(item)
运行结果:
marry
clain
lili
现在Student 就是一个可迭代的对象了。当执行for循环的时候就会自动调用__getitem__这个魔法函数,getitem中的参数item 就是索引,从0开始,直到python运行抛出异常,自动结束for循环。
案例2 __len__魔法函数:
class Student:
def __init__(self,student_list):
self.student_list = student_list
#魔法函数
def __getitem__(self, item):
return self.student_list[item]
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
#student现在是可迭代的,就可以进行切片,切片之后变成一个序列
student_1 = student[:2]
print(type(student_1))
print(len(student_1))
输出结果:
<class 'list'>
2
可以看到Student现在可迭代,可以对实例进行切片,切片后变成一个序列。对这个序列输出长度是可以的,如果我现在想对这个实例的对象求长度呢,可以看下面的代码
class Student:
def __init__(self,student_list):
self.student_list = student_list
#魔法函数
def __getitem__(self, item):
return self.student_list[item]
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
print(len(student))
运行结果:
Traceback (most recent call last):
File "F:/myfile/python/code/python3进阶/chapter06/getattr.py", line 44, in <module>
print(len(student))
TypeError: object of type 'Student' has no len()
提示对象Student没有len()的方法。那我们来添加__len__的魔法函数看下
class Student:
def __init__(self,student_list):
self.student_list = student_list
#魔法函数
def __getitem__(self, item):
return self.student_list[item]
#让当前的类变成一个序列类型
def __len__(self):
return len(self.student_list)
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
print(len(student))
运行结果:
3
添加了__len__的魔法函数后就可以使用len获取实例对象里面列表的长度了,让当前的类变成一个序列类型
案例3__str__ 魔法函数
class Student:
def __init__(self,student_list):
self.student_list = student_list
def __getitem__(self, item):
return self.student_list[item]
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
print(student)
输出结果:
<__main__.Student object at 0x0000015D3F49A940>
比如上面打印出来的对象地址,我们想要打印的是实例化对象里面的值,输出"marry",“clain”,“lili”,这个时候就需要__str__魔法函数来格式化输出了
class Student:
def __init__(self,student_list):
self.student_list = student_list
def __getitem__(self, item):
return self.student_list[item]
#格式化输出
def __str__(self):
return ','.join(self.student_list)
if __name__ == '__main__':
student = Student(["marry","clain","lili"])
#当使用print进行实例化对象打印的时候,自动调用__str__方法
print(student)
在看输出结果:
marry,clain,lili
案例4__getattr__和__getattribute__ 魔法函数
from datetime import date
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
if __name__ == '__main__':
user = User("黛玉",date(year=1982,month=2,day=21))
print(user.age)
如果是上面的代码,调用了不存在的属性age,会报错
输出结果如下:
Traceback (most recent call last):
File "F:/myfile/python/code/python3进阶/chapter06/getattr.py", line 14, in <module>
print(user.age)
AttributeError: 'User' object has no attribute 'age'
当我们加上__getattr__魔法函数的时候,就不会报错了。
from datetime import date
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
def __getattr__(self, item):
return "no shuch attribute"
if __name__ == '__main__':
user = User("黛玉",date(year=1982,month=2,day=21))
print(user.age)
输出结果如下:
no shuch attribute
Process finished with exit code 0
当调用到对象的属性值,并且这个属性值不存在的时候,就会自动调用__getattr__这个魔法函数,在这个魔法函数里面我们可以实现不存在的属性值的情况
在来看下__getattribute__ 魔法函数
from datetime import date
class User:
def __init__(self,name,birthday):
self.name = name
self.birthday = birthday
def __getattr__(self, item):
return "no shuch attribute"
def __getattribute__(self, item):
return "欢迎进入getattribute"
if __name__ == '__main__':
user = User("黛玉",date(year=1982,month=2,day=21))
print(user.test)
print(user.name)
输出结果:
欢迎进入getattribute
欢迎进入getattribute
Process finished with exit code 0
总结:
_getattr 是在查找不到属性的时候调用
getattribute 是获取属性的入口,不管调用的是什么属性都会进入到这个魔法函数,这个魔法函数不要轻易重写
案例5__enter__ 和__exit__魔法函数
上下文管理协议
在一个类中只要实现了__enter__ 和__exit__这两个魔法函数,就可以使用with
在with 创建类实例的时候会自动调用__enter__魔法函数,在调用实例方法的时候会自动调用__exit__
class Sample:
def __enter__(self):
#可以实现获取资源的方法
print("enter")
return self
def __exit__(self, exc_type, exc_val, exc_tb):
#可以写释放资源的方法
print("exit")
def do_something(self):
print("do something")
with Sample() as sample:
sample.do_something()
输出结果:
enter
do something
exit
with 语句还可以通过contextlib来实现相同的效果文章来源:https://www.toymoban.com/news/detail-508902.html
import contextlib
@contextlib.contextmanager
def file_open(file_name):
print("file open")
yield {}
print("file end")
with file_open("boy.txt") as f:
print("file processing")
输出结果:文章来源地址https://www.toymoban.com/news/detail-508902.html
file open
file processing
file end
到了这里,关于python 魔法函数学习的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!