Python常见的魔术方法和魔术属性(二)

简介: Python常见的魔术方法和魔术属性(二)

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__)

可以查看该类继承的父类,放到元祖中


相关文章
|
5天前
|
存储 数据处理 Python
Python如何显示对象的某个属性的所有值
本文介绍了如何在Python中使用`getattr`和`hasattr`函数来访问和检查对象的属性。通过这些工具,可以轻松遍历对象列表并提取特定属性的所有值,适用于数据处理和分析任务。示例包括获取对象列表中所有书籍的作者和检查动物对象的名称属性。
16 2
|
2月前
|
索引 Python
python-类属性操作
【10月更文挑战第11天】 python类属性操作列举
26 1
|
3月前
|
存储 API 索引
让 Python 的属性查找具有 C 一级的性能
让 Python 的属性查找具有 C 一级的性能
19 0
|
3月前
|
Python
Python中类属性与实例属性的区别
了解这些区别对于编写高效、易维护的Python代码至关重要。正确地使用类属性和实例属性不仅能帮助我们更好地组织代码,还能提高代码运行的效率。
39 0
|
3月前
|
Python
Python类中属性和方法区分3-8
Python类中属性和方法区分3-8
|
18天前
|
人工智能 数据可视化 数据挖掘
探索Python编程:从基础到高级
在这篇文章中,我们将一起深入探索Python编程的世界。无论你是初学者还是有经验的程序员,都可以从中获得新的知识和技能。我们将从Python的基础语法开始,然后逐步过渡到更复杂的主题,如面向对象编程、异常处理和模块使用。最后,我们将通过一些实际的代码示例,来展示如何应用这些知识解决实际问题。让我们一起开启Python编程的旅程吧!
|
17天前
|
存储 数据采集 人工智能
Python编程入门:从零基础到实战应用
本文是一篇面向初学者的Python编程教程,旨在帮助读者从零开始学习Python编程语言。文章首先介绍了Python的基本概念和特点,然后通过一个简单的例子展示了如何编写Python代码。接下来,文章详细介绍了Python的数据类型、变量、运算符、控制结构、函数等基本语法知识。最后,文章通过一个实战项目——制作一个简单的计算器程序,帮助读者巩固所学知识并提高编程技能。
|
5天前
|
Unix Linux 程序员
[oeasy]python053_学编程为什么从hello_world_开始
视频介绍了“Hello World”程序的由来及其在编程中的重要性。从贝尔实验室诞生的Unix系统和C语言说起,讲述了“Hello World”作为经典示例的起源和流传过程。文章还探讨了C语言对其他编程语言的影响,以及它在系统编程中的地位。最后总结了“Hello World”、print、小括号和双引号等编程概念的来源。
98 80
|
24天前
|
存储 索引 Python
Python编程数据结构的深入理解
深入理解 Python 中的数据结构是提高编程能力的重要途径。通过合理选择和使用数据结构,可以提高程序的效率和质量
134 59
|
4天前
|
分布式计算 大数据 数据处理
技术评测:MaxCompute MaxFrame——阿里云自研分布式计算框架的Python编程接口
随着大数据和人工智能技术的发展,数据处理的需求日益增长。阿里云推出的MaxCompute MaxFrame(简称“MaxFrame”)是一个专为Python开发者设计的分布式计算框架,它不仅支持Python编程接口,还能直接利用MaxCompute的云原生大数据计算资源和服务。本文将通过一系列最佳实践测评,探讨MaxFrame在分布式Pandas处理以及大语言模型数据处理场景中的表现,并分析其在实际工作中的应用潜力。
24 2