簡體   English   中英

如何使用exec根據Python3中的字典將列表分配給變量?

[英]How to use exec to assign list to variable according to dictionary in Python3?

我想將列表分配給變量,而listvariable都存儲在字典measurements 這是具有較少變量的 Python 2 版本的measurements

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]}

def f():
    for key,val in measurements.items():
        exec(key + ' = val') in globals(),locals()
    print (tg)
f()

但是,正如在另一個問題中提到的,它不適合 Python 3。如果我這樣編寫代碼:

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16,
 2.203e+16]}

def f():
    for key,val in measurements.items():
        ldict = {}
        exec(key + ' = val', globals(),ldict)
        key = ldict[key]
        # exec(key + ' = val') in globals(),locals()
    print (tg)
f()

我收到此錯誤: NameError: name 'val' is not defined

ldict = {}技巧創建了一個替代的本地命名空間以在exec內部使用。 這很有用,因為locals()返回的 dict 不會像在 Python 2 中那樣寫入您的實際本地人。

但是替代命名空間{}是空的。 它不包含您的locals() ,因此它沒有val 嘗試使用ldict = {**locals()}代替將本地人的內容復制到替代本地人ldict


請記住,您必須從 ldict 中讀取 exec 創建的所有“本地人”。 因此, print(tg)也不會工作,因為它只被分配在一個替代的本地命名空間中。 您可能不想每次循環都制作一個新的。 只是.update()一個你提前做的。

def f():
    ldict = {}
    for key,val in measurements.items():
        ldict.update(locals())
        exec(key + ' = val', globals(),ldict)
        key = ldict[key]
        # exec(key + ' = val') in globals(),locals()
    print (ldict['tg'])

為了性能優化,Python3 中的編譯器必須提前知道 locals 的數量和名稱。 (這不適用於globals() ,它們仍然會寫入。)

如果你事先知道他們,你可以從他們那里分配,例如

tg = ldict['tg']
print(tg)

如果您需要多個,您可以將字典解壓縮到本地,例如

a, b, c = (ldict[key] for key in ['a', 'b', 'c'])

或者您可以將整個 dict 轉儲到一個簡單的命名空間中並使用. 而不是[]

from types import SimpleNamespace

# ...

ns = SimpleNamespace(**ldict)
print(ns.tg)

您也可以只exec需要新本地ldict任何代碼,因為您可以為exec ldict命名空間。

exec("print(tg)", globals(), ldcit)

我知道您的示例代碼可能是從原始代碼簡化的,但它似乎根本不需要exec 除非您絕對需要,否則通常認為使用exec是不好的形式,因為它會混淆靜態分析工具並且在運行時編譯字符串很慢,尤其是在這樣的循環中重復時。

如果必須使用 exec,最好將循環放在 exec 字符串中(使用三引號),而不是在循環中調用 exec。 這樣字符串只需要編譯一次,而不是每次循環。

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]}

def f():
    for key,val in measurements.items():
        exec('{} = {}'.format(key, val))
    print (tg)

    local = locals()
    for key in measurements.keys():
        print 'Key: ', key, ', Value: ', local[key]
f()

蟒蛇3:

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]}

def f():
    for key,val in measurements.items():
        exec('global {};{} = {}'.format(key, key, val))
    print ('tg: ', tg)

    vars = globals()
    for key in measurements.keys():
        print ('Key: ', key, ', Value: ', vars[key])
f()

輸出:

[8.184e+16, 8.345e+16, 8.045e+16, 8.52e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]
Key:  tg , Value:  [8.184e+16, 8.345e+16, 8.045e+16, 8.52e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]

多年后,但我已經意識到您可以(ab)使用在類聲明中創建的臨時命名空間來獲得函數內部的直寫 locals() 命名空間。 這允許您非常直接地翻譯 Python 2 版本:

measurements = {'tg': [8.184e+16, 8.345e+16, 8.045e+16, 8.520e+16, 8.322e+16, 7.622e+16, 4.305e+16, 2.203e+16]}

def f():
    class _:
        for key,val in measurements.items():
            exec(key + ' = val', globals(), locals())
        print (tg)

f()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM