簡體   English   中英

如何從函數內部更改全局變量?

[英]How to change a global variable from within a function?

我正在嘗試從定義的變量中添加或減去,但我不知道如何用新值覆蓋舊值。

a = 15

def test():
    a = a +10
    print ( a )

test()

錯誤信息:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 4, in test
    a = a +10
UnboundLocalError: local variable 'a' referenced before assignment

嘗試運行代碼時遇到的錯誤是:

UnboundLocalError: local variable 'a' referenced before assignment

... 從表面上看,這似乎很奇怪:畢竟,上面代碼中的第一條語句 ( a = 15 ) 是一個賦值語句。 發生什么了?

實際上,有兩種截然不同的事情正在發生,除非您已經了解它們,否則它們都不是顯而易見的。

首先,您實際上有兩個不同的變量:

  • a在你的第一行是一個全局變量(所謂的,因為它存在於全球范圍內,外的任何函數定義)。

  • a在其他行是一個局部變量,也就是說,它只是你的內部存在test()函數。

這兩個變量彼此完全無關,即使它們具有相同的名稱。

如果在函數內部有賦值語句,則該變量是函數的局部變量 - 例如,您的a = a +10行。

即便如此,錯誤仍然看起來很奇怪——畢竟,你在test()做的第一件事就是賦值給a ,那么如何事先引用它呢?

答案是,在賦值語句中,Python 會先評估=符號右側的所有內容,然后再將其賦值給左側的名稱——因此,即使代碼中首先編寫了賦值, a也會首先被引用在右手邊: a +10

有兩種方法可以解決這個問題。 第一個是告訴 Python 你真的希望a inside test()在全局范圍內與a相同:

def test():
    global a
    a = a + 10
    print(a)

這會奏效,但這是一種非常糟糕的編寫程序的方式。 改變函數內的全局變量很難真正快速地管理,因為你通常有很多函數,而且沒有一個可以確定另一個函數不會以他們不期望的方式弄亂全局變量。

更好的方法是將變量作為參數傳遞給函數,如下所示:

a = 15

def test(x):
    x = x + 10
    print(x)

test(a)

請注意,名稱不必相同——您對test()新定義只是說它接受一個值,然后用它做一些事情。 你可以傳入任何你喜歡的東西——它可以是a ,或者數字7 ,或者其他東西。 事實上,如果您盡量避免在不同作用域中使用同名變量,您的代碼總是會更容易理解。

如果你玩上面的代碼,你會注意到一些有趣的事情:

>>> a = 15
>>> test(a)
25
>>> a
15

...... a沒有改變! 那是因為盡管您將它傳遞給test()並將它分配給x ,但隨后x發生了變化,留下原始的a

如果你想真正改變a ,你需要返回修改后的x從功能,然后重新分配回a在外面:

>>> a = 15
>>> 
>>> def test(x):
...     x = x + 10
...     print(x)
...     return x
... 
>>> a = test(a)
25
>>> a
25

我會這樣做:

def test(a):
    a = a +10
    return a

print(test(15))

請注意,在特此提出的版本中,有些內容與您的有所不同。

首先,我寫下的內容將創建一個函數,該函數具有作為輸入的值a (在本例中,當我們調用函數時設置為 15 - 已在最后一行中定義-),然后將值分配給對象a一個(它是15)加10,然后返回一個(其已被修改,現在是25),最后,打印出由於代碼的最后一行:

print(test(15))

請注意,您所做的實際上並不是一個純函數,可以這么說。 通常我們希望函數獲取一個輸入值(或多個)並返回一個輸入值(或多個)。 在您的情況下,您的輸入值實際上是空的並且沒有輸出值(因為您沒有使用return )。 此外,您嘗試在函數外部編寫此輸入a (當您通過說test(a)調用它時,值a未加載並給了您錯誤 - 即在計算機眼中它是“空的”) .

此外,我鼓勵您習慣於在函數中編寫return ,然后在調用它時使用 print(就像我在最后一行代碼中所寫的一樣: print(test(15)) ),而不是在函數內部使用它. 最好僅在調用函數並想查看函數實際執行的操作時使用 print。

至少,這是他們在基本編程課程中向我展示的方式。 這可以證明如下:如果您在函數內使用 return,該函數將給您一個值,該值稍后可以在其他函數中使用(即函數return是您可以使用的東西)。 否則,您只會在屏幕上顯示一個帶有print 的數字,但計算機無法進一步使用它。

PS你可以這樣做:

def test(a):
    a +=10      
    return a

print(test(15))

您正在修改在函數test()范圍內創建的變量a 如果您希望修改外部a可以執行以下操作:

a = 15

def test():
    global a
    a = a + 1
    print(a)

test()
a = 15

def test():
    global a
    a = a +10
    print ( a )
    
test()

如果要更改函數內局部變量的值,則需要使用 global 關鍵字。

除非使用關鍵字global明確定義,否則變量的范圍是塊本地的。 還有其他方法可以使用globals函數訪問函數的局部globals

a = 15

def test():
    a = globals()['a']
    a += 10
    print ( a )

test()

上面的示例將打印25同時保持全局值不變,即15

這里的問題是范圍。 該錯誤基本上意味着您正在使用變量a ,但它尚不存在。 為什么? 變量a尚未在test()函數中聲明。 在使用它們之前,您需要“邀請”全局變量。

有幾種方法可以在函數的作用域中包含變量。 一種方法是將其用作參數,如下所示:

def test(number):
    number = number + 10
    print ( number )

然后將其實現為:

test(a)

或者,您也可以使用global關鍵字來顯示a是全局變量的函數。 如何? 像這樣:

def test():
    global a
    a = a + 10
    print ( a )

使用global關鍵字,只是告訴test到哪里尋找a 使用第一種方法,您無法修改全局變量a因為您制作了它的副本並且正在使用該副本。 但是,第二種方法,您在函數test()a所做的任何更改都會影響全局變量a

# All the mumbo jumbo aside, here is an experiment 
# to illustrate why this is something useful 
# in the language of Python:
a = 15    # This could be read-only, should check docs

def test_1():
    b = a + 10    # It is perfectly ok to use 'a'
    print(b)

def test_2():
    a = a + 10    # Refrain from attempting to change 'a'
    print(a)

test_1()    # No error
test_2()    # UnboundLocalError: ...

你的錯誤與已經定義無關……一個變量只在它所謂的范圍內有效:如果你在一個函數中創建一個變量,它只在這個函數中定義。

def test():
   x=17
   print(x) # returns 17

test()
print(x) # results in an error.

暫無
暫無

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

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