2

我想为尊重from __future__ import division声明的数字制作一个特殊的容器。如果我from __future__ import division在容器定义中设置,那么一切都被迫使用truediv。相反,如果我以另一种方式做,那么一切都会使用整数除法。有什么方法可以检查正在进行哪种划分?(在 Python 3 中,这是一个有争议的问题,仅适用于 2.x)

例如,这里是file1.py

class MySpecialContainer(object):
    def __init__(self, value):
        self.value = value
    def div(self, other):
        new_value = self.value / other
        return self.__class__(new_value)
    def truediv(self, other):
        new_value = self.value * 1.0 / other
        return self.__class__(new_value)
    __div__ = div
    __truediv__ = truediv

然后在file2.py

from __future__ import division
from file1 import MySpecialContainer
obj = MySpecialContainer(5)
print obj.value # 5
print obj.div(2).value # 2
print 5 / 2 # 2.5

而显式使用除法运算符会导致__truediv__使用

print MySpecialContainer(5) / 2 # 2.5

有什么特殊的方法可以检测到这个问题并避免这个问题,还是我需要对我的容器做出明确的选择?

编辑:这显然是一个非常简单的例子,但我希望以更复杂的方式做到这一点(即,改变 pandas 以添加一个 truediv 方法并将 div 更改为对环境敏感)。特别是,我想在导入时动态执行此操作,根据导入文件进行更改(我猜这会引发关于首先导入哪个文件等的一系列问题......)

4

1 回答 1

4

这里的问题是该__future__语句分别适用于每个模块。虽然您可以检测它是否处于活动状态,但您只是在检测它是否处于活动状态file1.py——您已经知道了。

如果你只关心 CPython,你可以用 做一些讨厌的事情sys._getframe,但我不会。*

但是,无论如何您都不必这样做。与其打电话obj.div(2),不如做obj / 2。那将调用obj.__div__obj.__truediv__适当地。


* 如果你真的感兴趣:

if sys._getframe(1).f_code.co_flags | __future__.CO_FUTURE_DIVISION:

这(粗略地)告诉您直接负责调用当前函数的作用域是否与该from __future__ import division语句一起编译。

但这可能不是你想要的。例如,假设file3没有该__future__语句,它会创建一个使用您的对象的生成器表达式,并且file2确实具有__future__语句的 ,然后映射div到该生成器。在这种情况下,您想查看第 2 帧,而不是第 1 帧,对吗?但是你的代码怎么会知道呢?


在评论中:

有没有办法在导入时检查这个并用适当的方法替换

请记住,每个模块仅在第一次导入时编译。所以,假设你有两个不同的文件import file1file2divisionfile3没有。因为你已经编译了file1为适用于file2,所以它是错误的file3

您可以想象编写一个导入钩子来防止file1最终进入,sys.modules因此它们每个最终都会得到不同的副本或其他东西,但我认为这不合法,即使它有效。

于 2013-06-02T07:23:04.923 回答