python名称与作用域_Python变量命名与作用域的坑
function showImg(url) {
var frameid = 'frameimg' + Math.random();
window.img = '
document.write('');
}
使用python有些年頭了,自認為對Python的基本知識很了解了,今天發生的一件事讓我對Python有了更多的認識,寫成文章做個記錄。
同事讓我幫忙看以下一段代碼,具體內容和函數名字可以不用太過在意,命名上做了一些特殊處理,但是不影響代碼邏輯和要表達的意思。
for循環中當node_type為fb時,將FBX對象返回并作為全局變量dut(node_name的內容是字符串dut),接下來print dut,報錯。
def setup_module(module):
with step('Set_setup'):
function_1_run(topo_info)
function_2_run(topo_info)
function_3_run(topo_info, set_resource, 'device_config')
for node in topo_info.nodes:
if node.type == 'fb':
globals()[node.name] = FBX(node.manage_ip,'admin','111111')
print node.name
print globals()[node.name]
print dut
else:
globals()[node.name] = Device()
globals()[node.name].node_info = node
if not get_config_file(topo_info, set_resource, 'device_config'):
test = dut
print test
with cli_ctx(dut) as dut:
dut.cli.cmd_list = \
[
'configure',
'interface fastEthernet 2',
'ip address 192.168.1.5/24'
]
dut.cli.exec_cmd()
log.info('cli_ctx 1 end')
export_firebox_topo(topo_info, set_resource, 'device_config')
錯誤信息如下:
==================================== ERRORS ====================================
___________________ ERROR at setup of some_module_1 ___________________
module =
def setup_module(module):
with step('Set_setup'):
function_1_run(topo_info)
function_2_run(topo_info)
function_3_run(topo_info, set_resource, 'device_config')
for node in topo_info.nodes:
if node.type == 'fb':
globals()[node.name] = FBX(node.manage_ip,'admin','111111')
print node.name
print globals()[node.name]
> print dut
E UnboundLocalError: local variable 'dut' referenced before assignment
some_name_python.py:54: UnboundLocalError
========================== 1 error in 155.62 seconds ===========================
同事提到,如果將with cli_ctx as dut這個block刪除掉,代碼執行正常。
聽到這里,我的第一反應是變量作用域的問題,但是也無法道出其中原委,于是建議同事,將context manager那一段代碼改成with cli_ctx as d,重新嘗試一下是否有問題,同時我在網上繼續搜索相關的原因,之后由結果和理論結合分析問題的原因。
幸運的是,代碼修改以后,執行正常,我也找到了一些文章來解釋這個問題,我的第一感覺也沒有錯,的確是變量作用域的問題,代碼在執行過程中,print dut實際上是在訪問Local variable,而不是我們期望的global variable dut。
參考Python的官方文檔和搜索到的資料,總結出具體原因如下。
當搜索一個變量的時候,先從局部作用域開始搜索,如果在局部作用域沒有找到那個變量,就會在全局變量中找這個變量,如果找不到拋出異常Unbound-LocalError。
如果內部函數有引用外部函數的同名變量或者全局變量,并且對這個變量有修改,那么python會認為它是一個局部變量。因為對變量的定義在代碼塊以外,當前代碼塊中沒有變量的定義和賦值,所以報錯。
在我們的代碼中,全局變量dut雖然創建了,但是由于在函數代碼塊中,下文中有context manager cli_ctx對變量dut進行了賦值操作,導致在函數block中,dut成為了局部變量,而非全局變量。
對變量賦值的操作=是很明顯的語句,其他不是那么明顯的賦值操作有:for循環中的賦值,except語句中的賦值,with...as...{var}中的var。
大坑啊,基礎不夠牢靠還是。
Reference
Python 2.7.13 Documentation - Language Reference - 4. Execution Model
Stackoverflow - Short Description of the Scoping Rules?
總結
以上是生活随笔為你收集整理的python名称与作用域_Python变量命名与作用域的坑的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python的逆袭之路_Python领域
- 下一篇: python切割图像,使用Python图