Python常见的魔术方法和魔术属性(一):https://developer.aliyun.com/article/1495783
6、__call__
魔术方法
触发时机:把对象当作函数调用的时候自动触发 功能: 模拟函数化操作 参数: 参数不固定,至少一个self参数 返回值: 看需求
(1) 基本语法
class MyClass(): def __call__(self): print("__call__魔术方法被触发 ... ") obj = MyClass() obj()
定义了__call__
方法,对象就可以向函数一样调用,直接执行__call__
方法里面的代码
如果没定义__call__
方法,调用对象会报错
(2) 利用__call__
魔术方法做统一调用,把其他方法都放到__call__
方法里面一起调用
如果多个方法需要同时调用,每个都要调一次很麻烦,这时就需要__call__
魔术方法
class Wash(): def __call__(self,something): print("我要洗{}".format(something)) self.step1(something) self.step2() self.step3() return "洗完了" def step1(self,something): print("放水,把{}扔进去".format(something)) def step2(self): print("倒洗衣粉,洗衣液,蓝月亮,金纺,立白 ... ") def step3(self): print("洗一洗,晾干,穿上") obj = Wash() # obj.step1() # obj.step2() # obj.step3() res = obj("袜子") print(res)
传参,对象作为函数被调用参数的个数要和__call__
方法除了self的参数个数相同,如果不同,会报错
此时的something。是方法的形参,不是类的成员属性。不是类的成员属性不能通过对象调用,除非先创建类属性,或者通过构造方法创建类属性
直接属性名调用即可
打印返回值
(3) 模拟整型强转操作
import math class MyInt(): def __call__(self,num): if isinstance(num,bool): if num == False: return 0 else: return 1 elif isinstance(num,int): return num elif isinstance(num,float): # 方法一 # a,b = str(num).split(".") # return eval(a) # 方法二 """ if num >= 0: return math.floor(num) else : return math.ceil(num) """ # 简写 return math.floor(num) if num >= 0 else math.ceil(num) elif isinstance(num,str): if (num[0] == "+" or num[0] == "-") and num[1:].isdecimal(): # 获取当前字符串的正负值 if num[0] == "+": sign = 1 elif num[0] == "-": sign = -1 # 截取符号后面的字符串传递 return self.calc(num[1:],sign) elif num.isdecimal(): return self.calc(num) else: return "这个算不了兄弟~" # 计算最后的数值 def calc(self,num,sign=1): # 去掉前面的"0"字符串 num = num.lstrip("0") # print(num , type(num) , "<==============>") if num == "": return 0 return eval(num) * sign myint = MyInt() res = myint(-5.67) print(res , type(res)) res = myint("-000000000000055555") print(res , type(res)) res = myint("asdfasdfasdfasdf") print(res , type(res)) # print(myint("+0000000000000")) # bool int float 纯数字字符串 # int(3.78) => 3 # print(int(-3.78)) # import math # print(math.floor(0) ) # => 3 # print(math.ceil(0)) """ print( int("00000000000001223") ) # 1223 print( int("-00000000000001223") ) # -1223 print( int("+00000000000001223") ) # 1223 print( int("+0000000000000") ) # 1223 """ # print( int("asdfasdfasdfasdf") ) # 1223 # print( eval("00000000000001223") ) # print( eval("+00000000000001223") ) # print( eval("-00000000000001223") ) # print( eval("-00000000000001223abc") ) 支持字符串是小数的强制转换 #通过__call__模拟整形强转操作 # int 强制把数据变成整型,只支持布尔型,整形,浮点型,纯数字类型的字符串,二进制(忽略) 转换成整形 import math import re class MyInt(object): def __call__(self, num): #布尔型转换 if isinstance(num,bool): if num: return 1 else: return 0 #整形,直接返回 elif isinstance(num,int): return num #浮点型强转 elif isinstance(num,float): return math.floor(num) if num >= 0 else math.ceil(num) #纯数字字符串 elif isinstance(num,str): if num != "" and (num[0] == "+" or num[0] == "-") and re.search(r"^\d+\.\d+$|^\d+$",num[1:]): #获取字符串正负号 if num[0] == "+": sign = 1 elif num[0] == "-": sign = -1 #截取符号后面的字符串传递 return self.cal(num[1:],sign) elif num.isdecimal(): return eval(num) elif re.search(r"^\d+$(\.\d+$)?",num): return self.cal(num) else: return "这个计算不了,兄弟" else: return "这个计算不了,兄弟" def cal(self,num,sign=1): #去掉字符串前面的0 num = num.lstrip("0") if num == '': return 0 else: if isinstance(eval(num),float): # return eval(num) * sign return math.floor(eval(num)) * sign if eval(num) >= 0 else math.ceil(eval(num)) * sign elif isinstance(eval(num),int): return eval(num) * sign myint = MyInt() print(myint(2+3j))
7、__bool__
魔术方法
触发时机:使用bool(对象)的时候自动触发 功能:强转对象 参数:一个self接受当前对象 返回值:必须是布尔类型
类似的还有如下等等(了解):
__complex__(self) 被complex强转对象时调用 __int__(self) 被int强转对象时调用 __float__(self) 被float强转对象时调用
... ...
class MyClass(): def __bool__(self): return True obj = MyClass() print(bool(obj))
类对象默认,不做任何操作。使用bool强转,默认返回True
我们可以控制返回结果,只能是True或False,否则报错
类似的__int__
。必须返回int类型数据等
8、__add__
魔术方法 (与之相关的__radd__
反向加法)
触发时机:使用对象进行运算相加的时候自动触发,对象在+的左边触发add 功能:对象运算 参数:二个对象参数 返回值:运算后的值
类似的还有如下等等(了解):
__sub__(self, other) 定义减法的行为:- __mul__(self, other) 定义乘法的行为: __truediv__(self, other) 定义真除法的行为:/
... ...
class MyClass(): def __init__(self,num): self.num = num # 当对象在 + 号的左侧时,自动触发,触发的时候,把+左边的值当成参数传递给self,+右边的值当成参数传递给other def __add__(self,other): # print(self) # print(other) return self.num * 3 + other # 当对象在 + 号的右侧时,自动触发,触发的时候,把+右边的值当成参数传递给self,+左边的值当成参数传递给other def __radd__(self,other): # print(self) # 对象 # print(other) # 7 return self.num * 5 + other # add的触发方式 a = MyClass(3) res = a + 1 print(res)
对象在+左边,__add__
方法触发,返回的是 self3 + other = 33 + 1 = 10
#radd的触发方式
b = MyClass(5) res = 7 + b print(res)
对象在+的右边,__radd__
被触发,+右边的值传给self,+左边的值传给other。返回的是self 5 +1 = 55+1 = 26
#对象 + 对象
res = a + b
print(res)
a+b 触发的是add魔术方法 self 接受的是a other 接受的是b
return a.num + b => return 9 + b
res = 9 + b 触发的是radd魔术方法 self 接受的是b other 接受的是9
return b.num * 5 + 9 => 5 * 5 + 9 => 34
9、__len__
魔术方法
触发时机:使用len(对象)的时候自动触发 功能:用于检测对象中或者类中某个内容的个数 参数:一个self接受当前对象 返回值:必须返回整型
#len(对象) => 类中的所有自定义成员
class MyClass(): pty1 = 1 pty2 = 2 __pty3 = 3 def func1(): pass def func2(): pass def __func3(): pass def __len__(self): # 以__开头并且以__结尾的成员过滤掉; return len( [ i for i in MyClass.__dict__ if not ( i.startswith("__") and i.endswith("__") ) ] ) obj = MyClass() print(len(obj)) """ 代码原型; print(MyClass.__dict__) lst = [] for i in MyClass.__dict__: print(i , type(i)) if not ( i.startswith("__") and i.endswith("__") ): lst.append(i) print(len(lst)) """ """ { '__module__': '__main__', 'pty1': 1, 'pty2': 2, '_MyClass__pty3': 3, 'func1': <function MyClass.func1 at 0x7f6898431378>, 'func2': <function MyClass.func2 at 0x7f6898431400>, '_MyClass__func3': <function MyClass.__func3 at 0x7f6898431488>, '__len__': <function MyClass.__len__ at 0x7f6898431510>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None } """
魔术属性
与类相关的魔术属性 #__dict__ 获取对象或类的内部成员结构 #__doc__ 获取对象或类的内部文档 #__name__ 获取类名函数名 #__class__ 获取当前对象所属的类 #__bases__ 获取一个类直接继承的所有父类,返回元组
1、 __dict__
获取对象或类的内部成员结构
class Man(): pass class Woman(): pass class Sasuke(Man,Woman): """ 描述: 佐助这个的天生属性,技能 成员属性: __eye skin 成员方法: skylight __moonread """ __eye = "血轮眼->万花筒->轮回眼" skin = "白色" def skylight(self , myfunc): print("使用天照,一团黑色的火焰 ... 恐怖如斯") res = myfunc.__name__ print(res , type(res) ) def __moonread(self): print("使用月读,让敌人拉入到幻术空间,被施法者掌握") obj = Sasuke() dic = Sasuke.__dict__ dic = obj.__dict__ print(dic)
2、 __doc__
获取对象或类的内部文档
print(Sasuke.__doc__) print(obj.__doc__)
类和对象获取的一样,都是三个引号的描述
help查看的更全面
3、 __name__
获取类名函数名
def func343434(): print("佩恩出场时,使用一手地爆天星,技惊四座,点燃所有观众") obj.skylight(func343434)
获取传递的函数的函数名
4、 __class__
获取当前对象所属的类
print(obj.__class__)
5、 __bases__
获取一个类直接继承的所有父类,返回元组
print(Sasuke.__bases__)
可以查看该类继承的父类,放到元祖中