在广阔的 Python 编程世界中,有一组特性经常被初学者忽视,但在该语言的生态系统中具有重要意义。
魔术方法是一组前置方法defiPython 中提供特殊语法功能的点。 通过开头和结尾处的双破折号很容易识别它们,例如 __init__, __call__, __len__
… ETC。
魔术方法允许自定义对象的行为类似于内置的 Python 类型。
在本文中,我们将重点介绍强大的 dunder 函数。 我们将探讨它们的用途并讨论它们的用途。
无论你是 Python 新手还是经验丰富的程序员,本文旨在让你全面了解 Dunder 函数,让你的 Python 编码体验更高效、更愉快。
请记住,Python 的魔力不仅在于其简单性和多功能性,还在于其强大的功能,如 Dunder 函数。
也许是所有功能中最基本的 dunder 功能。 这是每当我们创建(或顾名思义,初始化)一个新对象时 Python 自动调用的神奇方法。__init__
比萨类:
def __init__(自我,大小,浇头):
self.size = 大小
self.toppings = 浇头
# 现在让我们创建一个披萨
my_pizza = Pizza('large', ['pepperoni', 'mushrooms'])
print(my_pizza.size) # 这将打印:large
print(my_pizza.toppings) # 这将打印:['pepperoni', 'mushrooms']
在此示例中,创建了一个名为 Pizza 的类。 我们设置我们的 __init__ 函数以包含在初始化时指定的参数,并将它们设置为我们自定义对象的属性。
在这里,它用来表示类的实例。 所以当我们写 self.size = size 时,我们是在说,“嘿,这个披萨对象有一个属性 size size
,我希望它是我在创建对象时提供的任何大小”。
这是Python的神奇方法,它允许我们 defi完成我们的定制项目的描述。
当您使用打印对象或将其转换为字符串时 str()
, Python 检查你是否有 defi我想出了一个方法 __str__
对于那个对象的类。
如果是这样,请使用该方法将对象转换为字符串。
我们可以扩展 Pizza 示例以包含一个函数 __str__
如下:
披萨类:def __init__(self, size, toppings): self.size = size self.toppings = toppings def __str__(self): return f"A {self.size} pizza with {', '.join(self.toppings )}" my_pizza = Pizza('large', ['pepperoni', 'mushrooms']) print(my_pizza) # 这将打印:一个大披萨配意大利辣香肠和蘑菇
__repr__
__str__ 函数更像是一种描述对象属性的非正式方式。 另一方面,__repr__ 用于提供自定义对象的更正式、详细和明确的描述。
如果你打电话 repr()
在一个对象上,或者你只是在控制台中输入对象名称,Python 将寻找一个方法 __repr__
.
Se __str__
是不是 defi晚上,Python会使用 __repr__
作为尝试打印对象或将其转换为字符串时的备份。 所以这通常是个好主意 defi至少完成 __repr__
,即使你不这样做 defi尼斯 __str__
.
我们可以这样做 defi尼雷尔 __repr__
对于我们的披萨示例:
比萨类:
def __init__(自我,大小,浇头):
self.size = 大小
self.toppings = 浇头
def __repr__(自我):
返回 f"披萨 ('{self.size}', {self.toppings})"
my_pizza = Pizza('large', ['pepperoni', 'mushrooms'])
print(repr(my_pizza)) # 这将打印: Pizza('large', ['pepperoni', 'mushrooms'])
__repr__
为您提供一个字符串,您可以将其作为 Python 命令运行以重新创建比萨饼对象,而 __str__
给你一个更人性化的描述。 我希望它能帮助你更好地咀嚼这些愚蠢的方法!
在 Python 中,我们都知道可以使用运算符将数字相加 +
作为 3 + 5
.
但是如果我们想添加一些自定义对象的实例怎么办?
双打功能 __add__
它使我们能够做到这一点。 它使我们有能力 defi完成操作者的行为 +
在我们的个性化项目上。
为了保持一致性,我们假设我们想要 defi完成的行为 +
在我们的披萨示例中。 比方说,每当我们将两个或多个比萨饼放在一起时,它会自动组合所有的配料。 它可能看起来像这样:
比萨类:
def __init__(自我,大小,浇头):
self.size = 大小
self.toppings = 浇头
def __add__(自我,其他):
如果不是实例(其他,比萨饼):
提高类型错误(“你只能添加另一个披萨!”)
new_toppings = self.toppings + other.toppings
返回披萨(self.size,new_toppings)
# 让我们创建两个比萨饼
pizza1 = Pizza('large', ['pepperoni', 'mushrooms'])
pizza2 = Pizza('大', ['橄榄', '菠萝'])
# 现在让我们“添加”它们
组合披萨 = 披萨 1 + 披萨 2
print(combined_pizza.toppings) # 这将打印:['pepperoni', 'mushrooms', 'olives', 'pineapple']
类似于 dunder __add__
,我们还可以 defi完成其他算术函数,例如 __sub__
(通过使用运算符进行减法 -
)和 __mul__
(对于使用运算符的乘法 *
).
这种 dunder 方法使我们能够 defi完成什么功能 len()
必须返回我们的定制项目。
Python 使用 len()
获取数据结构(如列表或字符串)的长度或大小。
在我们的例子中,我们可以说比萨饼的“长度”是它的配料数量。 以下是我们如何实现它:
比萨类:
def __init__(自我,大小,浇头):
self.size = 大小
self.toppings = 浇头
def __len__(自我):
返回 len(self.toppings)
# 让我们创建一个披萨
my_pizza = Pizza('large', ['pepperoni', 'mushrooms', 'olives'])
print(len(my_pizza)) # 这将打印:3
在 __len__ 方法中,我们只返回列表的长度 toppings
。 然而, len(my_pizza)
它会告诉我们上面有多少配料 my_pizza
.
这个 dunder 方法允许对象是可迭代的,即它可以在 for 循环中使用。
为此,我们还必须 defi完成函数 __next__
, 这个用于 defi完成应该在迭代中返回下一个值的行为。 当序列中不再有元素时,它还应该向可迭代对象发出信号。 我们通常通过抛出异常来实现这一点 StopIteration
.
对于我们的披萨示例,假设我们想要迭代配料。 我们可以使 Pizza 类可迭代 defi一个方法 __iter__
:
比萨类:
def __init__(自我,大小,浇头):
self.size = 大小
self.toppings = 浇头
def __iter__(自我):
自我.n = 0
回归自我
定义 __next__(自我):
如果 self.n < len(self.toppings):
结果 = self.toppings[self.n]
自我.n += 1
返回结果
其他:
提高停止迭代
# 让我们创建一个披萨
my_pizza = Pizza('large', ['pepperoni', 'mushrooms', 'olives'])
# 现在让我们迭代它
用于 my_pizza 的配料:
打印(打顶)
在这种情况下,for 循环调用 __iter__
, 初始化一个计数器 (self.n)
并返回披萨对象本身 (self)
.
然后,for循环调用 __next__
依次获得每个浇头。
当 __next__
退回所有调味料, StopIteration
它抛出一个异常,并且 for 循环现在知道没有更多的浇头,因此将中止迭代过程。
Ercole Palmeri