![](/img/trans.png)
[英]Overload arithmetic & comparison operators for element-wise list operations in Python
[英]Overload all arithmetic operators in Python
假设我构建了一个基本上代表数字加上一些奇特东西的类。 在任何算术/数学运算中,该类的实例应该像数字一样。
我可以重载该类中的所有数字运算符,但是没有更短的解决方案吗?
该课程基本上如下:
class MyFancyNumber:
def __init__(self, num, info):
self.num = num # the actual number
self.info = info # some more info, or other data
def doFancyStuff(self):
# does something fancy
def __add__(self, other):
return self.num + other # same pattern for all numeric functions
那这个呢?
class MyFancyNumber(int):
def __new__(cls, num, info=None):
return super(MyFancyNumber, cls).__new__(cls, num)
def __init__(self, num, info=None):
self.num = num
self.info = info
>>> MyFancyNumber(5)
5
>>> MyFancyNumber(5) + 2
7
>>> MyFancyNumber(5) / 4
1
>>> MyFancyNumber(5) * 0.5
2.5
>>> MyFancyNumber(5) - 7
-2
>>> MyFancyNumber(5, 'info').info
'info'
我想根据上述情况,你可以弄清楚你需要什么。
我并不认为这是特别惯用的,但......
假设所有函数定义的行为相同,例如“只调用self.num
类的基本行为并将所有非自身参数应用于它”,那么您可以循环遍历要定义的所有函数名称,并创建每一个都使用setattr
。 例:
class MyFancyNumber(object):
def __init__(self, num, info):
self.num = num
self.info = info
def __repr__(self):
return "MyFancyNumber({}, {})".format(repr(self.num), repr(self.info))
def make_func(name):
return lambda self, *args: MyFancyNumber(getattr(self.num, name)(*args), self.info)
for name in ["__add__", "__sub__", "__mul__", "__div__", "__invert__", "__neg__", "__pos__"]:
setattr(MyFancyNumber, name, make_func(name))
x = MyFancyNumber(50, "hello")
print(x + 10)
print(x - 10)
print(x * 10)
print(x / 10)
print(~x)
print(-x)
print(+x)
结果:
MyFancyNumber(60, 'hello')
MyFancyNumber(40, 'hello')
MyFancyNumber(500, 'hello')
MyFancyNumber(5, 'hello')
MyFancyNumber(-51, 'hello')
MyFancyNumber(-50, 'hello')
MyFancyNumber(50, 'hello')
编辑:我不确定你是否希望算术的结果是MyFancyNumber或常规内置数值类型,但无论哪种方式,实现都非常相似:
class MyFancyNumber(object):
def __init__(self, num, info):
self.num = num
self.info = info
def __repr__(self):
return "MyFancyNumber({}, {})".format(repr(self.num), repr(self.info))
def make_func(name):
return lambda self, *args: getattr(self.num, name)(*args)
for name in ["__add__", "__sub__", "__mul__", "__div__", "__invert__", "__neg__", "__pos__"]:
setattr(MyFancyNumber, name, make_func(name))
x = MyFancyNumber(50, "hello")
print(x + 10)
print(x - 10)
print(x * 10)
print(x / 10)
print(~x)
print(-x)
print(+x)
结果:
60
40
500
5
-51
-50
50
不,你必须定义所有算术运算符,否则Python将如何知道如何处理它们。 不要忘记你还需要像__radd__
这样的反向运算符。
您编写的代码也返回x+1
的int
。 你的意思是,或者你想要添加一个花哨的数字来返回另一个花哨的数字?
你可以只是继承int
或float
。 然后你不必重新实现运算符,但是每当你操作一个值时你仍然会失去特殊性质。
更好的解决方案就是在属性中使用数值,并在需要时明确转换为数字。 您可以使用__int__()
和__float__()
来实现转换。
如果您真的想模拟数字类型,那么文档将介绍您需要执行的操作:对于Python 3.x https://docs.python.org/3/reference/datamodel.html?highlight= int #muting-digital-类型或Python 2.x https://docs.python.org/2/reference/datamodel.html?highlight= int #emulating-numeric-types
只要你在init中传递一个参数,这对我来说就适用于python 2.7。 可悲的是,不知道为什么它有效。
class MyFancyNumber(int):
def __init__(self, num):
self.num = num # the actual number
def add_info(self,info):
self.info = info ## Add the info separately
def doFancyStuff(self):
# does something fancy
print MyFancyNumber(5)+5
用法
f = MyFancyNumber(2)
f.add_info(info)
f+4 ## returns 6
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.