![](/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.