簡體   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