python类中是有魔法的,这些魔法也被叫做魔法方法。使用这些魔法方法好像真的在施展魔法一样(哈哈 夸张了!),在类中定义好魔法方法后,我们就可以在调用类时使用这些魔法方法。他们能完成的任务非常多,也正是因为魔法方法的存在才使得类的使用方式和功能变得多种多样。
网上已经有很多很全面的魔法方法的整理了,因此我今天就简单介绍一下python中我们常用的魔法方法好啦。更重要的是希望大家理解魔法方法的功能和使用方式,毕竟学习都是触类旁通的嘛!
附上类使用专栏的其它文章的链接:
- python 类的使用(1) 之类使用的基本框架
- python 类的使用(2) 之类变量
- python 类的使用(3)之类中常用的三个装饰器@classmethod、@staticmethod、@property
- python 类的使用(4)之类常用的魔法方法
- python 类的使用(5)之类装饰器(类的装饰器和类作为装饰器)
- python 类的使用(6)之类的继承
- python 类的使用(7)之类的私有属性和方法 (类中以单下划线或双下划线开头的变量名或函数名)
魔法方法是啥
魔法方法在类中的存在形式就是含有被双下划线包裹的函数,例如我们常用的__init__和__str__。这些魔法方法通常不会被我们直接按照其函数名调用,而是在我们在一种更人性化的使用方式下被调用。
看个简单的例子就懂啦:
看出来这里的区别了吧,定义一个__str__方法的话,我们对这个类实例本身打印出的结果就不一样啦。
实际上魔法方法也就是我们在类的框架下,可以设置一些特定的魔法方法,这些魔法方法我们可以自定义其执行方式,这样我们可以以更人性化的方式来完成常用的某些操作啦。当然这些魔法方法需要python类魔法方法库中存在才行哦。
常用的几个魔法方法
__init __
首先就是最常见的__init__啦,虽说它不是实例化对象时第一个被调用的魔法方法(__new__才是),但它也是用来帮我们初始化类的。init也被称为构造器,它可以方便我们对类的属性进行定义,其规定了类实例的一些参数(即创建类时传入的参数)。
例:
class Animal:
def __init__(self, name, height):
self.name = name
self.height = height
def __str__(self):
return self.name, self.height
A = Animal('pig')
print(A)
正如这个例子所展示,使用init初始化这些被传入的参数,将类实例self与这些属性绑定,这样只要在其它函数中传入self,就能够访问到self所拥有的所有属性和方法了。
__call __
使用__call__能够让我们将类实例对象当做函数使用,比如上例中的A是一个类实例,只要加上一个括号,相当于将类实例当做了函数,这时运行的内容就是__call__中定义的内容。
例:
class Animal:
def __init__(self, name, height):
self.name = name
self.height = height
def __call__(self):
print(f"{self.name}'s height is {self.height} meters tall")
A = Animal('pig', '0.6')
A()
# 执行结果为: pig's height is 0.6 meters tall
__len__
当对类实例对象使用len(‘实例对象’)的结果。
例:
class Animal:
def __init__(self, name, height):
self.name = name
self.height = height
def __len__(self):
return len(self.name)
A = Animal('pig', '0.6')
print(len(A))
# 执行结果为3
除了上面介绍的这些魔法方法外,还有很多的魔法方法,比如常用的__del__,还有各种比较运算符(大 于小于等于等),还有类型转换(如__int__),还有算数运算符(加减乘除之类的),除了这些之外还有一些其它的,大家在使用时可以再多去查查。也可以去一个网友的博客上看哈。链接在这里:Python 魔法方法详解
上下文管理器
python中使用类魔法方法的一个典型例子是上下文管理器,即只需要在类中加入__enter__和__exit__那么就能够使用with somthing as st这样的用法,我们常用的with open就是这样呀!
出现with语句时enter首先派上用场,其将with的返回值赋值给as后的变量名,所以其实with open(‘1.txt’) as f 和 f = open(‘1.txt’)的意思是一样的,都是将open的返回值返回给f(这里如果我没搞错的话,open应该是一个类吧!)。enter在赋值后再执行enter函数中的其它步骤,这些步骤结束后才开始执行with后的代码,执行完所有with下的代码后(即要退出上下文管理器时)__exit__就上场了。
__exit__的功能是退出上下文管理器,并且其还能够检测with后的代码程序异常,其携带的四个参数的后三个exc_type, exc_val, exc_tb分别代表着异常类型,异常值和追溯信息(无报错则为None)。报错后还可以通过return True来屏蔽报错,完成整个程序的运行。
看下例子就理解啦
class Animal():
def __init__(self, name, height):
self.name = name
self.height = height
def print_it(self):
print(f'the animal is {self.name}')
def __enter__(self):
print('开始执行咯')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type, exc_val, exc_tb)
print('执行结束咯')
with Animal('pig', '0.6') as a:
a.print_it()
# 执行结果:
# 开始执行咯
# the animal is pig
# None None None
# 执行结束咯
这里我如果修改一下代码,让代码出错:
class Animal():
def __init__(self, name, height):
self.name = name
self.height = height
def print_it(self):
print(f'the animal is {name}') # 这里设置了错误,没有name变量
def __enter__(self):
print('开始执行咯')
return self
def __exit__(self, exc_type, exc_val, exc_tb):
print(exc_type, exc_val, exc_tb)
print('执行结束咯')
return True # 加上return True屏蔽错误
with Animal('pig', '0.6') as a:
a.print_it()
# 执行结果:
# 开始执行咯
# the animal is pig
# None None None
# 执行结束咯
结果:
可以看到虽说能看到报错信息,但是正常执行结束了。
上下文管理器不止可以在类中定义,还有一种简单的方式就是在函数中加上一个@contextlib.contextmanager装饰器,加上这个装饰器后按照这个装饰器规定的方法去写代码,就能够使用上下文管理器啦。这里我就不赘述了,大家有兴趣的可以参考 这篇博客。
叮
本文内容相对比较简单,但是魔法方法的使用对类来说是非常非常之重要的,大家一定要学习呀!当然本文介绍的内容不多,大家可以多看看网上别的博客再多学习一下,嘿嘿!
参考:Python 魔法方法详解
参考:深入理解 Python 中的上下文管理器
参考:python之(enter__和__exit)