我已经使用小数默认值定义了一个接收可选参数的函数:
def foo(x=0.1):
pass
现在,在IDLE shell中输入foo(
时,弹出的帮助我完成调用的工具提示会显示(x=0<tuple>)
,而不是预期的(x=0.1)
。我之前从未遇到过这个问题,但我发现很难相信我没有使用任何带有小数默认值的函数/方法。
假设它是一个功能,而不是一个错误,我很高兴有人能解释它为什么会发生。我在Windows 7上使用64位64位python。
修改
从评论中看,它似乎不是一个功能。 我已经通过2rs2ts的建议检查了不同的函数定义,并且发现了我试图在工具提示中替换的小数点的每个外观。所以这个定义 -
def foo(x=[(1,0.1), 2, .3]):
pass
生成工具提示(x=[(1, 0<tuple>), 2, 0<tuple>])
。
我应该关闭此问题并提交错误报告吗?
答案 0 :(得分:3)
这是一个奇怪的答案,发现它感觉有点像野鹅追逐......
我没有看到问题发布在bugs.python.org,但经过一些探讨后,我在Python 2.6.6中找到了CallTips.py文件,我看到了可能有问题的代码行。通过向下滚动到get_arg_text()
方法中的第161行,我看到了
arg_text = "(%s)" % re.sub("\.\d+", "<tuple>", arg_text)
这看起来就像您在问题中发布的那样,如果arg_text
是一个转换为字符串的浮点数,那么该行将返回<tuple>
字符串:
arg_text = "(%s)" % re.sub("\.\d+", "<tuple>", "9.0") # returns (9<tuple>)
但是,问题必须在svn.python.org/.../Calltips.py(在PEP 384期间?)修复,因为该版本没有上述行。实际上,get_arg_text()
已替换为get_argspec()
。
所以答案似乎是在PEP 384中修复了。基于对你的问题的评论,Python 3.3的IDLE有这个修复,但正如你所指出的,Python 2.7.5没有。为了比较,我粘贴了以下两种方法,以便有人能够准确解释PEP 384如何解决您所看到的问题。
希望它有所帮助。
旧版本的Calltips.py有get_arg_text(ob)
(至少与您使用的2.7.5版本一样)。例如,它位于Mac上的 /Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/idlelib/CallTips.py 。该功能定义如下:
def get_arg_text(ob):
"""Get a string describing the arguments for the given object"""
arg_text = ""
if ob is not None:
arg_offset = 0
if type(ob) in (types.ClassType, types.TypeType):
# Look for the highest __init__ in the class chain.
fob = _find_constructor(ob)
if fob is None:
fob = lambda: None
else:
arg_offset = 1
elif type(ob)==types.MethodType:
# bit of a hack for methods - turn it into a function
# but we drop the "self" param.
fob = ob.im_func
arg_offset = 1
else:
fob = ob
# Try to build one for Python defined functions
if type(fob) in [types.FunctionType, types.LambdaType]: # <- differs here!
argcount = fob.func_code.co_argcount
real_args = fob.func_code.co_varnames[arg_offset:argcount]
defaults = fob.func_defaults or []
defaults = list(map(lambda name: "=%s" % repr(name), defaults))
defaults = [""] * (len(real_args) - len(defaults)) + defaults
items = map(lambda arg, dflt: arg + dflt, real_args, defaults)
if fob.func_code.co_flags & 0x4:
items.append("...")
if fob.func_code.co_flags & 0x8:
items.append("***")
arg_text = ", ".join(items)
arg_text = "(%s)" % re.sub("\.\d+", "<tuple>", arg_text)
# See if we can use the docstring
doc = getattr(ob, "__doc__", "")
if doc:
doc = doc.lstrip()
pos = doc.find("\n")
if pos < 0 or pos > 70:
pos = 70
if arg_text:
arg_text += "\n"
arg_text += doc[:pos]
return arg_text
位于svn.python.org/.../Calltips.py的相应功能似乎修复了一个错误。该方法已重命名为get_argspec
:
def get_argspec(ob):
"""Get a string describing the arguments for the given object."""
argspec = ""
if ob is not None:
if isinstance(ob, type):
fob = _find_constructor(ob)
if fob is None:
fob = lambda: None
elif isinstance(ob, types.MethodType):
fob = ob.__func__
else:
fob = ob
if isinstance(fob, (types.FunctionType, types.LambdaType)):
argspec = inspect.formatargspec(*inspect.getfullargspec(fob))
pat = re.compile('self\,?\s*')
argspec = pat.sub("", argspec)
doc = getattr(ob, "__doc__", "")
if doc:
doc = doc.lstrip()
pos = doc.find("\n")
if pos < 0 or pos > 70:
pos = 70
if argspec:
argspec += "\n"
argspec += doc[:pos]
return argspec
答案 1 :(得分:2)
感谢Gary和Ariel的侦探工作,我能够通过在替换重新开头添加负面的lookbehind断言"(?<!\d)"
来解决这个问题。例如,现在匹配“.0”,第一个参数元组的有趣'名称',它从不跟随数字,但不匹配'0.0',浮点数的字符串表示,始终以数字开头。 CPython tracker issue 18539