1. operator内置操作符的函数接口
使用迭代器编程时,有时需要为简单的表达式创建小函数。有些情况下,尽管这确实可以被实现为lambda函数,但某些操作根本不需要新函数。operator模块定义了一些函数,可以对应标准对象API中内置的算术、比较和其他操作。
1.1 逻辑操作
有些函数可以用来确定一个值的相应布尔值,将其取反以创建相反的布尔值,以及比较对象以查看它们是否相等。
from operator import * a = -1 b = 5 print('a =', a) print('b =', b) print() print('not_(a) :', not_(a)) print('truth(a) :', truth(a)) print('is_(a, b) :', is_(a, b)) print('is_not(a, b):', is_not(a, b))
not_()后面有下划线,因为not是一个Python关键字。在if语句中测试一个表达式或将一个表达式转换为一个bool时会使用某种逻辑,truth()会应用与之相同的逻辑。is_()实现了is关键字使用的检查,is_not()完成同样的测试,不过返回相反的答案。
1.2 比较操作符
支持所有富比较操作符。
from operator import * a = 1 b = 5.0 print('a =', a) print('b =', b) for func in (lt, le, eq, ne, ge, gt): print('{}(a, b): {}'.format(func.__name__, func(a, b)))
这些函数等价于使用<、<=、==、>=、和>的表达式语法。
1.3 算术操作符
也支持处理数字值的算术操作符。
from operator import * a = -1 b = 5.0 c = 2 d = 6 print('a =', a) print('b =', b) print('c =', c) print('d =', d) print(' Positive/Negative:') print('abs(a):', abs(a)) print('neg(a):', neg(a)) print('neg(b):', neg(b)) print('pos(a):', pos(a)) print('pos(b):', pos(b)) print(' Arithmetic:') print('add(a, b) :', add(a, b)) print('floordiv(a, b):', floordiv(a, b)) print('floordiv(d, c):', floordiv(d, c)) print('mod(a, b) :', mod(a, b)) print('mul(a, b) :', mul(a, b)) print('pow(c, d) :', pow(c, d)) print('sub(b, a) :', sub(b, a)) print('truediv(a, b) :', truediv(a, b)) print('truediv(d, c) :', truediv(d, c)) print(' Bitwise:') print('and_(c, d) :', and_(c, d)) print('invert(c) :', invert(c)) print('lshift(c, d):', lshift(c, d)) print('or_(c, d) :', or_(c, d)) print('rshift(d, c):', rshift(d, c)) print('xor(c, d) :', xor(c, d))
提供了两个不同的出发操作符:floordiv()(Python 3.0版本之前实现的整数除法)和truediv()(浮点数除法)。
1.4 系列操作符
处理系列的操作符可以分为4组:建立序列、搜索元素、访问内容以及从序列删除元素。
from operator import * a = [1, 2, 3] b = ['a', 'b', 'c'] print('a =', a) print('b =', b) print(' Constructive:') print(' concat(a, b):', concat(a, b)) print(' Searching:') print(' contains(a, 1) :', contains(a, 1)) print(' contains(b, "d"):', contains(b, "d")) print(' countOf(a, 1) :', countOf(a, 1)) print(' countOf(b, "d") :', countOf(b, "d")) print(' indexOf(a, 5) :', indexOf(a, 1)) print(' Access Items:') print(' getitem(b, 1) :', getitem(b, 1)) print(' getitem(b, slice(1, 3)) :', getitem(b, slice(1, 3))) print(' setitem(b, 1, "d") :', end=' ') setitem(b, 1, "d") print(b) print(' setitem(a, slice(1, 3), [4, 5]):', end=' ') setitem(a, slice(1, 3), [4, 5]) print(a) print(' Destructive:') print(' delitem(b, 1) :', end=' ') delitem(b, 1) print(b) print(' delitem(a, slice(1, 3)):', end=' ') delitem(a, slice(1, 3)) print(a)
其中一些操作(如setitem()和delitem())会原地修改序列,而且不返回任何值。
1.5 原地操作符
除了标准操作符,很多对象类型还通过一些特殊操作符(如+=)支持”原地”修改。这些原地修改也有相应的等价函数。
from operator import * a = -1 b = 5.0 c = [1, 2, 3] d = ['a', 'b', 'c'] print('a =', a) print('b =', b) print('c =', c) print('d =', d) print() a = iadd(a, b) print('a = iadd(a, b) =>', a) print() c = iconcat(c, d) print('c = iconcat(c, d) =>', c)
1.6 属性和元素“获取方法”
operator模块最特别的特性之一是获取方法(getter)的概念。获取方法是运行时构造的一些callable对象,用来获取对象的属性或序列的内容。获取方法在处理迭代器或生成器序列时特别有用,因为获取方法引入的开销会大大低于lambda或Python函数的开销。
from operator import * class MyObj: """example class for attrgetter""" def __init__(self, arg): super().__init__() self.arg = arg def __repr__(self): return 'MyObj({})'.format(self.arg) l = [MyObj(i) for i in range(5)] print('objects :', l) # Extract the 'arg' value from each object g = attrgetter('arg') vals = [g(i) for i in l] print('arg values:', vals) # Sort using arg l.reverse() print('reversed :', l) print('sorted :', sorted(l, key=g))
属性获取方法类似于lambda x,n='attrname':getattr(x,n)。
元素获取方法类似于lambda x,y=5:x[y]。
from operator import * l = [dict(val=-1 * i) for i in range(4)] print('Dictionaries:') print(' original:', l) g = itemgetter('val') vals = [g(i) for i in l] print(' values:', vals) print(' sorted:', sorted(l, key=g)) print() l = [(i, i * -2) for i in range(4)] print(' Tuples:') print(' original:', l) g = itemgetter(1) vals = [g(i) for i in l] print(' values:', vals) print(' sorted:', sorted(l, key=g))
除了序列,元素获取方法还适用于映射。
1.7 结合操作符和定制类
operator模块中的函数完成操作符时会使用标准Python接口,所以它们不仅适用于内置类型,也适用于用户定义的类。
from operator import * class MyObj: """Example for operator overloading""" def __init__(self, val): super(MyObj, self).__init__() self.val = val def __str__(self): return 'MyObj({})'.format(self.val) def __lt__(self, other): """compare for less-than""" print('Testing {} < {}'.format(self, other)) return self.val < other.val def __add__(self, other): """add values""" print('Adding {} + {}'.format(self, other)) return MyObj(self.val + other.val) a = MyObj(1) b = MyObj(2) print('Comparison:') print(lt(a, b)) print(' Arithmetic:') print(add(a, b))