Python重载运算符
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python重载运算符相关的知识,希望对你有一定的参考价值。
#
#例子13-3 一元运算符+得到一个新Counter实例,但是没有零值和负值计数器
from collections import Counter
ct = Counter(‘abracadabra‘)
print(ct) #Counter({‘a‘: 5, ‘r‘: 2, ‘b‘: 2, ‘c‘: 1, ‘d‘: 1})
ct[‘r‘] = -3
ct[‘d‘] = 0
print(ct) #Counter({‘a‘: 5, ‘b‘: 2, ‘c‘: 1, ‘d‘: 0, ‘r‘: -3})
print(+ct) #Counter({‘a‘: 5, ‘b‘: 2, ‘c‘: 1})
import itertools
a = (1,2,3)
b = [4,5]
d = itertools.zip_longest(a,b,fillvalue=0.0)
#以下是Vector
from array import array
import reprlib
import math
import numbers
import functools
import operator
import itertools
class Vector:
typecode = ‘d‘
def __init__(self, components):
self._components = array(self.typecode, components)
def __iter__(self):
return iter(self._components)
def __repr__(self):
components = reprlib.repr(self._components)
components = components[components.find(‘[‘):-1]
return ‘Vector({})‘.format(components)
def __str__(self):
return str(tuple(self))
def __bytes__(self):
return (bytes([ord(self.typecode)]) +
bytes(self._components))
def __eq__(self, other):
return (len(self) == len(other) and
all(a == b for a, b in zip(self, other)))
def __hash__(self):
hashes = (hash(x) for x in self)
return functools.reduce(operator.xor, hashes, 0)
def __abs__(self):
return math.sqrt(sum(x * x for x in self))
def __bool__(self):
return bool(abs(self))
def __len__(self):
return len(self._components)
def __getitem__(self, index):
cls = type(self)
if isinstance(index, slice):
return cls(self._components[index])
elif isinstance(index, numbers.Integral):
return self._components[index]
else:
msg = ‘{.__name__} indices must be integers‘
raise TypeError(msg.format(cls))
shortcut_names = ‘xyzt‘
def __getattr__(self, name):
cls = type(self)
if len(name) == 1:
pos = cls.shortcut_names.find(name)
if 0 <= pos < len(self._components):
return self._components[pos]
msg = ‘{.__name__!r} object has no attribute {!r}‘
raise AttributeError(msg.format(cls, name))
def angle(self, n): # <2>
r = math.sqrt(sum(x * x for x in self[n:]))
a = math.atan2(r, self[n-1])
if (n == len(self) - 1) and (self[-1] < 0):
return math.pi * 2 - a
else:
return a
def angles(self): # <3>
return (self.angle(n) for n in range(1, len(self)))
def __format__(self, fmt_spec=‘‘):
if fmt_spec.endswith(‘h‘): # hyperspherical coordinates
fmt_spec = fmt_spec[:-1]
coords = itertools.chain([abs(self)],
self.angles()) # <4>
outer_fmt = ‘<{}>‘ # <5>
else:
coords = self
outer_fmt = ‘({})‘ # <6>
components = (format(c, fmt_spec) for c in coords) # <7>
return outer_fmt.format(‘, ‘.join(components)) # <8>
@classmethod
def frombytes(cls, octets):
typecode = chr(octets[0])
memv = memoryview(octets[1:]).cast(typecode)
return cls(memv)
‘‘‘
def __add__(self, other):
pairs = itertools.zip_longest(self,other,fillvalue=0.0)
return Vector(a+b for a,b in pairs)
#print((3,40) + v1) #TypeError: can only concatenate tuple (not "Vector") to tuple 【解析】如果左操作数是Vector之外的对象,则无法处理
#...为了支持涉及不同类型的运算,python为中缀运算符特殊方法提供了特殊的分派机制。对表达式a+b来说,解释器会执行以下几步操作
#...(1)如果a有__add__方法,而且返回值不是NotImplemented,调用a.__add__(b),然后返回结果
#...(2)如果a没有__add__方法,或者调用__add__方法返回NotImplemented,检查b有没有__radd__方法,如果有,而且没有返回NotImplemented,调用b.__radd__(a),然后返回结果
#...(3)如果前两者条件都不满足,抛出TypeError,并在错误消息中指明操作数类型不支持
#[注意]别把NotImplemented NotImplementedError搞混了。前者是特殊的单例值,如果中缀运算符特殊方法不能处理给定的操作数,那么要把它返回给解释器。后者是一种异常,抽象类中的占位方法把它抛出(raise),提醒子类必须覆盖
‘‘‘
def __add__(self, other):
pairs = itertools.zip_longest(self,other,fillvalue=0.0)
return Vector(a+b for a,b in pairs)
def __radd__(self, other):
return self + other #__radd__通常就这么简单:直接调用适当的运算符,在这里就委托__add__。任何可交换的运算符都能这么左。处理数字和向量时,+可以交换,但是拼接序列时不行
#例子13-8 Vector.__add__方法的操作数钥要是可迭代对象
v2 = Vector([3,4,5])
#print(v2 + 1) #TypeError: zip_longest argument #2 must support iteration
#例子13-9 这个加法的操作数应该是可迭代的数值对象
print(v2 + ‘ABC‘) #TypeError: unsupported operand type(s) for +: ‘float‘ and ‘str‘
#例子13-10 针对13-8 13-9 需要再进行优化,即有错误要抛出
v1 = Vector([3,4,5])
print(v1 + (10,20)) #(13.0, 24.0, 5.0)
以上是关于Python重载运算符的主要内容,如果未能解决你的问题,请参考以下文章