BrightXiong 发表于 2023-4-1 18:05:40

类和对象-__call__

>>> #只要定义了__call__()方法,Python便可以像调用函数一样去调用该对象,不仅支持位置参数和关键字参数,还可以用作闭包的简易实现!

内置函数repr()与str()运行结果常常相同,但设计初衷不同——str()将参数转换为字符串,给人看;
repr()将对象转换为程序可执行的字符串,给程序(机器)看。

被repr()转化后的字符串可以被内置函数eval()去引号后执行,其结果往往就是原参数,故eval()可以理解为repr()的反函数。
魔法方法__str__()和__repr__()分别对应str()和repr(),二者均返回字符串,且__repr__()可作为__str__()的代偿(反之不成立)。
不过,通过__str__()定义的只能应用于对象出现在打印操作的顶层,
但__repr__()则不同,其适用场景更多,用起来也更安全!
最后,同时定义两个方法可以让对象在不同场景下实现不同的显示效果,既灵活又有趣!

>>> #__call__():在对象中既可以有属性又可以有方法,python可以像调用函数一样去调用一个对象,要求就是需要这个对象的类定义__call__()魔法方法
>>> class C:
...         def __call__(self):
...                 print('Hello')
...
>>> c = C()
>>> c()
Hello
>>> class C():
...         def __call__(slef, *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)
>>> square(5)
25
>>> cube(3)
27

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

>>> #repr()返回的带引号,str()返回的不带引号
>>> eval("print('crazy')")
crazy
>>> eval(repr('crazy'))
'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')"))
"print('crazy')"
>>> eval(repr(print('carzy')))
carzy
>>> 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 =
>>> for each in cs:
...         print(each)
...
i love you
i love you
i love you
>>> print(cs)


>>> #__repr__()可以访问到每个cs的元素
>>> class C:
...         def __str__(self):
...                 return 'i love you'
...
>>> cs =
>>> print(cs)
[<__main__.C object at 0x01EAE3A0>, <__main__.C object at 0x01EAE5B0>, <__main__.C object at 0x01EAE4F0>]

>>> 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)
页: [1]
查看完整版本: 类和对象-__call__