『无为则无心』Python面向对象|『无为则无心』Python面向对象 — 59、魔法方法
目录
- 1、魔法方法
__new__()
- 2、魔法方法
__init__()
- 3、魔法方法
__del__()
- 4、魔法方法
__str__()
和__repr__()
- 5、魔法方法
__call__()
- 6、魔法方法
__len__()
- 7、魔法方法
__getitem__()
、__setitem__()
、__delitem__()
在Python语言中,有些方法名比较特别,在名称的前后各有两个下划线,这样的方法往往具有特殊的意义,我们统称为魔法方法,也叫特殊方法。需要注意的是,我们在创建自定义方法时要避免这样的格式,防止造成不必要的冲突。
Python的魔法方法有很多,我们主要介绍常用的几个魔法方法。以后需要用到其他的魔法方法,按照介绍的这几个调用方式,自己尝试一下就可以了,很简单的。
1、魔法方法
__new__()
类的实例化时,调用的第一个方法是__new__
方法。官方定义如下,可以看到
__new__
被定义成静态方法,第一个必须传入的参数是cls
,代表需要实例化的类。class Demo():
def __new__(cls, *args, **kwargs):
print('调用__new__方法')def __init__(self):
print('调用__init__方法')# 结果:调用__new__方法
d = Demo()
从结果看到,只调用了
__new__
方法,但奇怪的是并没有调用__init__
方法,这是为什么呢?实际上,
__new__
是负责对当前类进行实例化,并将实例返回,传给__init__
方法。__init__
方法中的self
就是指代__new__
传过来的对象,所以再次强调,__init__
是实例化后调用的第一个方法。只有
__new__
方法返回创建的实例对象,后边的__init__
方法才能执行。class Demo:
def __new__(cls, *args, **kwargs):
print('调用__new__方法')
return object.__new__(cls)def __init__(self):
print('调用__init__方法')# 创建对象
d = Demo()
"""
输出结果:
调用__new__方法
调用__init__方法
"""
总结:
__new__()
方法是一个魔法方法(同时也是一种静态方法),用于创建一个类的实例,返回一个类的实例对象,用于传入初始化方法__init__()
方法中。一般并不需要对其进行声明和重写,若是重写的话,需要注意返回一个有效的类的实例对象,实例通过object
父类调用类的实例化方法,用于返回一个对象实例。若是不返回一个类的实例对象,会导致类的__init__()
方法不会被调用,当然实例(self
为空)也不会被成功创建。2、魔法方法
__init__()
__init__
方法是类创建过程中用的比较多的魔法方法,是类对象创建后调用的初始化方法,紧跟者__new__
方法后调用,主要用于实例变量的初始化操作。__init__
方法可以理解为一个类的实例的构造器,其方法的特点是不会返回任何对象或者值,若返回则会抛出 TypeError
异常。(1)体验
__init__()
思考:洗衣机的宽度高度是与生俱来的属性,可不可以在生产过程中就赋予这些属性呢?
答:理应如此。
__init__()
方法的作用:初始化对象。示例:
"""
目标: 定义init方法设置初始化属性并访问调用
1. 定义类
init方法: width 和 height
添加实例方法:访问实例属性2. 创建对象
3. 验证成果
调用实例方法
"""
# 1.定义类
class Washer():# 定义初始化功能的函数
def __init__(self):
# 添加实例属性
self.width = 500
self.height = 800def print_info(self):
# 类里面调用实例属性
print(f'洗衣机的宽度是{self.width}, 高度是{self.height}')# 2. 创建对象
haier1 = Washer()
# 3. 调用实例方法
haier1.print_info()
注意:(2)带参数的
__init__()
方法,在创建一个对象时默认被调用,不需要手动调用。__init__(self)
中的self参数,不需要开发者传递,Python解释器会自动把当前的对象引用传递过去。
__init__()
思考:一个类可以创建多个对象,如何对不同的对象设置不同的初始化属性呢?
答:传参数。
# 定义类
class Washer():
# 定义带参数的init方法
def __init__(self, width, height):
self.width = width
self.height = height# 定义实例方法
def print_info(self):
# 调用实例属性
print(f'洗衣机的宽度是{self.width}')
print(f'洗衣机的高度是{self.height}')haier1 = Washer(10, 20)
haier1.print_info()# 如果创建对象的时候不传递参数,会报错。
# haier2 = Washer()
haier2 = Washer(100, 200)
haier2.print_info()
图解如下:
文章图片
3、魔法方法
__del__()
当删除对象时,Python解释器也会默认调用__del__()
方法。__del__()
方法属于析构函数。__del__()
方法不会被主动调用,只有当类的实例对象的引用计数为0时,才会被调用,一般不建议重写__del__()
方法。示例
class Washer():
def __init__(self, width, height):
self.width = width
self.height = heightdef __del__(self):
print(f'{self}对象已经被删除')haier1 = Washer(10, 20)# <__main__.Washer object at 0x0000026118223278>对象已经被删除
del haier1
即便不手动删除对象,也能调用到4、魔法方法__del__()
方法,也就上面示例中,不编写最后del haier1
语句,当Python程序执行完成后,也会打印一样的结果,是Python解释器自动调用的。
__str__()
和__repr__()
- Python 定义了
__str__()
和__repr__()
两种方法,__str__()
用于显示给用户,而__repr__()
用于显示给开发人员。
-
__str__
方法默认情况下,它会返回当前对象的类名+object at+内存地址
。
如下:
<__main__.Students object at 0x0000000002443808>
- 有时候想让屏幕打印的结果不是对象的内存地址,而是它的形式的字符串,以便更直观地显示对象内容,可以通过在该对象的类中重写
__str__()
或__repr__()
方法来实现。
- 注意:
__str__()
方法和__repr__()
方法的返回值只能是字符串!
以下三种场景中,会优先调用对象的
__str__()
方法。若没有,就调用__repr__()
方法。若再没有,则显示其内存地址。- 使用
print()
时。 - 使用
%s
和f'{}'
拼接对象时。 - 使用
str(x)
转换对象x时。
- 用
%r
进行字符串拼接时。 - 用
repr(x)
转换对象x时。
__repr__()
方法。若没有,则不再看其是否有__str__()
方法。若再没有,则显示其内存地址。(2)示例
__str__
方法一般放置的是一些解释说明的文字。示例:
class Washer():
def __init__(self, width, height):
self.width = width
self.height = heightdef __str__(self):
# return repr('这是海尔洗衣机的说明书')
return '这是海尔洗衣机的说明书'# __repr__方法在实际工作总一般如下使用
__repr__ = __str__haier1 = Washer(10, 20)
# 结果:这是海尔洗衣机的说明书
print(haier1)
5、魔法方法
__call__()
对象后面加括号,触发执行。提示:
__init__
方法的执行是由创建对象触发的,即:对象 = 类名()
。- 而对于
__call__
方法的执行是由对象后加括号触发的,即:对象()
或者类()()
。
class Person(object):
def __init__(self):
print("__init__方法执行了")def __call__(self, *args, **kwargs):
print("__call__方法中执行了")# 1.对象 = 类名()
p = Person()# 执行__init__# 2.对象() 调用__call__方法
p()# 3.类()() 调用__call__方法
Person()()# 执行__call__
提示:这个方法在工作中的应用自己以后总结,先知道怎么用就好。6、魔法方法
__len__()
__len__()
方法在list
,dict
,set
,tuple
,str
等序列中都存在,而在int
和float
类中是不存在的。print('__len__' in dir(int))# False
print('__len__' in dir(float))# Falseprint('__len__' in dir(str))# True
print('__len__' in dir(list))# True
print('__len__' in dir(tuple))# True
print('__len__' in dir(dict))# True
print('__len__' in dir(set))# True
如果一个类要表现得像一个
list
一样,有需求要获取有多少个元素,就得用 len()
函数。要让
len()
函数工作正常,类中就必须提供一个魔法方法__len__()
方法,它的作用是返回元素的个数。示例:
# 定义一个类,接收同学名的名字
class Students(object):
def __init__(self, *args):
self.names = argsdef __len__(self):
return len(self.names)stu = Students('唐僧', '孙悟空', '猪八戒', '沙和尚')
print(len(stu))# 4
print(stu.__len__())# 4
提示:只要在类中正确实现了7、魔法方法__len__()
方法,就可以用len()
函数。
__getitem__()
、__setitem__()
、__delitem__()
在Python中,如果我们想实现创建类似于序列和映射的类,可以通过重写魔法方法__getitem__()
方法、__setitem__()
方法、__delitem__()
方法去模拟。示例:
class MyDict(object):def __init__(self):
self.item = {}# 获取成员
def __getitem__(self, key):
return self.item.get(key)# 添加成员
def __setitem__(self, key, value):
self.item[key] = value# 删除成员
def __delitem__(self, key):
del self.item[key]# 获取人员数量
def __len__(self):
return len(self.item)if __name__ == "__main__":
# 创建序列对象
myDict = MyDict()# 添加元素
myDict.__setitem__('师傅', '唐憎')
myDict.__setitem__('大师兄', '孙悟空')
# 查看刚添加的成员
print(myDict.__getitem__('大师兄'))
print(f"现在成员{len(myDict)}人", )# 2# 修改成员
myDict.__setitem__('大师兄', '齐天大圣')
print(myDict.__getitem__('大师兄'))
print(f"现在成员{len(myDict)}人", )# 2# 删除元素
myDict.__delitem__('师傅')
print(f"现在成员{len(myDict)}人", )# 1"""
输出结果:
孙悟空
现在成员2人
齐天大圣
现在成员2人
现在成员1人
"""
【『无为则无心』Python面向对象|『无为则无心』Python面向对象 — 59、魔法方法】参考:
- https://www.cnblogs.com/woniuxy/p/11507648.html
- https://blog.csdn.net/chf1142152101/java/article/details/78715296
- https://www.cnblogs.com/oddgod/p/10992366.html
推荐阅读
- 轩辕展览-工业园区展厅设计的原则
- 实践GoF的23种设计模式(SOLID原则(上))
- 『无为则无心』Python面向对象|『无为则无心』Python面向对象 — 58、类方法和静态方法
- 故障分析 | MySQL 异地从库复制延迟案例一则
- python如何攻击网站_GitHub - wuhuanyan/buy_pig_plan_python: 用Python写的『电话攻击,电话轰炸,电话炸弹』...
- 『无为则无心』Python面向对象|『无为则无心』Python面向对象 — 57、类属性和实例属性
- 『德不孤』Pytest框架|『德不孤』Pytest框架 — 8、Pytest断言
- 『德不孤』Pytest框架|『德不孤』Pytest框架 — 7、Pytest预期失败
- 数学知识|离散数学易错知识点
- 系统学习 TypeScript(二)——开发流程和语法规则