python中类class的魔法方法(类class python)
off999 2025-05-02 12:51 24 浏览 0 评论
开始介绍之前,我们先看下之前文章我们介绍过的内置类merryview的一些方法,如下图所示: 有很多双下划线开始和结束的method,这么多method是做啥子用的呢?
其实这些方法就是我们常说的魔法方法,也是python中的特殊方法。它们以双下划线 __ 开始和结束,这些方法为 Python 类提供了丰富的功能。
以下开始介绍下常见的魔法方法:
1 构造方法
构造方法有__new__ __init__ __del__
__new__:如果设置了该方法,当我们定义类的实例时,该方法会被第一个调用,而不是先调用__init__方法。该方法需要返回一个类的实例。
__init__: 初始化类的实例属性,并可在该方法中定义其他一些属性或者调用其他函数等作为初始化的功能。
__del__: 当类实例对象销毁时会自动调用该方法。
举例:定义一个类,并做类的实例化
class Car(object):
def __init__(self,brand,color,cost_performance):
print('__init__被调用')
self.brand = brand
self.color = color
self.cost_performance = cost_performance
def __new__(cls, *args, **kwargs):
print('__new__被调用')
def __del__(self):
print('__del__被调用')实例化类:
car_ins = Car('BYD','black','high')
print(car_ins.brand)当执行时,发现报错如下:只有__new__方法被调用了,而没有调用__init__,所以在打印实例属性时报错。
原因是__new__方法中没有返回对象实例。
我们在__new__方法中添加如下一行代码:super().__new__(cls)
def __new__(cls, *args, **kwargs):
print('__new__被调用')
return super().__new__(cls)再次实例化类的时候
car_ins = Car('BYD','black','high')
print(car_ins.brand)打印结果如下:
__new__被调用
__init__被调用
BYD
__del__被调用解释:增加的这一行super().__new__(cls)作用就是调用基类object创建一个实例并返回,有了实例然后再调用__init__ 方法做初始化。当程序执行完成后,实例对象的内存会被释放,然后自动调用__del__方法。
2 类的表示方法
类的表示方法主要有__repr__ __str__
- __str__:当使用print函数打印对象实例或者str函数转换对象实例时,会调用该方法返回的字符串,如果没有该方法会继续找__repr__方法中的字符串信息
- __repr__:当使用repr函数打印对象实例时,会调用该方法返回的字符串,如果没有该方法会继续找__str_方法中的字符串信息
举例:
class Car(object):
def __init__(self,brand,color,cost_performance):
print('__init__被调用')
self.brand = brand
self.color = color
self.cost_performance = cost_performance
def __str__(self):
print('__str__被调用')
return '我是Car类'
def __repr__(self):
print('__repr__被调用')
return '我是Car类'类实例化后,打印下类实例:
car_ins = Car('BYD','black','high')
print(car_ins)
print(str(car_ins))
print(repr(car_ins))结果:
__str__被调用
我是Car类
__str__被调用
我是Car类
__repr__被调用
我是Car类3 上下文管理器方法
通过定义一个类,并实现__enter__()和__exit__()方法,那么这个类就可以被称为上下文管理器,也就可以使用with as的语句。
__enter__()方法:返回一个值,可以将它赋值给with...as后面的对象。
__exit__()方法: with...as 语句退出或者发送异常时会执行这个方法。
比如之前我们的文章讲到open函数我们经常会用到上下文管理器:
with open('test.txt','r') as fd:
content = fd.readlines ()4 可迭代对象和迭代器方法
方法有 __iter__ __next__
- 可迭代对象:指python中可以用来迭代(支持for循环)的对象,比如常见的列表/元组/字典/字符串等,这些对象中都会定义__iter__魔法方法。
- 迭代器:指可以帮助我们迭代其他对象的一种对象。这类对象会定义__next__魔法方法,可通过next()函数获取迭代的结果。
可迭代对象不一定是迭代器,但迭代器肯定是可迭代对象。因为迭代器要求必须同时实现__iter__方法和__next__方法, 而一旦实现了__iter__方法就必然是一个可迭代对象。但是反过来则不成立,可迭代对象可以不是迭代器。
1)判断对象是可迭代对象和迭代器
在python模块中先导入Iterable和Iterator。
from typing import Iterable,Iterator
或者
from collections.abc import Iterable,Iterator通过isinstance(Object, Iterable)可判断一个对象是否是可迭代对象
通过isinstance(Object, Iterator)可判断一个对象是否是迭代器
2)常见的列表等是可迭代对象,但不是迭代器。
#定义一个列表
listA = [1,4,3,2]
print(f'列表是否是迭代对象 :{isinstance(listA,Iterable)}')
print(f'列表是否是迭代器 {isinstance(listA,Iterator)}')
#结果:
列表是否是迭代对象 :True
列表是否是迭代器 Falsepython安装好后有个自带的模块builtins.py,找到定义的list类,会发现该类中定义了__iter__方法,没有定义__next__方法。
class list(object):
"""
Built-in mutable sequence.
If no argument is given, the constructor creates a new empty list.
The argument must be an iterable if specified.
"""
def append(self, *args, **kwargs): # real signature unknown
""" Append object to the end
.....
def __iter__(self, *args, **kwargs): # real signature unknown
""" Implement iter(self). """
pass使用next()执行列表会报错列表不是一个迭代器。
next(listA)
#会报错如下
Traceback (most recent call last):
File "test.py", line 9, in <module>
next(listA)
TypeError: 'list' object is not an iterator3)使用iter()将可迭代对象转换为迭代器
还是以上面的列表举例,使用iter()将列表转换为迭代器。
list_iter = iter(listA)
print(f'列表使用iter()后是否是迭代对象 :{isinstance(list_iter,Iterable)}')
print(f'列表使用iter()是否是迭代器 {isinstance(list_iter,Iterator)}')
#打印结果
列表使用iter()后是否是迭代对象 :True
列表使用iter()是否是迭代器 True5 容器方法
容器方法主要有__len__ __getitem__ __setitem__ __delitem__ __contains__ __reversed__
- __len__(self ): 获取容器中元素的数量,配合len() 函数使用。
- __getitem__(self, index): 获取容器中的元素值,index表示容器中的索引。
- __setitem__(self, index, value): 设置容器中的元素值,index表示容器中的索引,value表示要设置的值。
- __delitem__(self, index): 删除容器中的元素,index表示容器中的索引。
- __contains__(self, item): 判断容器中是否包含某个元素,使用in 判断。
- __reversed__(self): 当使用reversed() 内建函数会调用该方法,定义为返回一个反转之后的序列。
举例:自定义一个列表对象,并初始化一个传入的列表
class MyList(object):
def __init__(self,newlist):
self.newlist = newlist
def __len__(self):
print('使用了__len__')
return len(self.newlist)
def __getitem__(self,index):
print('使用了__getitem__')
return self.newlist[index]
def __setitem__(self, index, value):
print('使用了__setitem__')
self.newlist[index] = value
def __delitem__(self, index):
print('使用了__delitem__')
del self.newlist[index]
def __contains__(self, item):
print('使用了__contains__')
return item in self.newlist
def __reversed__(self):
print('使用了__reversed__')
return reversed(self.newlist)对自定义列表对象进行增删改查时,会用到上述魔法方法:
先初始化实例:
mylist1 = MyList([1,2,3,4,5])1)获取元素个数:
print(f'初始元素个数:{len(mylist1)}')结果:
使用了__len__
初始元素个数:52)获取元素值
print(f'index为1的值:{mylist1[1]}')结果:
使用了__getitem__
index为1的值:23)设置元素值
mylist1[0] = 100
print(f'index为0的值:{mylist1[0]}')结果:
使用了__setitem__
使用了__getitem__
index为0的值:1004)删除元素的值
del mylist1[-1]
print(f'删除最后一个元素后列表为:{list(mylist1)}')结果:
使用了__delitem__
使用了__len__
使用了__getitem__
使用了__getitem__
使用了__getitem__
使用了__getitem__
使用了__getitem__
删除最后一个元素后列表为:[100, 2, 3, 4]5)判断是否包含某个元素
print(f'判断数字2是否在列表内:{2 in mylist1}')结果:
使用了__contains__
判断数字2是否在列表内:True6)反转序列
print(list(reversed(mylist1)))结果:
使用了__reversed__
[4, 3, 2, 100]6 比较方法
比较方法主要有__eq__ __lt__ __le__ __gt__ __ge__ __ne__
- __eq__(self, other):定义等于操作符(==)的行为。
- __ne__(self, other):定义不等于操作符(!=)的行为。
- __lt__(self, other):定义小于操作符(<)的行为。
- __gt__(self, other):定义大于操作符(>)的行为。
- __le__(self, other):定义小于等于操作符(<=)的行为。
- __ge__(self, other):定义大于等于操作符(>=)的行为。
举例:定义一个类,初始化时随机生成一个整数。
import random
class rnum(object):
def __init__(self,num):
self.num = random.randint(0,num)
def __eq__(self,other:int):
print('使用了__eq__')
return self.num == other
def __le__(self,other:int):
print('使用了__getitem__')
return self.num <= other
def __ge__(self, other:int):
print('使用了__ge__')
return self.num >= other
def __lt__(self, other:int):
print('使用了__lt__')
return self.num < other
def __gt__(self, other:int):
print('使用了__gt__')
return self.num > other
def __ne__(self,other:int):
print('使用了__ne__')
return self.num != other初始化类,传入数字10,并将对象做比较运算。
newnum = rnum(10)
print(f'newnum.num = {newnum.num}')
#比较对象值的数字7的大小
print(f'判断== : {newnum == 7}')
print(f'判断>= : {newnum >= 7}')
print(f'判断>= : {newnum >= 7}')
print(f'判断< : {newnum < 7}')
print(f'判断> : {newnum > 7}')
print(f'判断!= : {newnum != 7}')#结果:
newnum.num = 1
使用了__eq__
判断== : False
使用了__ge__
判断>= : False
使用了__ge__
判断>= : False
使用了__lt__
判断< : True
使用了__gt__
判断> : False
使用了__ne__
判断!= : True7 算术方法
常用到的算术方法如下:
__add__(self, other):实现加法+操作。
__sub__(self, other):实现减法-操作。
__mul__(self, other):实现乘法*操作。
__floordiv__(self, other):实现使用//操作符的整数除法。
__div__(self, other):实现使用/操作符的除法。
__mod__(self, other):实现%取余操作。
__divmod__(self, other):实现 divmod 内建函数。__pow__:实现冥运算**操作
__lshift__(self, other):实现左移位运算符<<。
__rshift__(self, other):实现右移位运算符>>。
__and__(self, other):实现按位与运算符&。
__or__(self, other):实现按位或运算符|。
__xor__(self, other):实现按位异或运算符^。
举例:定义一个类,初始化时随机生成一个整数。
import random
class rnum(object):
def __init__(self,num):
self.num = random.randint(0,num)
def __add__(self,other:int):
print('使用了__add__')
return self.num + other
def __sub__(self,other:int):
print('使用了__sub__')
return self.num - other
def __mul__(self, other:int):
print('使用了__mul__')
return self.num * other
def __floordiv__(self, other:int):
print('使用了__floordiv__')
return self.num // other
def __mod__(self,other:int):
print('使用了__mod__')
return self.num % other
def __divmod__(self,other:int):
print('使用了__divmod__')
return divmod(self.num,other)
def __pow__(self,other:int):
print('使用了__pow__')
return self.num ** other
def __lshift__(self,other:int):
print('使用了__lshift__')
return self.num << other
def __rshift__(self,other:int):
print('使用了__rshift__')
return self.num >> other
def __and__(self,other:int):
print('使用了__and__')
return self.num & other
def __or__(self,other:int):
print('使用了__or__')
return self.num | other
def __xor__(self,other:int):
print('使用了__xor__')
return self.num ^ other初始化类,并计算如下:
1)按数值计算
newnum = rnum(100)
print(f'newnum.num = {newnum.num}')
print(f'加法: {newnum + 3}')
print(f'减法 : {newnum - 3}')
print(f'乘法 : {newnum * 3}')
print(f'//除法 : {newnum // 3}')
print(f'计算余数 : {newnum % 3}')
print(f'计算商和余数 : {divmod(newnum,3)}')
print(f'计算冥次 : {newnum ** 3}')#结果
newnum.num = 41
使用了__add__
加法: 44
使用了__sub__
减法 : 38
使用了__mul__
乘法 : 123
使用了__floordiv__
//除法 : 13
使用了__mod__
计算余数 : 2
使用了__divmod__
计算商和余数 : (13, 2)
使用了__pow__
计算冥次 : 689212)按位进行计算:指转换为2进制后的一些计算
print(f'计算左移<< : {newnum << 3}')
print(f'计算右移>> : {newnum >> 3}')
print(f'计算位与& : {newnum & 3}')
print(f'计算位或| : {newnum | 3}')
print(f'计算位异或^ : {newnum ^ 3}')#结果
使用了__lshift__
计算左移<< : 328
使用了__rshift__
计算右移>> : 5
使用了__and__
计算位与& : 1
使用了__or__
计算位或| : 43
使用了__xor__
计算位异或^ : 42解释按位计算的示例:
print(f'数字41的2进制数:{bin(41)}')
print(f'2进制转为10进制数:{int("0b101001",base=2)}')
#0b101001 整体往左移3位变成0b101001000
print(f'2进制转为10进制数:{int("0b101001000",base=2)}')
#0b101001 整体往右移3位变成0b101
print(f'2进制转为10进制数:{int("0b101",base=2)}')
#0b101001 与数字3(0b11) 做&的运算 得到0b000001
print(f'2进制转为10进制数:{int("0b000001",base=2)}')
#0b101001 与数字3(0b11) 做|的运算 得到0b101011
print(f'2进制转为10进制数:{int("0b101011",base=2)}')
#0b101001 与数字3(0b000011) 做^的运算 得到0b101010
print(f'2进制转为10进制数:{int("0b101010",base=2)}')结果:跟上面按位运算的结果一致
数字41的2进制数::0b101001
2进制转为10进制数::41
2进制转为10进制数::328
2进制转为10进制数::5
2进制转为10进制数::1
2进制转为10进制数::43
2进制转为10进制数::42补充知识:
- 按位左移:将一个数的各二进制位全部左移若干位,右边多出的位将用0填充。
- 按位右移:将一个数的各二进制位全部右移若干位,左边多出的位将用0填充。
- 按位与:只有当两个对应位都为1时,结果才为1,否则结果为0
- 按位或:只要有一个对应位为1时,结果就为1,都为0时结果为0
- 按位异或:相同为0,不同为1:如果两个比较的位相同,则结果为0;如果不同,则结果为1。
8 属性方法
关于属性相关的有以下方法:
__dir__(self):定义对类的实例调用 dir() 时的行为,返回一个属性列表。
__getattr__(self,name):当用户试图访问一个不存在的属性时,会调用该方法。
__setattr__(self,name,value):自定义某个属性的赋值时调用该方法。
__delattr__(self,name):删除某个属性时调用该方法。
举例:定义一个类以及上面的方法
class Car(object):
def __init__(self,brand,color,cost_performance):
print('__init__被调用')
self.brand = brand
self.color = color
self.cost_performance = cost_performance
def __dir__(self):
print('__dir__被调用')
return ['brand','color','cost_performance']
def __getattr__(self, name):
print('__getattr__被调用')
return self.__dict__.get(name)
def __setattr__(self,name,value):
print('__setattr__被调用')
self.__dict__[name] = value
def __delattr__(self,name):
print('__delattr__被调用')
del self.__dict__[name]类实例化
car_ins = Car('BYD','black','high')1)返回实例的属性列表
print(dir(car_ins))结果:
__dir__被调用
['brand', 'color', 'cost_performance']2)返回实例的属性字典
print(car_ins.__dict__)结果:
{'brand': 'BYD', 'color': 'black', 'cost_performance': 'high'}3)获取某个属性
print(car_ins.other)结果:因为没有该属性,所以返回为None
__getattr__被调用
None4)设置属性
car_ins.other = 'xxx'
print(car_ins.__dict__)结果:
__setattr__被调用
{'brand': 'BYD', 'color': 'black', 'cost_performance': 'high', 'other': 'xxx'}5)删除属性
del car_ins.other
print(car_ins.__dict__)结果:
__delattr__被调用
{'brand': 'BYD', 'color': 'black', 'cost_performance': 'high'}共勉: 东汉·班固《汉书·枚乘传》:“泰山之管穿石,单极之绠断干。水非石之钻,索非木之锯,渐靡使之然也。”
-----指水滴不断地滴,可以滴穿石头;
-----比喻坚持不懈,集细微的力量也能成就难能的功劳。
----感谢读者的阅读和学习和关注,谢谢大家。
相关推荐
- xp3用什么模拟器打开(xp3用什么模拟器打开好)
-
可以按照以下的步骤排查解决:首先,游戏必须要使kirikiri引擎,这点可以从文件中是否含有部分xp3后缀的文件来判断然后用模拟器打开date.xp3就行了,部分汉化游戏是直接打开exe程序如果遇到d...
- 固态硬盘用mbr还是guid(固态硬盘guid好还是mbr好)
-
如果电脑原装系统是win8或者以上的,那么硬盘分区表格式为GUID(GPT)格式的;如果是win7以下的,那么一般就是MBR的。主引导记录(MBR)是计算机开机后访问硬盘时所必须要读取的首个扇区,由分...
- 为什么fps大神都是400dpi(fps为什么高)
-
400DPI,在游戏里调节不同英雄的鼠标灵敏度,可以保证最小范围微调改动鼠标移动速度。因为DPI和灵敏度是乘积关系。举个例子:如果你玩麦克雷时鼠标DPI是3200,游戏内灵敏度是1。但你切换到源氏和闪...
- 系统集成项目管理工程师难考吗
-
系统集成项目管理工程师考试的普遍通过率是在10%左右,但是并不表示考试真的有那么难。因为考试本身没有报考条件的限制,且考试报名费用很低,很多人都不重视考试。所以通过率普遍偏低,只要你认真备考,有一...
- 360影视大全下载2025免费版(下载360影视大全最新版下载安装到手机版)
-
你好朋友360影视大全里的很多视频都是免费的,建议安装最新的360影视大全就可以了打开360视频,搜索自己需要的视频,点击360播放器右下角的下载箭头,即可将视频进行下载,下载完毕之后视频会保存在36...
- 360安全卫士手机版下载(360安全卫士官方免费下载手机版5.5.0)
-
相当靠谱360手机卫士是一款由奇虎网推出的功能强、效果好、受用户欢迎的上网安全软件。360安全卫士拥有查杀木马、清理插件、修复漏洞、电脑体检、保护隐私等多种功能,并独创了“木马防火墙”“360密盘”等...
- deepin和统信uos(统信和deepin的区别)
-
差不多。1Deepin原名LinuxDeepin、deepinos、深度操作系统,于2014年4月改名Deepin。deepin团队基于Qt/C++(用于前端)和Go(用于后端)开发了的全新深度桌...
- 三星驱动(三星驱动板)
-
驱动是必须装的,但不需要单独安装驱动。 1、电脑的所有硬件,必然要装驱动,键盘、鼠标什么的,都是有驱动的。驱动是软件和硬件结合的桥梁。但多数普通常见的硬件,驱动是widnows系统自带的,不需要用户...
- u盘启动杀毒软件(u盘杀毒系统)
-
有,但是主要是专杀工具,全面的综合杀毒软件基本上没有,因为没什么用。 1、放在U盘里的杀毒软件,就是不安装,也不监控,只杀毒的软件。 2、目前的杀毒软件的工作机制,主要是监控,监控电脑不感染病...
- 联想维修站点查询官网(联想 维修 服务网点)
-
您可以在联想的官方网站上查询到附近的授权维修服务点,或者拨打联想的客服电话寻求帮助。在维修服务点,您可以享受到专业的维修服务,包括硬件故障、软件问题、系统优化等方面的维护和维修。维修人员将会根据您的电...
- 电脑不识别移动硬盘(移动硬盘灯亮但不读取)
-
电脑不能识别移动硬盘可能是由于以下原因造成的:1.电脑和硬盘之间的连接首先,可以确保移动硬盘正确连接到电脑上,检查USB接口是否松动或损坏,可以尝试更换USB线或者尝试连接到其他USB接口看是否能够...
- 键盘的win键在哪里(电脑键盘的win键在哪里)
-
win键就是电脑键盘上显示WINDOWS标志的按键。位于CTRL键与ALT键两个键之间,win键的具体位置一般电脑键盘上有左右两个。Windows键是一种特殊的键,通常位于键盘的左下角。它的图案是一个...
- ghost全盘备份步骤图(用ghost怎么进行全盘备份)
-
可以用手动备份到指定分区。一、用一键Ghost还原中的“中文向导”备份开始-程序-一键Ghost-选出“中文向导”,Ghost中文向导-1、备份文件默认是“第1硬盘第1分区”,如果不是,将鼠标指针移...
欢迎 你 发表评论:
- 一周热门
-
-
抖音上好看的小姐姐,Python给你都下载了
-
全网最简单易懂!495页Python漫画教程,高清PDF版免费下载
-
Python 3.14 的 UUIDv6/v7/v8 上新,别再用 uuid4 () 啦!
-
飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx
-
python入门到脱坑 输入与输出—str()函数
-
宝塔面板如何添加免费waf防火墙?(宝塔面板开启https)
-
Python三目运算基础与进阶_python三目运算符判断三个变量
-
(新版)Python 分布式爬虫与 JS 逆向进阶实战吾爱分享
-
失业程序员复习python笔记——条件与循环
-
系统u盘安装(win11系统u盘安装)
-
- 最近发表
- 标签列表
-
- python计时 (73)
- python安装路径 (56)
- python类型转换 (93)
- python进度条 (67)
- python吧 (67)
- python的for循环 (65)
- python格式化字符串 (61)
- python静态方法 (57)
- python列表切片 (59)
- python面向对象编程 (60)
- python 代码加密 (65)
- python串口编程 (77)
- python封装 (57)
- python写入txt (66)
- python读取文件夹下所有文件 (59)
- python操作mysql数据库 (66)
- python获取列表的长度 (64)
- python接口 (63)
- python调用函数 (57)
- python多态 (60)
- python匿名函数 (59)
- python打印九九乘法表 (65)
- python赋值 (62)
- python异常 (69)
- python元祖 (57)
