{% raw %}
Python 魔术方法
Python 魔术方法教程描述了什么是 Python 魔术方法,并说明了如何使用它们。 在本教程中,我们介绍了一些常见的魔术方法。
Python 魔术方法
Python 魔术方法是为我们的自定义类添加功能的特殊方法。 它们被双下划线包围(例如__add __())。
Python 中有许多魔术方法。 它们中的大多数用于非常特殊的情况。 我们将提到一些更流行的方法。
__add__方法
__add__()方法用于实现加法运算。 在 Python 中,数字不是原始字面值,而是对象。 num + 4表达式等效于num.__add__(4)。
add_dict.py
#!/usr/bin/env pythonclass MyDict(dict):def __add__(self, other):self.update(other)return MyDict(self)a = MyDict({'de': 'Germany'})b = MyDict({'sk': 'Slovakia'})print(a + b)
在示例中,我们有一个自定义字典,该字典使用__add__()实现加法运算。
class MyDict(dict):def __add__(self, other):self.update(other)return MyDict(self)
自定义字典继承自内置dict。 __add__()方法与update()方法添加两个字典,并返回新创建的字典。
a = MyDict({'de': 'Germany'})b = MyDict({'sk': 'Slovakia'})
我们创建两个简单的字典。
print(a + b)
我们添加两个字典。
$ ./add_dict.py{'de': 'Germany', 'sk': 'Slovakia'}
这是输出。
__init__和__str__方法
__init__()方法用于初始化对象。 此方法用于实现对象的构造器。 __str__()提供了对象可读的输出。
init_str.py
#!/usr/bin/env pythonclass Person:def __init__(self, name, occupation):self.name = nameself.occupation = occupationdef __str__(self):return f'{self.name} is a {self.occupation}'p = Person('John Doe', 'gardener')print(p)
在示例中,我们有一个Person类,具有两个属性:name和occupation。
def __init__(self, name, occupation):self.name = nameself.occupation = occupation
在__init__()方法中,我们将实例变量设置为传递给构造器的值。
def __str__(self):return f'{self.name} is a {self.occupation}'
__str__()方法可以很好地输出对象。
$ ./init_str.pyJohn Doe is a gardener
这是输出。
__repr__方法
__repr__()方法由内置函数repr()调用。 当它求值返回对象的表达式时,在 Python shell 上使用它。
__str__()用于提供对象的人类可读版本,__repr__()用于提供对象的完整表示。 后者的输出也更适合开发者。
如果缺少__str__()实现,则将__repr__()方法用作后备。
def __repr__(self):return '<{0}.{1} object at {2}>'.format(self.__module__, type(self).__name__, hex(id(self)))
对象的__repr__()方法的默认实现类似于上面的代码。
repr_ex.py
#!/usr/bin/env pythonclass Person:def __init__(self, name, occupation):self.name = nameself.occupation = occupationdef __str__(self):return f'{self.name} is a {self.occupation}'def __repr__(self):return f'Person{{name: {self.name}, occupation: {self.occupation}}}'p = Person('John Doe', 'gardener')print(p)print(repr(p))
该示例实现了__str__()和__repr__()方法。
$ ./repr_ex.pyJohn Doe is a gardenerPerson{name: John Doe, occupation: gardener}
这是输出。
__len__和__getitem__方法
__len__()方法返回容器的长度。 当我们在对象上使用内置的len()方法时,将调用该方法。 __getitem__()方法定义项目访问([])运算符。
french_deck.py
#!/usr/bin/env pythonimport collectionsfrom random import choiceCard = collections.namedtuple('Card', ['suit', 'rank'])class FrenchDeck:ranks = [str(i) for i in range(2, 11)] + list('JQKA')suits = ["heart", "clubs", "spades", "diamond"]def __init__(self):self.total = [Card(suit, rank)for suit in self.suits for rank in self.ranks]def __len__(self):return len(self.total)def __getitem__(self, index):return self.total[index]deck = FrenchDeck()print(deck[0])print(len(deck))print(choice(deck))
该方法用于实现法语卡片组。
Card = collections.namedtuple('Card', ['suit', 'rank'])
我们使用一个命名的元组来定义一个Card类。 namedtuple是用于创建元组类的工厂功能。 每张卡都有一套西装和一个等级。
def __len__(self):return len(self.total)
__len__()方法返回卡座(52)中的卡数。
def __getitem__(self, index):return self.total[index]
__getitem__()实现索引操作。
print(deck[0])
我们得到卡组的第一张牌。 这称为__getitem__()。
print(len(deck))
这将调用__len__()方法。
$ ./french_deck.pyCard(suit='heart', rank='2')52Card(suit='diamond', rank='A')
这是输出。
__int__和__index__方法
调用__int__()方法以实现内置的int()函数。 当在切片表达式中使用对象以及内置的hex(),oct()和bin()函数时,__index__()方法将类型转换为int。
char_ex.py
#!/usr/bin/env pythonclass Char:def __init__(self, val):self.val = valdef __int__(self):return ord(self.val)def __index__(self):return ord(self.val)c1 = Char('a')print(int(c1))print(hex(c1))print(bin(c1))print(oct(c1))
在示例中,我们创建一个自定义的Char类,该类实现了int(),hex(),bin()和oct()函数。
./char_ex.py970x610b11000010o141
这是输出。
__eq __,__ lt__和__gt__方法
__eq__()实现了==运算符。 __lt__()实现了<运算符,__gt__()实现了>运算符。
pouch.py
#!/usr/bin/env pythonimport collectionsCoin = collections.namedtuple('coin', ['rank'])# a gold coin equals to two silver and six bronze coinsclass Pouch:def __init__(self):self.bag = []def add(self, coin):self.bag.append(coin)def __eq__(self, other):val1, val2 = self.__evaluate(other)if val1 == val2:return Trueelse:return Falsedef __lt__(self, other):val1, val2 = self.__evaluate(other)if val1 < val2:return Trueelse:return Falsedef __gt__(self, other):val1, val2 = self.__evaluate(other)if val1 > val2:return Trueelse:return Falsedef __str__(self):return str(self.bag)def __evaluate(self, other):val1 = 0val2 = 0for coin in self.bag:if coin.rank == 'g':val1 += 6if coin.rank == 's':val1 += 3if coin.rank == 'b':val1 += 1for coin in other.bag:if coin.rank == 'g':val2 += 6if coin.rank == 's':val2 += 3if coin.rank == 'b':val2 += 1return val1, val2pouch1 = Pouch()pouch1.add(Coin('g'))pouch1.add(Coin('g'))pouch1.add(Coin('s'))pouch2 = Pouch()pouch2.add(Coin('g'))pouch2.add(Coin('s'))pouch2.add(Coin('s'))pouch2.add(Coin('b'))pouch2.add(Coin('b'))pouch2.add(Coin('b'))print(pouch1)print(pouch2)if pouch1 == pouch2:print('Pouches have equal value')elif pouch1 > pouch2:print('Pouch 1 is more valueable than Pouch 2')else:print('Pouch 2 is more valueable than Pouch 1')
我们有一个可以容纳金,银和青铜硬币的小袋。 一枚金币等于两个银币和六个铜币。 在示例中,我们使用 Python 魔术方法为pouch对象实现了三个比较运算符。
def __eq__(self, other):val1, val2 = self.__evaluate(other)if val1 == val2:return Trueelse:return False
在__eq__()方法中,我们首先求值两个小袋的值。 然后我们比较它们并返回布尔结果。
def __evaluate(self, other):val1 = 0val2 = 0for coin in self.bag:if coin.rank == 'g':val1 += 6if coin.rank == 's':val1 += 3if coin.rank == 'b':val1 += 1for coin in other.bag:if coin.rank == 'g':val2 += 6if coin.rank == 's':val2 += 3if coin.rank == 'b':val2 += 1return val1, val2
__evaluate()方法计算两个袋的值。 它穿过小袋的硬币,并根据硬币的等级增加一个值。
pouch1 = Pouch()pouch1.add(Coin('g'))pouch1.add(Coin('g'))pouch1.add(Coin('s'))
我们创建第一个袋,并在其中添加三个硬币。
if pouch1 == pouch2:print('Pouches have equal value')elif pouch1 > pouch2:print('Pouch 1 is more valueable than Pouch 2')else:print('Pouch 2 is more valueable than Pouch 1')
我们将小袋与比较运算符进行比较。
2D 向量示例
在下面的示例中,我们介绍了几种其他魔术方法,包括__sub__(),__mul__()和__abs__()。
vector.py
#!/usr/bin/env pythonimport mathclass Vec2D:def __init__(self, x, y):self.x = xself.y = ydef __add__(self, other):return Vec2D(self.x + other.x, self.y + other.y)def __sub__(self, other):return Vec2D(self.x - other.x, self.y - other.y)def __mul__(self, other):return self.x * other.x + self.y * other.ydef __abs__(self):return math.sqrt(self.x ** 2 + self.y ** 2)def __eq__(self, other):return self.x == other.x and self.y == other.ydef __str__(self):return f'({self.x}, {self.y})'def __ne__(self, other):return not self.__eq__(other)u = Vec2D(0, 1)v = Vec2D(2, 3)w = Vec2D(-1, 1)a = u + vprint(a)print(a == w)a = u - vprint(a)a = u * vprint(a)print(abs(u))print(u == v)print(u != v)
在示例中,我们有一个Vec2D类。 我们可以比较,加,减和乘向量。 我们还可以计算向量的长度。
$ ./vector.py(2, 4)False(-2, -2)31.0FalseTrue
这是输出。
在本教程中,我们使用了 Python 魔术方法。
您可能也对以下相关教程感兴趣: Python 字符串, Python Jinja 教程和 Python 教程,或列出所有 Python 教程 。
{% endraw %}
