簡體   English   中英

Python 3. 'exec' 函數的混淆問題

[英]Python 3. Confusing issue with 'exec' function

我一直在使用 tkinter 為 gui 開發我的蛇游戲。 問題出在其中一項功能上。

該函數應該分別使用 Canvas().create_rectangle 和 Canvas().create_oval 繪制身體片段和水果。 因此,我沒有為每種情況編寫單獨的代碼,而是決定編寫一次,然后使用“shape”參數對其進行修改,即“矩形”或“橢圓形”。 函數還必須為自己的目的返回繪制元素的 id。 最初那部分代碼如下所示:

        exec(

        """
segment_id = self.grid.create_{}(coords, 
    [coord + self.pxSize for coord in coords],  
        fill=color, tag=tag, width=0)

        """.format(shape))

        return segment_id

而不是得到一個常見的NameError: name 'segment_id' is not defined ,我得到了NameError: name 'self' is not defined

谷歌搜索后,我只發現了這個:

ldict = {}
exec('var = something', globals(), ldict)
var = ldict['var']

這解決了NameError: name 'segment_id' is not defined ,但沒有解決另一個。 所以使用科學的 poke 方法,我通過將 locals() 傳遞給它的“globals”參數來修復它。 它有效,現在我更困惑了。

這是代碼:

class Game(Tk):
    def __init__(self):
         ...
    # ...

    def drawSegment(self, position, color, tag, shape, id_=None):
        coords = self.field.from_1D_to_2D(position)
        coords = [i * self.pxSize for i in coords]

        # id > 1, otherwise deletes background
        if id_ and id_ > 1:
            self.grid.delete(id_)

        # ???
        ldict = {}

        exec(

        """
segment_id = self.grid.create_{}(coords,
    [coord + self.pxSize for coord in coords],
        fill=color, tag=tag, width=0)

        """.format(shape), locals(), ldict)

        segment_id = ldict['segment_id']

        return segment_id

    # ...

我需要的是關於它為什么起作用以及發生了什么的答案。

像這樣使用 exec 是不必要的,而且正如您所遇到的那樣,非常令人困惑; 所以我有兩個不同的答案給你。

這是怎么回事?

當您將globals=globals(), locals=ldictexec ,它將在只能看到globalsldict的范圍內執行代碼; 所以特別是,它不會看到任何局部於drawSegment方法局部范圍的變量。 由於self僅在此本地范圍內定義,為了從exec調用內部引用self ,您需要傳入locals() ,而不僅僅是globals()

你應該怎么做?

而不是動態執行基於的值的代碼全塊shape ,可以只動態查找所需CREATE_ *基於方法shape

creator = getattr(self.grid, 'create_{}'.format(shape))
segment_id = creator(coords, [coord + self.pxSize for coord in coords],
                     fill=color, tag=tag, width=0)

如果您知道形狀只有兩種可能性,那么根據個人品味,您可能會更加明顯:

creator = self.grid.create_oval if shape == 'oval' else self.grid.create_rectangle

暫無
暫無

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

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