鱼C论坛

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

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

[复制链接]
发表于 2022-8-16 05:22:32 | 显示全部楼层 |阅读模式
购买主题 已有 13 人购买  本主题需向作者支付 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__()
  1. #__call__():在对象中既可以有属性又可以有方法,python可以像调用函数一样去调用一个对象,要求就是需要这个对象的类定义__call__()魔法方法
  2. class C:
  3.     def __call__(self):
  4.         print('hello')

  5. c = C()
  6. c()#hello

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

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

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

  20. square = Power(2)
  21. cube = Power(3)
  22. print(square(5))#25
  23. print(cube(3))#27

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

  27. print(repr("print('crazy')"))#"print('crazy')"
  28. print(str("print('crazy')"))#print('crazy')
  29. #repr()返回的带引号,str()返回的不带引号
  30. eval("print('crazy')")#crazy
  31. eval(repr('crazy'))
  32. try:
  33.     eval(str('crazy'))
  34. except NameError as e:
  35.     print(e)#name 'crazy' is not defined
  36. #str('crazy')的返回值为crazy,不带引号,python会将其作为变量名来引用,结果就是找不到的定义fishc的变量
  37. #repr()返回的是带引号的'crazy',eval(repr('crazy'))会执行
  38. eval(repr("print('crazy')"))#不打印
  39. eval(repr(print('crazy')))#crazy
  40. eval(str("print('crazy')"))#crazy
  41. eval(str(print('crazy')))#crazy

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

  46. c = C()
  47. print(repr(c))#i love you
  48. print(str(c))#i love you

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

  59. class C:
  60.     def __str__(self):
  61.         return 'i love you'

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

  65. class C:
  66.     def __init__(self, data):
  67.         self.data = data
  68.     def __str__(self):
  69.         return f'data = {self.data}'
  70.     def __repr__(self):
  71.         return f'C({self.data})'
  72.     def __add__(self, other):
  73.         self.data += other

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-5-11 17:08

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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