我正在编写一些Python 2.7.12代码,并对此代码执行中的以下错误感到非常惊讶:
def validate_available_links(self, link_dict, sub_element=None):
def strip_dirt(key_val):
#TODO: properly strip HTML encoded characters
key_val = key_val.replace("\u2039", "<")
key_val = key_val.replace("\u203a", ">")
return key_val
# Scrape all the links from the current webpage and verify
# it with the provided link dictionary.
if sub_element is None:
act_links = self.suiteContext['browser'].webdriver.find_elements_by_tag_name('a')
else:
act_links = sub_element.find_elements_by_tag_name('a')
result = {strip_dirt(lnk.text): lnk.get_attribute('href') for lnk in act_links}
diff_keys = set(result.keys()) - set(link_dict.keys())
diff_values = set(result.values()) - set(link_dict.values())
self.tear_down_hook()
for l_text, l_url in link_dict.iteritems():
self.cfg.logger.info("[VALIDATION] Verify Link text [{}] and URL [{}]."
.format(l_text, l_url))
import pdb; pdb.set_trace()
执行代码时
(Pdb) result = {strip_dirt(lnk.text): lnk.get_attribute('href') for lnk in act_links}
*** NameError: global name 'strip_dirt' is not defined
(Pdb) strip_dirt
<function strip_dirt at 0x0651BBB0>
(Pdb) result = {strip_dirt(lnk.text): lnk.get_attribute('href') for lnk in act_links}
*** NameError: global name 'strip_dirt' is not defined
(Pdb) strip_dirt('x')
'x'
(Pdb) {strip_dirt(lnk.text): lnk.get_attribute('href') for lnk in act_links}
*** NameError: global name 'strip_dirt' is not defined
有人可以解释为什么内部函数strip_dirt
不能被字典理解所访问,而是用于外部函数的其余部分吗?
答案 0 :(得分:1)
我不是pdb
专家,所以如果我错了,请纠正我。
这是MCVE:
import pdb
def f():
def g(n): return 2*n
pdb.set_trace()
f()
现在,在pdb
中,正如所料:
ipdb> g(5)
10
但是g
名称来自哪里?
ipdb> 'g' in globals()
False
ipdb> 'g' in locals()
True
好的,g
位于locals()
的{{1}}个变量中。创建列表或字典理解时,您有新的f
变量:
locals()
因此,在列表/字典理解中,ipdb> [locals() for _ in range(1)]
[{'_': 0, '.0': <range_iterator object at 0x7f1924003d80>}]
既不在g
也不在locals()
:
globals()
现在,最大的问题是:为什么这在正在运行的程序中起作用而不在ipdb> [g(1) for _ in range(1)]
*** NameError: name 'g' is not defined
中?我希望我有一个解释的开头:
ipdb
在import pdb
import inspect
def f():
def g(n): return 2*n
print([g(1) for _ in range(1)])
print([inspect.stack()[1].frame.f_locals for _ in range(1)])
pdb.set_trace()
f()
# output:
[2] # it works because...
[{'g': <function f.<locals>.g at 0x7f1916692488>}] # ...g is in the parent stack frame
,注意到:
ipdb
但是如果你从父框架手动取ipdb> [g(1) for _ in range(1)]
*** NameError: name 'g' is not defined
,它就会起作用:
g
结论:与正在运行的程序不同,ipdb> [inspect.stack()[1].frame.f_locals for _ in range(1)]
[{'g': <function f.<locals>.g at 0x7f1916692488>, '__return__': None}]
ipdb> [inspect.stack()[1].frame.f_locals['g'](1) for _ in range(1)]
[2]
似乎无法直接访问存储在父框架中的值。
请注意,这可能在很大程度上取决于Python的实现。 (我使用过CPython。)