鱼C论坛

 找回密码
 立即注册
查看: 1855|回复: 2

[知识点备忘] 第071讲:类和对象(XIV)

[复制链接]
发表于 2022-8-16 05:22:32 | 显示全部楼层 |阅读模式
购买主题 已有 21 人购买  本主题需向作者支付 5 鱼币 才能浏览
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2022-10-1 10:10:34 | 显示全部楼层
只要定义了__call__()方法,Python便可以像调用函数一样去调用该对象,不仅支持位置参数和关键字参数,还可以用作闭包的简易实现!内置函数repr()与str()运行结果常常相同,但设计初衷不同——str()将参数转换为字符串,给人看;repr()将对象转换为程序可执行的字符串,给程序(机器)看。被repr()转化后的字符串可以被内置函数eval()去引号后执行,其结果往往就是原参数,故eval()可以理解为repr()的反函数。魔法方法__str__()和__repr__()分别对应str()和repr(),二者均返回字符串,且__repr__()可作为__str__()的代偿(反之不成立)。不过,通过__str__()定义的只能应用于对象出现在打印操作的顶层,但__repr__()则不同,其适用场景更多,用起来也更安全!最后,同时定义两个方法可以让对象在不同场景下实现不同的显示效果,既灵活又有趣!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-7 17:36:42 | 显示全部楼层
本帖最后由 Ensoleile 于 2023-1-10 00:30 编辑

__call__()、__str__()和__repr__()
#__call__():在对象中既可以有属性又可以有方法,python可以像调用函数一样去调用一个对象,要求就是需要这个对象的类定义__call__()魔法方法
class C:
    def __call__(self):
        print('hello')

c = C()
c()#hello

class C:
    def __call__(self, *args, **kwargs):
        print(f'位置参数 -> {args}\n关键字参数 -> {kwargs}')

c = C()
c(1, 2, 3, x=250, y=520)
# 位置参数 -> (1, 2, 3)
# 关键字参数 -> {'x': 250, 'y': 520}

#用__call__()函数实现闭包的效果
class Power:
    def __init__(self, exp):
        self.exp = exp
    def __call__(self, base):
        return base ** self.exp

square = Power(2)
cube = Power(3)
print(square(5))#25
print(cube(3))#27

#跟字符串相关的魔法方法:__str__()和__repr__()   P168
#__repr__()对应repr()函数,str()函数将参数转换为字符串对象,是给人看的;repr函数将对象转换为程序可执行的字符串,是给程序看的
#repr()与eval()互被称为反函数,eval()作用为将参数去引号后执行,并且得到结果。repr()函数返回的字符串作为参数传递给eval()函数的话,那么所得到的结果必定是repr()函数的参数

print(repr("print('crazy')"))#"print('crazy')"
print(str("print('crazy')"))#print('crazy')
#repr()返回的带引号,str()返回的不带引号
eval("print('crazy')")#crazy
eval(repr('crazy'))
try:
    eval(str('crazy'))
except NameError as e:
    print(e)#name 'crazy' is not defined
#str('crazy')的返回值为crazy,不带引号,python会将其作为变量名来引用,结果就是找不到的定义fishc的变量
#repr()返回的是带引号的'crazy',eval(repr('crazy'))会执行
eval(repr("print('crazy')"))#不打印
eval(repr(print('crazy')))#crazy
eval(str("print('crazy')"))#crazy
eval(str(print('crazy')))#crazy

#代偿:__str__() -> __repr__(),repr代偿str,反过来不行
class C:
    def __repr__(self):
        return 'i love you'

c = C()
print(repr(c))#i love you
print(str(c))#i love you

#__str__()魔法方法定义的,只能应用于对象出现在打印操作的顶层,即如果把多个对象放到一个列表中,然后打印该列表的话,那么就没办法访问到对应的字符串了
cs = [C(), C(), C()]
for each in cs:
    print(each)
# i love you
# i love you
# i love you
print(cs)
#[i love you, i love you, i love you]
#__repr__()可以访问到每个cs的元素

class C:
    def __str__(self):
        return 'i love you'

cs = [C(), C(), C()]
print(cs)
#[<__main__.C object at 0x000001699FF0AC70>, <__main__.C object at 0x000001699FF0AC40>, <__main__.C object at 0x000001699FF0ACD0>]

class C:
    def __init__(self, data):
        self.data = data
    def __str__(self):
        return f'data = {self.data}'
    def __repr__(self):
        return f'C({self.data})'
    def __add__(self, other):
        self.data += other

c = C(250)
print(c)#data = 250
print(repr(c))#C(250)
c + 250
print(c)#data = 500
print(repr(c))#C(500)
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-11-21 18:52

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表