我在Python 2.7.3和Kivy 1.8.0中使用以下函数来淡入Grid小部件:
def __init__(self, **kwargs):
# ...Init parent class here...
self.grid.opacity = 0.0
Clock.schedule_interval(self.show, 1 / 10)
def show(self, value):
if self.grid.opacity == 1.0:
return False
else:
self.grid.opacity += 0.1
show()
无限执行,self.grid.opacity == 1.0
总是返回False,因此调度程序永远不会删除该函数。
我想,并且文档说,opacity
是NumericProperty
,默认为1.0
,但我正在调用show()
之前更改其值。
这是我尝试过的:
if self.grid.opacity == NumericProperty(1.0):
if float(self.grid.opacity) == 1.0:
它不起作用。此外,我确信self.grid.opacity
1.0
和type()
在我进行比较之前检索float
。
这有效:
if str(self.grid.opacity) == "1.0":
但显然我不喜欢这个解决方案。
有什么想法吗?
答案 0 :(得分:4)
可能是浮动比较问题。我不知道应用程序,但浮点数永远不会精确,因此测试它们的相等性会导致问题。您可以尝试以下方式:
if abs(float(self.grid.opacity) - 1.0) < .001:
pass
一个有趣的浮动行为的例子,至少在我的设置上:
>>> .1 + .1 + .1 == .3
False
>>> .1 + .1 == .2
True
答案 1 :(得分:4)
可能不是Python特有的。阅读What Every Programmer Should Know About Floating-Point Arithmetic。
0.1不能完全表示为IEEE754双精度浮点数。所以我想浮点(解析自)0.1
(不完全十分之一)不会转换为字符串“0.1”
答案 2 :(得分:3)
这是你的问题:
>>> q=0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1+0.1
>>> str(q)
'1.0'
>>> q
0.9999999999999999
>>> q==1
False
底线从不将浮点数与==,期间进行比较。
答案 3 :(得分:2)
正如其他人所说,问题是由于存储浮点数的方式。虽然您可以尝试使用变通方法,但还有更好的方法:Animation
。
在__init__
:
self.grid.opacity = 0
anim = Animation(opacity=1)
anim.start(self.grid)
答案 4 :(得分:1)
@Basile Starynkevitch回答了为什么会发生这种情况,浮点数的性质在这里起作用。进行这种比较的一般形式是:
abs(numberA - numberB) <= SOMEEPSILON
其中SOMEEPSILON
是您认为可接受的保证金。
如果您使用较小的数字并且不担心舍入错误,可以sys.float_info.epsilon
因此,我通过将两者结合起来评论:
abs(self.grid.opacity- 1.0) <= sys.float_info.epsilon
文档中epsilon值的定义是:
difference between 1 and the least value greater than 1 that is representable as a float
这是另一种说法,即1和它之前的数字之间的最小值。
因此,例如,如果python只能表示最多2个小数位的数字,那么epsilon将是1.00和0.99之间的差异(实际上该值远小于此值)