魔术方法 Python's Magic Methods
构建和初始化
-
__new__(cls,[...)
一个对象的实例化时__new__是第一个被调用的方法。在类中传递其他任何参数到__init__。
很少使用 -
__init__(self,[...)
类的初始化。自定义一个对象的初始化行为。 -
__del__(self)
定义为当一个对象被垃圾回收时的行为。
对可能需要额外清理的对象相当有用,比如 sockets 或文件对象。
如果对象仍处于存活状态而当被解释退出时,__del__没有保证就会被执行,因此这样的__del__不能作为良好的编码规范的替代。
实际使用
from os.path import join
class FileObject:
'''对文件对象的包装,确保文件在关闭时得到删除'''
def __init__(self, filepath='~', filename='sample.txt'):
# 按filepath,读写模式打开名为filename的文件
self.file=open(join(filepath,filename), 'r+')
def __del__(self):
self.file.close()
del self.file
使操作符在自定义类内工作
使用 Python 魔术方法的优势之一就是它提供了一种简单的方式能让对象的行为像内建类型。我们可以使用魔术方法定义运算符的意义。
比较
-
__cmp__(self, other)
实现所有比较操作符行为(<,==,!=,等),但有可能不按你想要的方法工作(例如,一个实例是否等于另一个这取决于比较的准则,以及一个实例是否大于其他的这也取决于其他的准则)。如果 self < other,那 cmp 应当返回一个负整数;如果 self == other,则返回 0;如果 self > other,则返回正整数。它通常是最好的定义,而不需要你一次就全定义好它们,但当你需要用类似的准则进行所有的比较时,cmp 会是一个很好的方式,帮你节省重复性和提高明确度。 -
__eq__(self, other)---->== -
__ne__(self, other)---->!= -
__lt__(self, other)---->< -
__gt__(self, other)---->> -
__le__(self, other)----><= -
__ge__(self, other)---->>=
P.S.
- 比较的时候,优先使用
__gt__(),__lt__(),__eq__(),如果找不到则使用__cmp__()。 -
@total_ordering可以在重载__eq__和随意一个其他比较(__gt__等等)的情况下补全其他比较。可以节省大量时间
实例
比较两个字符串长度
class Word(str):
'''单词类,比较定义是基于单词长度的'''
def __new__(cls, word):
# 注意,我们使用了__new__,这是因为str是一个不可变类型,
# 所以我们必须更早地初始化它(在创建时)
if ' ' in word:
word = word[:word.index(' ')] # 截断至第一个空格处
print(f'单词内含有空格,截断到{word}')
return str.__new__(cls, word)
def __gt__(self, other):
return len(self) > len(other)
def __lt__(self, other):
return len(self) < len(other)
def __ge__(self, other):
return len(self) >= len(other)
def __le__(self, other):
return len(self) <= len(other)
def __eq__(self, other):
return len(self) == len(other)
print('abc'<'cbe')
print(Word('ab c') == Word('cb'))
数字操作符
类行为的描述
-
__str__(self)
当你定义的类中一个实例调用了str(),用于给它定义行为 -
__repr__(self)
当你定义的类中一个实例调用了repr(),用于给它定义行为。str()和repr()主要的区别在于它的阅读对象。repr()产生的输出主要为计算机可读(在很多情况下,这甚至可能是一些有效的 Python 代码),而str()则是为了让人类可读。 -
__unicode__(self)
当你定义的类中一个实例调用了unicode(),用于给它定义行为。unicode()像是str(),只不过它返回一个 unicode 字符串。 警惕!如果用户用你的类中的一个实例调用了str(),而你仅定义了__unicode__(),那它是不会工作的。 以防万一,你应当总是定义好__str__(),哪怕用户不会使用 unicode -
__hash__(self)
当你定义的类中一个实例调用了hash(),用于给它定义行为。 它必须返回一个整型,而且它的结果是用于来在字典中作为快速键比对。 -
__nonzero__(self)
当你定义的类中一个实例调用了bool(),用于给它定义行为。 返回True或False,取决于你是否考虑一个实例是True或False的。
属性访问控制
调用
Reference
[1] A Guide to Python's Magic Methods - Rafe Kettler