这篇文章主要介绍了Python的魔术方法
参考文章:
Python
魔术方法指南
魔术方法,顾名思义是一种可以给对象(类)增加魔法的特殊方法,它们的表示方法一般是用双下划线包围(如__init__
)
对象实例化
1 2 3 4 5 6 7 8 9 10 11 12
| from os.path import join
class FileObject: '''给文件对象进行包装从而确认在删除时文件流关闭'''
def __init__(self, filepath='~', filename='sample.txt'): self.file = open(join(filepath, filename), 'r+')
def __del__(self): self.file.close() del self.file
|
__new__(cls, [...])
:
在一个对象实例化调用的第一个方法,第一个参数是类,剩下的参数传递给__init__
__init__(self, [...])
:
类的初始化方法。当构造函数被调用的时候的任何参数够会传给它
__del__(self)
:
__new__
和__init__
为对象的构造器,__del__
为对象的析构器。当一个对象进行过垃圾回收时候的行为就是这个方法。当一个对象在删除的时候需要更多的清洁工作,就需要使用这个方法
比较
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Word(str): '''存储单词的类,定义比较单词的几种方法'''
def __new__(cls, word): if ' ' in word: print("Value contains spaces. Truncating to first space.") word = word[:word.index(' ')] 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)
|
__cmp__(self, other)
:
用于比较的魔术方法,实现了所有的比较符号。如果self
<
other
返回一个负数;如果self
==
other
返回0;如果self
>
other
返回正数。一般情况下是分别定义每一个比较符号。如果想实现所有的比较符号,就需要调用这个方法。
__eq__(self, other)
: 等号
__ne__(self, other)
: 不等号
__lt__(self, other)
: 小于
__gt__(self, other)
: 大于
__le__(self, other)
: 小于等于
__ge__(self, other)
: 大于等于
一元操作符和函数
__pos__(self)
:实现正号的特性
__neg__(self)
:实现负号的特性
__abs__(self)
:abs, 绝对值
__invert__(self)
:实现~的特性
普通算数操作符
__add__(self, other)
: 实现加法
__sub__(self, other)
: 实现减法
__mul__(self, other)
: 实现乘法
__floordiv__(self, other)
: 实现整除法
__div__(self, other)
: 实现除法
__mod__(self, other)
: 实现取模
__pow__(self, other)
: 实现指数
__lshift__(self, other)
: 实现<<
__rshift__(self, other)
: 实现>>
__and__(self, other)
: 实现&
__or__(self, other)
: 实现|
__xor__(self, other)
: 实现^
其他
1 2 3 4 5 6 7 8
| def __setattr__(self, name, value): self.name = value
def __setattr__(self, name, value): self.__dict__[name] = value
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| class AccessCounter: '''一个包含计数器的控制权限的类每当值被改变时计数器会加一'''
def __init__(self, val): super(AccessCounter, self).__setattr__('counter', 0) super(AccessCounter, self).__setattr__('value', val)
def __setattr__(self, name, value): if name == 'value': super(AccessCounter, self).__setattr__('counter', self.counter + 1) super(AccessCounter, self).__setattr__(name, value)
def __delattr__(self, name): if name == 'value': super(AccessCounter, self).__setattr__('counter', self.counter + 1) super(AccessCounter, self).__delattr__(name)]
|
__str__(self)
: 返回值,人类可读
__repr__(self)
: 返回值,机器可读
__unicode__(self)
: 返回unicode()
__hash__(self)
: hash()返回一个整形
__nonzero__(self)
: bool()返回的值
__getattr__(self, name)
:
当用户试图获取一个不存在(或不建议的属性)的属性时,给出一些警告
__setattr__(self, name, value)
:
无论属性是否存在,都允许你定义对属性的赋值行为
__delattr__(self, name)
: 删除一个属性
封装附加魔术方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| class FunctionalList: '''一个封装了一些附加魔术方法比如 head, tail, init, last, drop, 和take的列表类。 '''
def __init__(self, values=None): if values is None: self.values = [] else: self.values = values
def __len__(self): return len(self.values)
def __getitem__(self, key): return self.values[key]
def __setitem__(self, key, value): self.values[key] = value
def __delitem__(self, key): del self.values[key]
def __iter__(self): return iter(self.values)
def __reversed__(self): return reversed(self.values)
def append(self, value): self.values.append(value) def head(self): return self.values[0] def tail(self): return self.values[1:] def init(self): return self.values[:-1] def last(self): return self.values[-1] def drop(self, n): return self.values[n:] def take(self, n): return self.values[:n]
|
反射
__instancecheck__(self, instance)
:
检查一个实例是否为定义类的实例
__subclasscheck__(self, subclass)
:
检查一个类是否为定义类的子类
更改状态
__call__(self, [...])
:
经常改变状态的时候,调用这个方法是一种直接和优雅的方法
1 2 3 4 5 6 7 8 9 10
| class Entity: '''调用实体来改变实体的位置。'''
def __init__(self, size, x, y): self.x, self.y = x, y self.size = size
def __call__(self, x, y): '''改变实体的位置''' self.x, self.y = x, y
|
会话管理
使用with语句来调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Closer: '''通过with语句和一个close方法来关闭一个对象的会话管理器'''
def __init__(self, obj): self.obj = obj
def __enter__(self): return self.obj
def __exit__(self, exception_type, exception_val, trace): try: self.obj.close() except AttributeError: print('Not closable.') return True
|
__slots__
限制class的属性,但不限制class的子类的属性,除非子类也使用__slots__
例子:
使用__slots__
会比不使用,减少40%~50%的内存
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class MyClass(object): def __init__(self, name, identifier): self.name = name self.identifier = identifier self.set_up()
class MyClass(object): __slots__ = ['name', 'identifier'] def __init__(self, name, identifier): self.name = name self.identifier = identifier self.set_up()
|