共计 2696 个字符,预计需要花费 7 分钟才能阅读完成。
Python 的数据模型是它的外围,理解数据模型对于了解 Python 是十分重要的。在 Python 中,咱们通过魔法办法(或称为非凡办法,名字以两个下划线开始和完结)来定义咱们的数据模型。在本文中,咱们将深入探讨这些魔法办法,并演示如何应用它们来定义你本人的数据类型。
一、结构和初始化
让咱们从两个最根本的魔法办法开始:__init__
和__new__
。它们被用于定义对象的初始化和结构过程。
class MyClass: | |
def __new__(cls, *args, **kwargs): | |
instance = super().__new__(cls) | |
return instance | |
def __init__(self, value): | |
self.value = value | |
my_instance = MyClass(5) | |
print(my_instance.value) # 输入: 5 |
__new__
办法负责创立新的实例,而 __init__
办法则负责初始化实例。通常,咱们只须要重写 __init__
办法,除非咱们须要管制对象的创立过程。
二、示意和格式化
__repr__
和 __str__
办法容许咱们定义对象的字符串示意。__repr__
应该返回一个尽可能明确的对象示意,而 __str__
则应返回一个适宜打印的示意。
class MyClass: | |
def __init__(self, value): | |
self.value = value | |
def __repr__(self): | |
return f'MyClass(value={self.value})' | |
def __str__(self): | |
return str(self.value) | |
my_instance = MyClass(5) | |
print(repr(my_instance)) # 输入: MyClass(value=5) | |
print(str(my_instance)) # 输入: 5 |
三、比拟操作
Python 通过魔法办法提供了丰盛的比拟操作。例如,__eq__
定义了等于操作,__lt__
定义了小于操作,等等。
class MyClass: | |
def __init__(self, value): | |
self.value = value | |
def __eq__(self, other): | |
if isinstance(other, MyClass): | |
return self.value == other.value | |
return NotImplemented | |
def __lt__(self, other): | |
if isinstance(other, MyClass): | |
return self.value < other.value | |
return NotImplemented | |
my_instance1 = MyClass(5) | |
my_instance2 = MyClass(10) | |
print(my_instance1 == my_instance2) # 输入: False | |
print(my_instance1 < my_instance2) # 输入: True |
四、算术操作
Python 同样提供了一系列的魔法办法来定义算术操作。例如,__add__
定义了加法操作,__mul__
定义了乘法操作,等等。
class MyClass: | |
def __init__(self, value): | |
self.value = value | |
def __add__(self, other): | |
if isinstance(other, MyClass): | |
return MyClass(self.value + other.value) | |
return NotImplemented | |
my_instance1 = MyClass(5) | |
my_instance2 = MyClass(10) | |
result = my_instance1 + my_instance2 | |
print(result.value) # 输入: 15 |
五、访问控制
通过定义 __getattr__
,__setattr__
,__delattr__
和__getattribute__
办法,咱们能够对属性拜访进行更粗疏的管制。
class MyClass: | |
def __init__(self): | |
self._my_secret = 5 | |
def __getattr__(self, name): | |
if name == 'secret': | |
print("Warning: Accessing secret attribute") | |
return self._my_secret | |
raise AttributeError(f"{self.__class__.__name__} object has no attribute {name}") | |
def __setattr__(self, name, value): | |
if name == 'secret': | |
print("Warning: Changing secret attribute") | |
super().__setattr__(name, value) | |
my_instance = MyClass() | |
print(my_instance.secret) # 输入: 5 | |
my_instance.secret = 10 | |
print(my_instance.secret) # 输入: 10 |
六、容器类型
通过定义 __len__
,__getitem__
,__setitem__
,__delitem__
等办法,咱们能够创立自定义的容器类型。
class MyContainer: | |
def __init__(self): | |
self._items = [] | |
def __len__(self): | |
return len(self._items) | |
def __getitem__(self, index): | |
return self._items[index] | |
def __setitem__(self, index, value): | |
self._items[index] = value | |
def __delitem__(self, index): | |
del self._items[index] | |
container = MyContainer() | |
container._items = [1, 2, 3] | |
print(len(container)) # 输入: 3 | |
print(container[1]) # 输入: 2 | |
container[1] = 10 | |
print(container[1]) # 输入: 10 | |
del container[1] | |
print(container._items) # 输入: [1, 3] |
七、总结
Python 的数据模型容许咱们应用魔法办法定义本人的数据类型,让咱们的代码更加 Pythonic。这只是冰山一角,还有更多的魔法办法期待你去发现。把握了这些,你将能更加深刻地了解 Python,并写出更好的 Python 代码。