Python的魔术方法


Python里面有一些以双下划线的(_)开头和结尾的方法,他们被称为魔术方法或者特殊方法,他虽然不是必须的,但是因为它能够自动执行而不用像普通方法一样调用。这样神奇的功能为面向对象编程提供了丰富的扩展性,让我们能够自定义自己的数据类型、算术运算等等。

使用魔术方法要注意避免与Python内置的魔术方法发生冲突,最好检查一下官方文档

Python内置常用魔术方法

1. 初始化与销毁

__init__

用于初始化新创建的对象。

class MyClass:  
def __init__(self, value):
self.value = value

# 使用
obj = MyClass(10)
print(obj.value) # 输出: 10

__del__

当对象即将被销毁时调用。

class MyClass:  
def __init__(self):
print("Object created")

def __del__(self):
print("Object destroyed")

# 使用
obj = MyClass() # 输出: Object created
del obj # 输出: Object destroyed

2. 字符串表示

__str__

返回对象的字符串表示形式。

class Person:  
def __init__(self, name, age):
self.name = name
self.age = age

def __str__(self):
return f"Person(name={self.name}, age={self.age})"

# 使用
p = Person("Alice", 30)
print(p) # 输出: Person(name=Alice, age=30)

__repr__

返回对象的官方字符串表示形式,通常用于调试。

class Person:  
def __init__(self, name, age):
self.name = name
self.age = age

def __repr__(self):
return f"Person({self.name!r}, {self.age})"

# 使用
p = Person("Alice", 30)
print(repr(p)) # 输出: Person('Alice', 30)

3. 算术运算符

__add__

定义对象加法运算的行为。

class Vector:  
def __init__(self, x, y):
self.x = x
self.y = y

def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)

# 使用
v1 = Vector(1, 2)
v2 = Vector(3, 4)
v3 = v1 + v2
print(v3.x, v3.y) # 输出: 4 6

4. 比较运算符

__eq__

定义对象相等性的比较。

class Person:  
def __init__(self, name):
self.name = name

def __eq__(self, other):
if isinstance(other, Person):
return self.name == other.name
return False

# 使用
p1 = Person("Alice")
p2 = Person("Alice")
print(p1 == p2) # 输出: True

5. 容器相关

__len__

返回容器(如列表或自定义容器)的长度。

class MyList:  
def __init__(self, *args):
self.items = list(args)

def __len__(self):
return len(self.items)

# 使用
my_list = MyList(1, 2, 3, 4)
print(len(my_list)) # 输出: 4

6. 迭代器与生成器

__iter__

返回迭代器对象,使对象可以用于迭代(如在for循环中)。

class MyRange:  
def __init__(self, start, end):
self.value = start
self.end = end

def __iter__(self):
return self

def __next__(self):
if self.value < self.end:
current = self.value
self.value += 1
return current
else:
raise StopIteration

# 使用
for i in MyRange(0, 5):
print(i) # 输出: 0

7. 上下文管理

__enter__ 和 __exit__

定义对象作为上下文管理器时的行为,通常与with语句一起使用。

class ManagedFile:  
def __init__(self, filename):
self.filename = filename

def __enter__(self):
self.file = open(self.filename, 'r')
return self.file

def __exit__(self, exc_type, exc_value, traceback):
self.file.close()

# 使用
with ManagedFile('example.txt') as file:
data = file.read()
print(data)
# 文件在with块结束后自动关闭

8. 属性访问

__getattr__

当尝试访问不存在的属性时调用。

class MyObject:  
def __init__(self):
self.existing_attribute = 'Hello'

def __getattr__(self, name):
return f"Unknown attribute: {name}"

# 使用
obj = MyObject()
print(obj.existing_attribute) # 输出: Hello
print(obj.non_existing_attribute) # 输出: Unknown attribute: non_existing_attribute

__setattr__

当为对象设置属性时调用。

class MyObject:  
def __init__(self):
self._internal_state = {}

def __setattr__(self, name, value):
if name.startswith('_'):
super().__setattr__(name, value)
else:
self._internal_state[name] = value

# 使用
obj = MyObject()
obj.my_attribute = 'value'
print(obj._internal_state) # 输出: {'my_attribute': 'value'}

__delattr__

当删除对象属性时调用。

class MyObject:  
def __init__(self):
self.existing_attribute = 'Hello'

def __delattr__(self, name):
if hasattr(self, name):
delattr(super(MyObject, self), name)
else:
raise AttributeError(f"No attribute named {name}")

# 使用
obj = MyObject()
del obj.existing_attribute
print(hasattr(obj, 'existing_attribute')) # 输出: False

9. 转换

__int__

定义到整数的转换。

class Temperature:  
def __init__(self, celsius):
self.celsius = celsius

def __int__(self):
return self.celsius

# 使用
temp = Temperature(25)
celsius = int(temp)
print(celsius) # 输出: 25

__float__

定义到浮点数的转换。

class Fraction:  
def __init__(self, numerator, denominator):
self.numerator = numerator
self.denominator = denominator

def __float__(self):
return self.numerator / self.denominator

# 使用
fraction = Fraction(1, 2)
float_value = float(fraction)
print(float_value) # 输出: 0.5

这些只是Python中魔术方法的一部分,实际上还有很多其他魔术方法可用于定义对象的不同行为。使用魔术方法时,需要确保遵循它们的预期用途,并仔细阅读官方文档以获取更详细的信息和最佳实践。

注意不存过度使用魔术方法,因为

1.并不是所有Python都熟悉,所以会影响可读性与可维护性,

2.此外因为其自动调用,尤其是哪些修改对象状态的方法(如__setattr__),可能会导致代码中出现意外的副作用,从而增加调试和排查问题的难度。

3.虽然魔术方法在某些情况下可以提高代码的灵活性和便利性,但它们也可能引入额外的性能开销

4.魔术方法通常允许开发者深入对象的内部状态和行为。然而,过度使用魔术方法可能会破坏对象的封装性,使得对象的状态和行为变得更容易被外部代码修改和干扰。这可能导致代码的健壮性和可重用性降低。


原文始发于微信公众号(阿尘blog):Python的魔术方法

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/278919.html

(0)
土豆大侠的头像土豆大侠

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!