Python中operator模块提供了一套与 Python 的内置运算符对应的高效率函数。
不仅对应内置运算符,还可以获取方法。可优化涉及回调函数的运算性能,比lambda、Python函数的开销小、速度快。
python
import operator
[x for x in dir(operator) if not x.startswith('_')]
# 结果:
['abs', 'add', 'and_', 'attrgetter', 'call', 'concat', 'contains', 'countOf',
'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand', 'iconcat',
'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul', 'index', 'indexOf', 'inv',
'invert', 'ior', 'ipow', 'irshift', 'is_', 'is_not', 'isub', 'itemgetter',
'itruediv', 'ixor', 'le', 'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller',
'mod', 'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift', 'setitem',
'sub', 'truediv', 'truth', 'xor']
from operator import *
1、数学运算
注意:数字不可变。因此,原地运算符,会被计算,但不会被赋值,不改变原变量的数字。
|----------------|-----------|----------------------------------------------------------------------------------------------------------|------------------------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| add(a,b) | a + b | 相加 | add(2,3) 结果:5 |
| iadd(a,b) | a += b | 相加,原地运算符 | a = 5 iadd(a,3) 结果:8 a 结果:5 |
| sub(a,b) | a - b | 相减 | sub(2,3) 结果:-1 |
| isub(a,b) | a -= b | 相减,原地运算符 | |
| mul(a,b) | a * b | 相乘 | mul(2,3) 结果:6 |
| imul(a,b) | a *= b | 相乘,原地运算符 | |
| truediv(a,b) | a / b | 相除 | truediv(2,3) 结果:0.6666666666666666 |
| itruediv(a,b) | a /= b | 相除,原地运算符 | |
| floordiv(a,b) | a // b | 相除取整数 | floordiv(2,3) 结果:0 |
| ifloordiv(a,b) | a //= b | 相除取整数,原地运算符 | |
| mod(a,b) | a % b | 相除取余数 | mod(2,3) 结果:2 |
| imod(a,b) | a %= b | 相除取余数,原地运算符 | |
| pow(a,b) | a ** b | 幂, | pow(2,3) 结果:8 |
| ipow(a,b) | a **= b | 幂,原地运算符 | |
| matmul(a,b) | a @ b | 矩阵乘法 | |
| imatmul(a,b) | a @= b | 矩阵乘法,原地运算符 | |
| neg(a) | - a | 算术取反 | neg(1) 结果:-1 |
| pos(a) | + a | 取正 | pos(-1) 结果:-1 |
| abs(a) | | 绝对值 | abs(-1) 结果:1 |
|-------------------|-----------|---------------|--------------------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| inv(a), invert(a) | | 按位取反,等价于 ~ a | ① inv(2) 结果:-3 invert(2) 结果:-3 |
| lshift(a,b) | a << b | 左移 | ② lshift(2,3) 结果:16 |
| ilshift(a,b) | a <<= b | 左移,原地运算符 | |
| rshift(a,b) | a >> b | 右移 | rshift(2,3) 结果:0 |
| irshift(a,b) | a >>= b | 右移,原地运算符 | |
| and_(a,b) | a & b | 按位与 | ③ and_(2,3) 结果:2 |
| iand(a,b) | a &= b | 按位与,原地运算符 | |
| or_(a,b) | a | b | 按位或 | or_(2,3) 结果:3 |
| ior(a,b) | 即 a |= b | 按位或,原地运算符 | |
| xor(a,b) | a ^ b | 按位异或 | xor(2,3) 结果:1 |
| ixor(a,b) | a ^= b | 按位异或,原地运算符 | |
注解:(假设8位二进制,最高位为符号位,负数用补码形式存储)
① 按位取反。inv(2) 结果:-3
2(二进制:00000010):按位取反,则11111101(原码10000011,十进制:-3)。
② 左移。lshift(2,3) 结果:16
2(二进制:00000010):左移3位,则00010000(十进制:16)。
③ 按位与。and_(2,3) 结果:2
2(二进制:00000010),3(二进制:00000011):按位与,则00000010(十进制:2)。
按位与:1 & 1 = 1,1 & 0 = 0,0 & 0 = 0
按位或:1 | 1 = 1,1 | 0 = 1,0 | 0 = 0
按位异或:1 ^ 1 = 0,1 ^ 0 = 1,0 ^ 0 = 0
2、比较运算
|---------|---------|------|------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| lt(a,b) | a < b | 小于 | lt(2,3) 结果:True |
| le(a,b) | a <= b | 小于等于 | le(2,3) 结果:True |
| gt(a,b) | a > b | 大于 | gt(2,3) 结果:False |
| ge(a,b) | a >= b | 大于等于 | ge(2,3) 结果:False |
| eq(a,b) | a == b | 等于 | eq(2,3) 结果:False |
| ne(a,b) | a != b | 不等于 | ne(2,3) 结果:True |
lt:less than 小于
le:less than or equal to 小于等于
gt:greater than 大于
ge:greater than or equal to 大于等于
eq:equal to 等于
ne:not equal to 不等于
3、逻辑运算
|-------------|------------|----------------------------|-------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| truth(a) | a | 真值测试。a 为真,返回True,否则返回False | truth(0) 结果:False |
| not_(a) | not a | 逻辑取反 | not_(0) 结果:True |
| is_(a,b) | a is b | a 是 b | |
| is_not(a,b) | a is not b | a 不是 b | |
4、序列运算
注意:原地运算符中被赋值的序列需是可变的。若不可变的序列(字符串、元组),会计算但不会赋值,即不改变原序列。
|----------------|------------|----------------------------|----------------------------------------------------------------------------------------------------------------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| concat(a,b) | a + b | 序列a、b,拼接 | concat([1],[2,3]) 结果:[1, 2, 3] |
| iconcat(a,b) | a += b | 序列a、b,拼接,原地运算符 | |
| contains(a,b) | b in a | 序列a 中包含元素b | contains("hello","e") 结果:True |
| countOf(a,b) | | 序列a 中元素b出现的次数 | countOf("hello","l") 结果:2 |
| indexOf(a,b) | | 序列a 中元素b第一次出现的位置。若不存在,则报错 | indexOf("hello","o") 结果:4 |
| getitem(a,b) | a[b] | 序列a 中获取下标/切片b对应的元素 | getitem("hello",1) 结果:'e' getitem("hello",slice(1,3)) 结果:'el' |
| setitem(a,b,c) | a[b]=c | 可变序列a 中赋值下标/切片b对应的元素为c | a = [1,2,3]; setitem(a,2,"w"); a 结果:[1, 2, 'w'] a = [1,2,3]; setitem(a,slice(1,3),["w","y"]); a 结果:[1, 'w', 'y'] |
| delitem(a,b) | del a[b] | 可变序列a 中删除下标/切片b对应的元素 | a = [1,2,3]; delitem(a,1); a 结果:[1, 3] a = [1,2,3]; delitem(a,slice(1,3)); a 结果:[1] |
| length_hint(a) | len(a) | 序列a的长度 | length_hint("hello") 结果:5 |
add 和 iadd 也可以拼接序列,和concat结果相同。
|-----------|--------|----------------|-----------------------------------|
| 函数 | 对应运算符 | 描述 | 举例 |
| add(a,b) | a + b | 序列a、b,拼接 | add([1],[2,3]) 结果:[1, 2, 3] |
| iadd(a,b) | a += b | 序列a、b,拼接,原地运算符 | |
5、3.11 新版功能
提供了快速访问对象的属性、获取序列元素、方法调用。
适合作为快速提取器(map, sorted, itertools**.**groupby等)的参数。
(5-1)attrgetter 【访问对象的属性】
- attrgetter(属性)(对象):对象**.**属性,即获取对象的属性。
- attrgetter(属性1, 属性2 ...)(对象):(对象**.** 属性1, 对象**.**属性2,...),即获取对象的多个属性,返回元组形式。
python
from operator import *
class People(object):
def __init__(self,name,age):
self.name = name
self.age = age
p1 = People("Tom",18)
p2 = People("Jack",25)
get_age = attrgetter("age")
get_age(p1) # 结果:18
get_age(p2) # 结果:25
# 相当于
p1.age # 结果:18
p2.age # 结果:25
get_all = attrgetter("name","age")
get_all(p1) # 结果:('Tom', 18)
get_all(p2) # 结果:('Jack', 25)
# 相当于
p1.name,p1.age # 结果:('Tom', 18)
p2.name,p2.age # 结果:('Jack', 25)
# attrgetter 比 lambda 速度快
list(map(get_age,[p1,p2])) # 结果:[18, 25]
# 相当于
list(map(lambda x:x.age,[p1,p2])) # 结果:[18, 25]
list(map(get_all,[p1,p2])) # 结果:[('Tom', 18), ('Jack', 25)]
# 相当于
list(map(lambda x:(x.name,x.age),[p1,p2])) # 结果:[('Tom', 18), ('Jack', 25)]
(5-2)itemgetter 【获取序列的元素】
- itemgetter(下标)(序列):序列[下标],即获取序列中下标对应的元素。
- itemgetter(slice(起始下标, 结束下标))(序列): 序列[起始下标**:**结束下标],通过切片获取序列中的元素。
- itemgetter(下标1, 下标2, ...)(序列):(序列[下标1],序列[下标2],...),即获取序列中多个下标对应的元素,返回元组形式。
python
from operator import *
a = "hello"
itemgetter(1)(a) # 结果:'e'
itemgetter(slice(1,4))(a) # 结果:'ell'
itemgetter(1,2,4)(a) # 结果:('e', 'l', 'o')
- itemgetter(键)(字典):字典[键],通过键获取字典中的值。
- itemgetter(键1, 键2,...)(字典):(字典[键1], 字典[键2], ...),通过多个键获取字典中的值,返回元组形式。
python
from operator import *
d = {'一季度':20,'二季度':50,'三季度':15,'四季度':35}
itemgetter('二季度')(d) # 结果:50
itemgetter('二季度','四季度')(d) # 结果:(50, 35)
在sorted、map等使用时,itemgetter 比 lambda 速度快。
python
from operator import *
b = [("一季度",20),("二季度",50),("三季度",15),("四季度",35)]
# 按元组中下标为1的元素大小排序
sorted(b,key=itemgetter(1)) # 结果:[('三季度', 15), ('一季度', 20), ('四季度', 35), ('二季度', 50)]
# 相当于
sorted(b,key=lambda x:x[1]) # 结果:[('三季度', 15), ('一季度', 20), ('四季度', 35), ('二季度', 50)]
# 获取元组中下标为1的元素
list(map(itemgetter(1),b)) # 结果:[20, 50, 15, 35]
# 相当于
list(map(lambda x:x[1],b)) # 结果:[20, 50, 15, 35]
(5-3)methodcaller 【调用对象的方法】
- methodcaller(方法)(对象):对象**.**方法(),即调用对象的方法。
- methodcaller(方法, 参数1, 参数2 ...)(对象):对象**.**方法(参数1, 参数2,...),即调用对象的方法,并传递参数。
python
from operator import *
class People(object):
def __init__(self,name,age):
self.name = name
self.age = age
def introduce(self):
return f"我是{self.name}"
p1 = People("Tom",18)
intro = methodcaller("introduce")
intro(p1) # 结果:'我是Tom'
# 相当于
p1.introduce() # 结果:'我是Tom'