繁体   English   中英

在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+1int 你的意思是,或者你想要添加一个花哨的数字来返回另一个花哨的数字?

你可以只是继承intfloat 然后你不必重新实现运算符,但是每当你操作一个值时你仍然会失去特殊性质。

更好的解决方案就是在属性中使用数值,并在需要时明确转换为数字。 您可以使用__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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM