别眨眼!看魔术方法如何提升Python 代码性能?

全文共4790字,预计学习时长14分钟

图源:Unsplash

掌握一些技巧,可尽量提高Python程序性能,也可以避免不必要的资源浪费。比如,在Python中使用魔术方法,就可以提升代码性能。今天,小芯就给大家传授可以提升python程序性能的“魔术”,赶快来学习吧~

什么是魔术方法(Magic Methods)?

魔术方法是面向对象的Python编程中的概念。你有很多可以定义类别的特殊方法,以增添其 “魔力”。

魔术方法总是被双下划线包围,例如__ init __ 。它们也没有得到充足的记录。Python的所有魔术方法都记录在Python文档的同一部分中,分布分散且组织松散。在该部分几乎找不到示例。

有哪些魔术方法?

为了解决魔术方法文档缺失的问题,我整理了一些有关如何使用Python魔术方法的简单示例。

图源:Unsplash

1. 创建一个只接受整数和浮点数作为其值的dict对象

首先创建一个虚拟的用例。在这种情况下,笔者想创建一个能够创建字典对象的类,该类只接受整数或浮点数作为其值。

如果任何有其他数据类型例如:字符串、列表、元组作为值添加到自定义字典对象中,将引发异常,提示用户此自定义dict对象只能接受整数和浮点数。

为了实现上述,使用以下魔术方法:

__int __,__ setitem __和__str__

首先创建一个名为CustomIntFloat 的自定义类,然后将dict 传递到参数继承列表中。这意味着,除了选择修改此行为的地方之外,创建对象的行为将与字典基本一致。

然后创建一个__ init __方法来构造CustomIntFloat dict 对象。该对象的参数列表中包含键和值,默认情况下,将其设置为“None”类型。原因是,如果用户创建CustomIntFloat类的对象,而没有传递键或值,则将创建一个空的dict。我创建了一个简单的条件,该条件是:如果未传递键,则默认情况下会将键参数分配给“None”,并通过引用CustomIntFloat 对象(带有类属性empty_dict)来创建一个空dict 。

接下来,如果用户指定了长度为1的键以及int或float类实例的对应值,则将在对象中设置键和值。

最后,在else语句中,如果用户将多个键和值指定为可迭代对象,则将使用zip函数将可迭代对象压缩,并为其分配变量名称zipped。最后,遍历压缩后的值,并检查该值是int还是float类型。如果不是,则会引发自定义错误CustomIntFloatError异常现象。

2. CustomIntFloatError Exception类和__str__魔术方法

当引发CustomIntFloatError异常时,实际上是在创建CustomIntFloatError类的实例并同时输出它。

因此,此自定义错误类需要__ init __和__str__魔术方法。在此实例中,采用传递的值,并将其设置为CustomIntFloatError类中的属性值。

这意味着,当程序报错,传递给CustomIntFloat的init值可以设置为customintflower类中的属性(self.value),易于检查。

如果指定了无效输入,则会引发CustomIntFloatError异常,并且不会构造该对象。一条有用的错误消息会告知用户只有整数和浮点数是有效值。

同样,当尝试使用多个键和值实例化对象z(已注释掉)时,将引发相同的异常,通知用户此处存在“三个”无效输入。

  1. #z = CustomIntFloat (key= ['a','b','c'],value= [1、2,'three'])
  2. ž = CustomIntFloat (key= [ 'A' ,'B' ,'C' ],value= [ 1 ,2 ,3 ])

3. __ setitem __魔术方法

在字典中设置键和值时会调用__setitem __这种魔术方法。一旦构造了CustomIntFloat 对象,如果用户尝试添加非int或float类型的值,则将引发相同的CustomIntFloatError 异常。在下面添加了一个代码段,该代码段显示了如何按预期设置键和值。

  1. x = CustomIntFloat('a', 1)
  2. print(type(x))
  3. x['b'] =2.1
  4. print(x)
  5. # x['c'] = 'Three'

无效的输入会导致引发CustomIntFloatError异常,如下所示。

  1. classCustomIntFloatError(Exception):
  2. def__init__(self, value):
  3. self.value = value
  4. def__str__(self):
  5. returnself.value +' is not valid\nOnly Integers and floats are valid values \nin CustomIntFloat(dict) '
  6. classCustomIntFloat(dict):
  7. empty_dict = {}
  8. def__init__(self, key=None, value=None):
  9. if key isNone:
  10. CustomIntFloat.empty_dict = {}
  11. eliflen(key) ==1andisinstance(value, (int, float)):
  12. dict.__setitem__(self, key, value)
  13. else:
  14. zipped =zip(key, value)
  15. for tup in zipped:
  16. ifisinstance(tup[1], (int, float)):
  17. dict.__setitem__(self, tup[0], tup[1])
  18. else:
  19. raise CustomIntFloatError(tup[1])
  20. def__setitem__(self, key, value):
  21. ifnotisinstance(value, (int, float)):
  22. raise CustomIntFloatError(value)
  23. returndict.__setitem__(self, key, value)

4. CustomIntFloat类的摘要 

图源:Unsplash

通过像dict 这样的内置类继承,可以通过魔术方法来重新实现自定义行为。这有很多好处。

重要的是,用户不需要学习任何新语法。当用户想要向CustomIntFloatdict 对象添加键和值时,他们只需以通常的方式进行添加。唯一的区别是选择了只允许int和float类型的值。如果用户指定了其他任何类型,则自定义错误消息会有效地指示用户出错的位置以及预期的值类型。

5. Quick-Fire魔术方法

使用数学运算符的示例

__sub__,__add__,和__ MUL __(附a custom __repr__))

还可以在Python中的数学运算符中利用魔术方法一起看看魔术方法的具体运用,如在自定义对象中创建的__add__,__sub__和__MUL __。

像+,-,/和*这样的运算符是多态方法。如下面的Python prompt所示,加号(+)是多态的,可用于连接字符串,将整数和组合列表相加。这是可行的,因为所有这些类型(str,list和int)在各自的类中都有一个add方法。Python只是将+符号转换为对调用对象的__add__方法(请参见下面的示例)。

这意味着,如果在类中包含__add__方法,则可以利用自己的对象中的+号。

类中的魔术方法运算符

此处,创建一个名为NumOperations 的类。此类会创建NumOperations 对象。当将NumOperations的用户将列表传递到__init __ 的参数列表时,该列表将被设置为NumOperations对象中的属性,并命名为math_list 。

当NumOperations 对象(S)建成后,可以便捷地利用魔术方法和定义对象以及播发数学运算。

更详细地说,魔术方法__sub__接受2个NumOperations对象,并将它们的列表压缩在一起,迭代其他对应的元组列表。从第一个元组中减去第二个元素,并将该值附加到名为minuslst的新列表中,并将其作为参数传递给NumOperations构造函数。

现在,返回值为一个新的NumOperations 对象。

使用__sub__方法执行此广播意味着我们可以利用减号(-)运算符。

再次利用魔术方法__ repr __,以返回新对象中列表集的字符串。同时,对此进行了修改,以便当用户在得到两个所期望的NumOperations对象输出。

这是一个列表,其中的元素已被相互减去;

[90,81,72,63,54]。

__add__和__MUL __都有一个类似的方法操作——__sub__,但使用列表理解来削减必要的代码行数。

为了使用自定义NumOperation对象,已经提前定义了减法,加法和乘法魔术方法。

这种广播行为类似于数据分析包(例如Pandas和Numpy)中的广播行为。

__add__和__MUL __方法都有两个NumOperations 对象。这意味着用户可以同时利用加号运算符+和乘法运算符*。,在下面的示例中可以看出,q是x * y的结果,它返回了一个新的NumOperations对象。当我们打印q时,我们将广播操作的字符串表示形式作为列表。

  1. classNumOperations(object):
  2. def__init__(self, math_list):
  3. self.math_list = math_list
  4. def__sub__(self, other):
  5. minuslst = []
  6. zipped =zip(self.math_list, other.math_list)
  7. for tup in zipped:
  8. minuslst.append(tup[0] - tup[1])
  9. return NumOperations(minuslst)
  10. def__add__(self, other):
  11. addlst = [x + y for x, y inzip(self.math_list, other.math_list)]
  12. return NumOperations(addlst)
  13. def__mul__(self, other):
  14. mullst = [x * y for x, y inzip(self.math_list, other.math_list)]
  15. return NumOperations(mullst)
  16. def__repr__(self):
  17. returnstr(self.math_list)
  18. x = NumOperations([100, 90, 80, 70, 60])
  19. y = NumOperations([10, 9, 8, 7, 6])
  20. p = x - y
  21. z = x + y
  22. q = x * y
  23. print('Subtraction: '+str(p))
  24. print('Addition: '+str(z))
  25. print('Multiplication: '+str(q))

图源:Unsplash

我们可以使用Python操作符(如加号、减号和乘法符号)自定义对象。这是非常强大的功能,而强大的原因是其能够非常轻松地传达对象操作的能力。用户不需要学习任何新方法,他们只需将NumOperations对象相加、相减或相乘,当用户打印结果对象时,将看到他们期望的输出。

是不是很神奇?

留言 点赞 关注

我们一起分享AI学习与发展的干货
欢迎关注全平台AI垂类自媒体 “读芯术”

(添加小编微信:dxsxbb,加入读者圈,一起讨论最新鲜的人工智能科技哦~)

发布了691 篇原创文章 · 获赞 2327 · 访问量 29万+

猜你喜欢

转载自blog.csdn.net/duxinshuxiaobian/article/details/103905584