我想为尊重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更改为对环境敏感)。特别是,我想在导入时动态执行此操作,根据导入文件进行更改(我猜这会引发一系列关于首先导入哪个文件的问题等等)。
答案 0 :(得分: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 file1
; file2
已division
开启,file3
未开启file1
。由于您已将file2
编译为适合file3
,因此file1
会出错。
你可以想象写一个导入钩子,阻止sys.modules
在{{1}}结束,所以他们每个人都得到一个不同的副本或东西,但我不认为这是合法的,甚至如果它奏效了。