在函数内部实现“全局变量”后,未定义名称“变量”

时间:2019-04-03 19:01:18

标签: python

但是,当我遇到有关变量定义范围的问题时,我目前正在使用python开发第一个程序。这是我的代码中有问题的示例:

def listen(topLeft, bottomRight):

    timeless = 0
    # The key combination to check
    COMBINATIONS = [
        {keyboard.Key.shift, keyboard.KeyCode(char='b')}
    ]

    # The currently active modifiers
    current = set()

    def execute():
        global topLeft,bottomRight,timeless
        print("Do Something")

        if timeless == 0:
            topLeft = mouse.position
            timeless += 1
        elif timeless == 1:
            bottomRight = mouse.position
            timeless += 1
        elif timeless >= 2:
            return False

    def on_press(key):
        global timeless
        if any([key in COMBO for COMBO in COMBINATIONS]):
            current.add(key)
            if any(all(k in current for k in COMBO) for COMBO in              COMBINATIONS):
                execute()

    def on_release(key):
        if any([key in COMBO for COMBO in COMBINATIONS]):
            current.remove(key)

    with keyboard.Listener(on_press=on_press, on_release=on_release) as     listener:
        listener.join()

基本上,一旦侦听器调用on_press,就会调用execute。为了传递timeless变量,我使用了global标签。但是,一旦程序开始执行execute函数,我将收到以下错误代码:NameError: name 'timeless' is not defined。 任何帮助将不胜感激,因为我已经尽了一切努力

3 个答案:

答案 0 :(得分:1)

您声明任何函数的全局变量外部。您可以在函数内部引用全局变量,而无需使用关键字。在为变量分配新值时,只需使用关键字global,这是一种指定要向全局变量而不是共享的新局部变量分配值的方式同名。 See this for examples。以您的示例为例,首先在任何函数外部定义全局变量,然后在函数中使用它们,并在需要修改时使用global关键字:

# Global variable definitions outside of any function.
timeless = 0
topLeft = 0
bottomRight = 0

# Define the function that uses the variables.
def execute():
    print("Do Something")
    global timeless
    if timeless == 0:
        global topLeft  # modifying the global variable with this name!
        topLeft = mouse.position
        timeless += 1
    elif timeless == 1:
        global bottomRight  # modifying the global variable!
        bottomRight = mouse.position
        timeless += 1
    elif timeless >= 2:
        return False

所有这些都表明,最好避免一般的全局变量。您可以改为定义一个类,并将成员属性用于需要修改并在多个方法中引用的那些内容。例如,类似:

class Listener:
    def __init__(self):
        self.timeless = 0
        self.top_left = 0
        self.bottom_right = 0

    def execute(self, mouse):  # pass some mouse object in, otherwise what's "mouse"?
        print('Do something')
        if self.timeless == 0:
            self.top_left = mouse.position
            self.timeless += 1
        elif self.timeless == 1:
            ...

答案 1 :(得分:1)

由于timeless实际上是函数listen中的局部变量,因此它不是全局变量,并且实际上您的错误是由于没有名为timeless的全局变量而引起的。 execute所需要的是将timeless(可能还有topLeftbottomRight声明为非局部的,以便它引用包含词法范围的堆栈中的第一个绑定

def listen(topLeft, bottomRight):

    timeless = 0
    # The key combination to check
    COMBINATIONS = [
        {keyboard.Key.shift, keyboard.KeyCode(char='b')}
    ]

    # The currently active modifiers
    current = set()

    def execute():
        # modify the local variables in listen
        nonlocal topLeft,bottomRight,timeless
        print("Do Something")

        if timeless == 0:
            topLeft = mouse.position
            timeless += 1
        elif timeless == 1:
            bottomRight = mouse.position
            timeless += 1
        elif timeless >= 2:
            return False

    ...

在全局范围内定义的函数中,globalnonlocal是相同的,因为第一个包含范围。在嵌套函数中,global会直接跳到全局范围,而nonlocal会一次向上移动一个嵌套范围。

答案 2 :(得分:0)

timeless = 0
topLeft = 0
bottomRight = 0
current = set()

def listen(topLeft, bottomRight):
    timeless = 0
    # The key combination to check
    COMBINATIONS = [
        {keyboard.Key.shift, keyboard.KeyCode(char='b')}
    ]
    # The currently active modifiers
    current = set()

def execute():
    print("Do Something")
    if timeless == 0:
        topLeft = mouse.position
        timeless += 1
    elif timeless == 1:
        bottomRight = mouse.position
        timeless += 1
    elif timeless >= 2:
        return False


def on_press(key):
    if any([key in COMBO for COMBO in COMBINATIONS]):
        current.add(key)
        if any(all(k in current for k in COMBO) for COMBO in COMBINATIONS):
            execute()


def on_release(key):
    if any([key in COMBO for COMBO in COMBINATIONS]):
        current.remove(key)