我目前正在实现一个可以处理与物理单位相关的数字数据的类。
我想实现一种计算实例平方根的方法。假设您有一个具有属性value和name的类的实例:
from math import sqrt
class Foo:
def __init__(self, value, name)
self.value = value
self.name = name
def __sqrt__(self):
return sqrt(self.value)
我想实现类似于 add (自身,其他)这样的魔术方法的功能,当我调用math.sqrt()函数时,该方法将计算平方根:
A = Foo(4, "meter")
root = math.sqrt(A)
应返回调用A. sqrt ()函数。
答案 0 :(得分:3)
您不能不将math.sqrt
重新分配给自定义功能。如果要允许将Foo
强制转换为int
或float
,则可以实现__int__
和__float__
并强制转换,然后调用math.sqrt
:< / p>
class Foo:
def __init__(self, value, name)
self.value = value
self.name = name
def __float__(self):
return float(self.value)
def __int__(self):
return int(self.value)
A = Foo(4, "meter")
root = math.sqrt(float(A))
编辑:根据下面的评论,由于数学模块的实现方式,如果math.sqrt(A)
实现Foo
,似乎可以直接调用__float__
。我仍然宁愿明确而不是隐含。
答案 1 :(得分:2)
没有简单/开箱即用的方式连接math.sqrt
来呼叫Foo.__sqrt__
。
只需在sqrt
中实现Foo
:
class Foo:
...
def sqrt(self):
return sqrt(self.value)
A = Foo(4, "meter")
root = A.sqrt()
如果出于某种原因您坚持认为它可以被黑客入侵,但我看不出您为什么要这样做:
from math import sqrt
class Foo:
def __init__(self, value, name):
self.value = value
self.name = name
def __sqrt__(self):
return sqrt(self.value)
orig_sqrt = sqrt
def my_sqrt(value):
if isinstance(value, Foo):
return orig_sqrt(value.value)
# or return value.__sqrt__()
else:
return orig_sqrt(value)
sqrt = my_sqrt
A = Foo(4, "meter")
print(sqrt(A))
# 2.0
print(sqrt(4))
# 2.0
答案 2 :(得分:0)
sqrt
没有像其他数字函数那样神奇的方法。
您可以在类中定义一个sqrt
方法,如另一个答案所指出。
您还可以做的是创建自己的sqrt
函数,如果传递了该类的实例,则会对该类的属性调用math.sqrt
。
import math
def sqrt(x):
if isinstance(x, Foo):
return math.sqrt(x.value)
return math.sqrt(x)
但是,这是很棘手的,除非您出于某种原因绝对需要在混合类型的容器上不加选择地调用sqrt
,否则不建议这样做。