Python 3。与“exec”函数混淆的问题

2024-04-24 11:31:20 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直在使用tkinter for gui开发我的蛇游戏。问题出在其中一个函数中。你知道吗

函数应该使用Canvas()绘制身体碎片和水果。分别创建\u矩形和Canvas()。创建\u椭圆形。因此,我没有为每种情况编写单独的代码,而是决定只编写一次,然后使用'shape'参数对其进行修改,该参数可以是'rectangle'或'oval'。函数还必须返回所绘制元素的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

    # ...

我需要的是关于它为什么起作用以及发生了什么的答案。你知道吗


Tags: 函数代码selfidfor参数tagsegment
1条回答
网友
1楼 · 发布于 2024-04-24 11:31:20

像这样使用exec是没有必要的,而且正如您所遇到的,非常混乱;因此我为您提供了两个不同的答案。你知道吗

发生什么事了?

当您将globals=globals(), locals=ldict传递给exec时,它将在一个只能看到globalsldict的范围内执行代码;因此特别是,它不会看到任何对drawSegment方法局部范围是局部的变量。由于self只在这个局部范围内定义,为了从exec调用内部引用self,您需要传入locals(),而不仅仅是globals()。你知道吗

你应该怎么做?

不必基于shape的值动态执行整个代码块,您只需基于shape动态查找所需的create方法:

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

相关问题 更多 >