Python的魔法函数
1. 什么是魔法函数
Python的类中有很多内置的魔法函数,他们以__开始和结束,如__init__,__str__等等,它是未来增强类的特性,不需要专门调用,在特定的场合下Python会自己调用,不能自己定义魔法函数
2. 常用的魔法函数
1. 字符串表示1. __str__:在print的情况下,可以返回友好的内容显示,python环境下直接运行返回指针地址
2. __repr__:不管是print或者直接执行,都会返回直接的内容显示
class Label: def __init__(self, value='hello world'): self.value = value label = Label() # 在cmd的python环境下才能输出,在py编辑器无输出 # 但他们都只是指向了一个地址,显然这不是我们想要的结果 lable # <__main__.Label at 0x2128207e448> print(label) # <__main__.Label object at 0x000002128207E448> # __str__:面向用户编程,在print下输出内容 class Label: def __init__(self, value='hello world'): self.value = value def __str__(self): return self.value label = Label() # __str__只能在print的情况下才能输出具体想要的效果 label # <__main__.Label at 0x212827fdcc8> print(label) # hello world # __repr__:面向程序员编程,不管是print还是直接运行的情况下,都能输出内容 class Label: def __init__(self, value='hello world'): self.value = value def __repr__(self): return self.value label = Label() # 输出结果直观 label # hello world print(label) # hello world
2. 集合序列相关
1. __len__: 计算对象容器中元素的个数
class Weekly: def __init__(self,my_list): self.my_list = my_list def __len__(self): return len(self.my_list) weekly = Weekly([1,2,3,4,5]) # 如果没有__len__函数,执行len方法时报错 print(len(weekly)) # 5
2. __setitem__、__getitem__和__delitem__
class A: def __init__(self): self.dict = {} # --__setitem__--,新建字典 def __setitem__(self, key, value): self.dict[key] = value # --__getitem__--,通过字典key获取value def __getitem__(self, item): return self.dict[item]
# --__delitem__--,删除对应key的记录 def __delitem__(self, key): self.dict[key]
a = A()
a.dict['name'] = 'timi' # 调用了setitem方法
a['age'] = 22 # dict省略,一样的结果
print(a.dict) # {'name': 'miti', 'age': 12}
print(a['name'] # 调用getitem方法 timi
del a['age'] # del函数必须调用__delitem__方法
print(a.__dict__) # {'dict': {'name': 'miti'}}
3. __contains__:查找属性是否在class中
class H: def __init__(self, data): self.data = data # 判断item是否存在class的data中,是返回True,不是返回False def __contains__(self, item): return item in self.data h = H(['a', 'b', 'c', 'd']) print('b' in h) # True print('f' in h) # False
3. 迭代相关
1. __iter__和__next__:迭代器
class Iterator: def __init__(self, value): self.start = 0 self.end = value def __iter__(self): return self def __next__(self): if self.start < self.end: self.start += 1 return self.start else: raise StopIteration iterator = Iterator(5) # 可使用for循环遍历 for i in iterator: print(i, end=' ') # 1 2 3 4 5 # 可以使用next函数遍历 print(next(iterator)) # 1 print(next(iterator)) # 2 print(next(iterator)) # 3 print(next(iterator)) # 4 print(next(iterator)) # 5
4. 实现调用方法
1. __call__: 实现类对象像普通函数那样可调用
class Call: def __init__(self, name): self.name = name def __call__(self, age): print(f'我叫{self.name},今年{age}岁。') call = Call('Tom') # 类实例化对象时传参形式 call(22) # call方法的传参,类似于普通函数调用
5. 上下文管理器(with)
1. __enter__和__exit__: 实现with上下文管理器调用
class Open: def __init__(self, filename): self.filename = filename def __enter__(self): self.f = open(self.filename, 'r') return self.f # 如果不返回,则返回一个None # def __exit__(self, exc_type, exc_val, exc_tb): self.f.close() openTest = Open(r'E:\Python\file.txt') # with开始运行时,会调用__enter__()方法,运行结束后,会调用__exit__()方法 with openTest as f: print(f.read())
6. 元类相关
1. __init__:构造函数,初始化对象,类在生成对象时默认被调用
class Init: def __init__(self,name,age): self.name = name self.age = age def say(self): # 调用init方法 return (f'他叫{self.name},今年{self.age}岁') init = Init('Tom',22) init1 = Init('miki', 30) print(init.say()) # 他叫Tom,今年22岁 print(init1.say()) # 他叫miki,今年30岁
2. __new__:负责类的创建,在__init__之前执行
1.在类实例化之前调用,最先调用并返回类实例,一般不建议重写__new__除非是在str,int或者tuple不可变类型的子类时 2.在__init__之前被创建,它必须要有一个参数cls,表示要返回的实例化类 3.new的返回值是一个对象,也就是init中的self 4.必须要return出new函数才能执行init函数,否则返回None # # __new__ 在new的返回值和self的值时一样的,也就是说new返回的是self class Animal(object): def __init__(self): pass class Capstr(): # 在重写__new__()方法时,需要在参数中加入*args,**kwargs,或者显式地加入对应的参数,才能通过__init__()方法初始化参数 def __new__(cls, *args, **kwargs): # or def __new__(cls, name) print('new_cap') # 构造一个类实例,并传递给__init__方法 instance = super().__new__(cls) print(id(instance)) # 2676307354184 return instance # 如果__new__()方法返回一个其他类的实例的话,那它自身的__init__()方法将不会被调用。而且,new()方法将会初始化一个其他类的对象 # return Animal() def __init__(self, name): self.name = name print('init_cap') print(id(self)) # 2676307354184 # 先调用__new__方法,在调用__init__方法 cap = Capstr('timo') print(id(cap)) # 2676307354184 # 返回其他类时 print(type(cap)) # <class '__main__.Animal'> print(cap) # <__main__.Animal object at 0x10fea3550>
7. 数值相关
1. __abs__:执行abs是自动调用class类中的__abs__方法,返回一个绝对值
class Abs: def __init__(self, x): self.x = x def __abs__(self): return abs(self.x) print(abs(Abs(-33))) # 33
2. __bool__:执行bool函数时调用__bool__方法,返回的是一个布尔值
# 当对象为int类型时,值为0返回False,否则返回True print(bool(0)) # False print(bool(1)) # True # 当对象为str类型是,str类当中没有__bool__方法,默认调用__len__方法,当长度为0时,返回False,否则返回True # 列表,元组,字典,集合亦是如此 print(bool('')) # False print(bool('a')) # True # 当对象是类实例化对象时,默认返回True class A: def __init__(self, x): self.x = x print(bool(A(0))) # True print(bool(A('a'))) # True # 在class类内部重新定义__bool__方法 class B: def __init__(self, x): self.x = x def __bool__(self): if self.x > 5: return True return False print(bool(B(2))) # False print(bool(B(6))) # True # 如果class类中没有定义__bool__函数,则会去调用__len__方法 class C: def __init__(self, value): self.length = value def __len__(self): return self.length print(bool(C('a'))) # True print(bool(C(0))) # False print(bool(C(1))) # True
3. __int__和__float__方法:执行int或float方法的时候会去调用类内部的__int__或__float__方法
class IntAndFloat: def __init__(self, x): self.x = x def __int__(self): return (int(self.x)) def __float__(self): return float(self.x) print(type(int(IntAndFloat('123'))),int(IntAndFloat('123'))) # <class 'int'> 123 print(type(float(IntAndFloat('123'))),float(IntAndFloat('123'))) # <class 'float'> 123.0
4. __hash__:哈希返回值
class Hash: def __init__(self, name): self.name = name # 通过重写__hash__的返回值,返回值只能是整数 def __hash__(self): return 123 # hash方法在执行类实例的时候,会调用class类中的__hash__方法 print(hash(Hash('timi'))) # 123
8. 属性相关
1. __setattr__、__getattr__和__getattebute__
class Attr:
def __init__(self):
pass
def __setattr__(self, key, value):
# self.name = value 不能直接进行赋值,否则进入死循环(递归)
self.__dict__[key] = value
def __getattr__(self, name):
print('访问不存在key时,触发__getattr__方法')
return self.__dict__[name]
# 属性拦截器,当实例对象的属性被访问的时候都会触发__getattribute__方法
def __getattribute__(self, item):
print('key无论存不存在,都会触发__getattrbute__方法')
return super().__getattribute__(item)
attr = Attr()
attr.name = 'momo' # 调用__setattr__方法和__getattribute__方法
print(attr.name) # 调用__getattr__方法和__getattribute__方法
attr.a # 访问不存在key时,触发__getattr__方法和__getattribute__方法
分类:
Python—世界上最好的语言
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY