探索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所有,由作者自行决定使用。
[
上一篇文章
探索数据可视化的Matplotlib样式表
](www.analyticsvidhya.com/blog/2021/0…)