探索Python中的神奇方法

166 阅读6分钟

初学者编程Python

探索Python中的神奇方法

Srivignesh_R ,2021年8月9日

文章视频书

这篇文章是作为数据科学博客马拉松的一部分发表的

魔术方法

魔法是Python中的特殊方法,在方法名称的两边有双下划线(dunder)。魔法主要用于操作符重载。操作符重载意味着为操作符提供了额外的功能,Python隐含地调用魔法方法为其提供额外的功能。例如,两个整数的相乘可以使用乘法运算符(2*3=6),同样的运算符可以用来重复字符串("apple- " * 3 = 'apple- apple- apple')。

一些魔法方法的例子是__init__, __len__, __repr__, __add__,等等。

__add__魔法方法

__add__魔法方法被用来添加类实例的属性。例如,假设 object1 是一个类 A 的实例,object2 是一个类 B 的实例,这两个类都有一个名为'a'的属性,它持有一个整数。当操作 object1 + object2 时,__add__方法隐含地添加这些实例的属性,如 object1.a + object2.a,如果这样定义的话。

class One:
    def __init__(self, a):
        self.a = a
    def __add__(self, object2):
        return self.a + object2.a
class Two:
    def __init__(self, a):
        self.a = a
    def __add__(self, object2):
        return self.a + object2.a
a_instance = One(10)
b_instance = Two(20)
print(a_instance + b_instance)
# Output: 30

在上面的代码中,类一和类二拥有一个叫做'a'的属性,持有一个整数值。我们定义了两个实例a_instance和b_instances,它们的属性中分别包含10和20的值。当我们执行操作 a_instance + b_instance 时,定义的 __add__ 方法将把操作转换成 a_instance.a + b_instance.a,结果是输出 30。

具体的操作可以用字符串来完成。

class Str:
    def __init__(self, string_):
        self.string_ = string_
    def __add__(self, string2):
        return self.string_ + string2
instance1 = Str("Hello")
print(instance1 + " Folks")
# Output: Hello Folks

操作 instance1 + " Folks "通过隐式执行以下操作将两个字符串连接起来 instance1.string_ + " Folks"。

__getitem__和__setitem__魔法方法

__getitem__方法被用来从被调用的实例的属性中获取一个项目。__getitem__ 通常用于容器,如 list, tuple, 等等。

class A:
    def __init__(self, item):
        self.item = item
    def __getitem__(self, index):
        return self.item[index]
a = A([1, 2, 3])
print(f"First item: {a[0]}")
print(f"Second item: {a[1]}")
print(f"Third item: {a[2]}")
# Output: 
# First item: 1
# Second item: 2
# Third item: 3

__setitem__方法用来将项目设置到被调用实例属性的一个特定索引中。类似于 __getitem__,__setitem__ 也被用于容器。

class SetItemExample:
    def __init__(self, item):
        self.item = item
    def __setitem__(self, index, item1):
        self.item[index] = item1
setitem_instance = SetItemExample([1, 2, 3])
print(f"Items before setting: {setitem_instance.item}")
setitem_instance[1] = 5
print(f"Items after setting: {setitem_instance.item}")
# Output
# Items before setting: [1, 2, 3]
# Items after setting: [1, 5, 3]

__repr__魔法方法

__repr__魔法方法用来在字符串中表示一个类的实例。当我们试图打印一个类的对象时,__repr__方法被隐式调用,返回一个字符串。

class ReprExample:
    def __init__(self, a, b, c):
        self.a = a
        self.b = b
        self.c = c
    def __repr__(self):
        return f"ReprExample(a={self.a}, b={self.b}, c={self.c})"
repr_instance = ReprExample(1, 2, 3)
print(repr_instance)
# Output
# ReprExample(a=1, b=2, c=3)

上面的类需要三个整数参数,即a、b和c。我们通过使用ReprExample(1, 2, 3)创建一个实例,如果我们打印这个实例,它将打印出__repr__中定义的字符串。

__len__魔法方法

__len__ 魔法方法用于查找实例属性的长度。当我们使用 len(instance) 时,它返回实例属性的长度,通常为容器。

class LenExample:
    def __init__(self, item):
        self.item = item
    def __len__(self):
        return len(self.item)
len_instance = LenExample([1, 2, 3])
print(len(len_instance))
# Output: 3

当我们调用 len() 方法时,返回名为 item 的列表的长度,该列表定义在 __len__ 方法中。

__lt__, __gt__, __le__, __ge__, __eq__, 和 __ne__魔法方法

比较运算符可以被用来比较对象的属性。可用的方法有__lt__, __gt__, __le__, __ge__, __eq__, 和__ne__,分别执行小于、大于、小于或等于、大于或等于、等于和不等于的操作。

class Comparison:
    def __init__(self, a):
        self.a = a
    def __lt__(self, object2):
        return self.a < object2.a
    def __gt__(self, object2):
        return self.a > object2.a
    def __le__(self, object2):
        return self.a <= object2.a
    def __ge__(self, object2):
        return self.a >= object2.a
    def __eq__(self, object2):
        return self.a == object2.a
    def __ne__(self, object2):
        return self.a != object2.a
a = Comparison(1)
b = Comparison(2)
print(
    a < b,
    a > b,
    a <= b,
    a >= b,
    a == b,
    a != b
)
# Output
# True False True False False True

实例a和b包含一个名为'a'的属性,分别持有整数值1和2。

当我们调用以下操作时。

  • a < b。
  • a > b,
  • a <= b,
  • a >= b。
  • a == b,
  • a != b

魔法方法被Python隐式调用,执行以下操作,而不是上面提到的那些。

  • a.a < b.a,
  • a.a > b.a。
  • a.a <= b.a,
  • a.a >= b.a,
  • a.a == b.a,
  • a.a != b.a

这些定义在魔法方法内部的隐式操作返回布尔值。

__contains__魔法方法

__contains__方法是在使用成员操作符'in'时调用的。当我们想检查一个元素是否存在于对象的属性中,这些属性通常是容器(列表,元组),我们可以使用 __contains__ 方法。

class ContainsExample:
    def __init__(self, items):
        self.items = items
    def __contains__(self, item):
        return item in self.items
contains_instance = ContainsExample([1, 2, 3, 4, 5])
print(4 in contains_instance)

上面的代码使用 __contains__ 方法来查找一个整数是否存在于整数的列表中。在上面的代码中,我们检查了整数4是否存在于整数列表中,该列表是 ContainsExample 类的一个属性。

__enter__ 和 __exit__ 的神奇方法

__enter__ 和 __exit__ 方法是和 python 中的 'with' 块一起使用的。python中的'with'块被用来打开和关闭文件对象或任何其他有关闭方法的对象。

class WriteFile:
    def __init__(self, file_name):
        self.file_name = file_name
        self.file = None
    def log(self, text):
        self.file.write(text+'n')
    def __enter__(self):
        self.file = open(self.file_name, "a+")
        return self    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.file.close()
with WriteFile(r"filename.txt") as log_file:
    log_file.log("Log Test 1")
    log_file.log("Log Test 2")

当这个类以文件名 "filename.txt "被调用时,__enter__方法隐式地创建了一个文本文件。在执行了文本文件中的命令后,__exit__方法被隐式调用以关闭文件对象。通过这种方式,我们可以使用 __enter__ 和 __exit__ 的神奇方法。这些方法也可以用来打开和关闭一个数据库连接。

__call__魔法方法

当一个类的实例被调用时,__call__魔法方法被调用。我们可以使用__call__方法直接从实例名称中调用,而不是编写另一个方法来执行某些操作。

class CallExample:
    def __init__(self, val):
        self.val = val
    def __call__(self, b):
        return self.val * b
call_example = CallExample(5)
print(call_example(6))
# Output: 30

call_example实例可以作为一个方法被直接调用,因为我们已经在类中定义了__call__方法。在这个例子中的__call__方法得到一个名为b的值,并与类的'val'属性相乘,在上面的例子中产生了30的输出。

__iter__魔法方法

__iter__方法被用来为所提供的实例提供一个生成器对象。我们可以利用iter()和next()方法来利用__iter__方法。

class Squares:
    def __init__(self, start, stop):
        self.start = start
        self.stop = stop
    def __iter__(self):
        for value in range(self.start, self.stop + 1):
            yield value ** 2
i = iter(Squares(1, 3))
print(next(i))
print(next(i))
print(next(i))
# Output: 1 4 9

在上面的代码中,我们将找到所提供的范围(开始和停止)之间的数值的平方。当我们调用iter(Squares(1, 3))方法时,__iter__方法被调用,该方法可以得到所提供范围内的数值的平方。在我们的例子中,我们使用的是 1 到 3 的范围,所以如果我们调用 next() 方法,输出结果将是 1, 4, 和 9。

总结

  • 在这篇文章中,我们看到了如何利用python中的魔法方法来为类对象提供额外的功能,而没有任何开销。
  • __add__方法被用来添加两个对象的属性
  • __getitem__ 和 __setitem__ 方法用于设置和获取一个对象的容器属性的项目。
  • __repr__方法用来打印对象为一个字符串。
  • __len__方法用来查找对象属性的长度。
  • __lt__, __gt__, __le__, __ge__, __eq__, 和 __ne__ 方法用于比较对象的属性。
  • __contains__方法用于成员身份的验证
  • __enter__ 和 __exit__ 方法在 python 中与 'with' 块一起使用。
  • __call__方法用于使用对象作为一个方法。
  • __iter__方法用于使用该对象生成生成器对象。

本文所展示的媒体不属于Analytics Vidhya所有,由作者自行决定使用。

你也可以在我们的手机APP上阅读这篇文章 Get it on Google Play

标签 :博客马拉松, 编程, python

[

上一篇文章

探索数据可视化的Matplotlib样式表

](www.analyticsvidhya.com/blog/2021/0…)

Srivignesh_R