Python: 不应该使用的魔术方法
Python: magic methods that shouldn't be used
我创建了一个 class,它是一个 tuple
包装器,元组不支持项目突变。
我应该离开 __setitem__
和 __delitem__
实现还是实现那些方法,例如下面(因此有点像 Refused Bequest 代码的味道)?哪种方法更pythonic?在这种情况下自定义异常不是更好吗?
def __setitem__(self, key, value):
"""
:raise: Always.
:raises: TypeError
"""
self.data_set[key] = value # Raise from tuple.
def __delitem__(self, key):
"""
:raise: Always.
:raises: TypeError
"""
raise TypeError("Item deletion is unsupported") # Custom exceptions thrown.
如果它们对您的自定义有意义,则实施其中之一或同时实施两者 class。
如果您实施 __setitem__()
,您将能够在代码中使用 yourobject[yourindex] = yourvalue
语法(使用您选择实施的语义)。
如果您实施 __delitem__()
,您将能够使用 del yourobject[yourindex]
显式实现一个方法只是为了引发异常是没有意义的,Python 默认情况下会这样做:
class Test(object):
pass
test = Test()
test['foo'] = 'bar' # will call Test.__setitem__() which is not explicitly defined
会给TypeError: 'Test' object does not support item assignment
尽管这是个人喜好问题,但我认为您根本不应该实施它们。具有 __setitem__, __delitem__
的 class 实现可变集合 协议 (隐式地,甚至通过使用 collection abstract base classes 显式地实现)。你的class只是不支持这个接口,就是这样,用户没有理由也没有权利假设它支持
如果你的 class 应该是一个正确的元组子类型(根据 Liskov substitution principle),那么它的行为应该与元组 wrt/ 到 set/del 的行为相同 - 这正如 Guillaume 提到的那样,如果您既不定义 __setitem__
也不定义 __delitem__
,这是默认行为。我不明白那怎么会属于 "Refused Bequest" 类别。
如果您的 class 在其实现中使用了一个元组但不应该是一个正确的元组子类型,那么做任何有意义的事情 - 但如果您不想允许项目分配/删除那么最简单的事情就是不实施它们。
我创建了一个 class,它是一个 tuple
包装器,元组不支持项目突变。
我应该离开 __setitem__
和 __delitem__
实现还是实现那些方法,例如下面(因此有点像 Refused Bequest 代码的味道)?哪种方法更pythonic?在这种情况下自定义异常不是更好吗?
def __setitem__(self, key, value):
"""
:raise: Always.
:raises: TypeError
"""
self.data_set[key] = value # Raise from tuple.
def __delitem__(self, key):
"""
:raise: Always.
:raises: TypeError
"""
raise TypeError("Item deletion is unsupported") # Custom exceptions thrown.
如果它们对您的自定义有意义,则实施其中之一或同时实施两者 class。
如果您实施 __setitem__()
,您将能够在代码中使用 yourobject[yourindex] = yourvalue
语法(使用您选择实施的语义)。
如果您实施 __delitem__()
,您将能够使用 del yourobject[yourindex]
显式实现一个方法只是为了引发异常是没有意义的,Python 默认情况下会这样做:
class Test(object):
pass
test = Test()
test['foo'] = 'bar' # will call Test.__setitem__() which is not explicitly defined
会给TypeError: 'Test' object does not support item assignment
尽管这是个人喜好问题,但我认为您根本不应该实施它们。具有 __setitem__, __delitem__
的 class 实现可变集合 协议 (隐式地,甚至通过使用 collection abstract base classes 显式地实现)。你的class只是不支持这个接口,就是这样,用户没有理由也没有权利假设它支持
如果你的 class 应该是一个正确的元组子类型(根据 Liskov substitution principle),那么它的行为应该与元组 wrt/ 到 set/del 的行为相同 - 这正如 Guillaume 提到的那样,如果您既不定义 __setitem__
也不定义 __delitem__
,这是默认行为。我不明白那怎么会属于 "Refused Bequest" 类别。
如果您的 class 在其实现中使用了一个元组但不应该是一个正确的元组子类型,那么做任何有意义的事情 - 但如果您不想允许项目分配/删除那么最简单的事情就是不实施它们。