簡體   English   中英

作為輸入傳遞給函數的python字典在該函數中充當全局而不是局部

[英]python dictionary passed as an input to a function acts like a global in that function rather than a local

我對下面的行為感到非常困惑。 案例 1、3 和 4 的表現符合我的預期,但案例 2 則不然。 為什么情況 2 允許函數全局更改字典條目的值,即使函數從不返回字典? 我使用函數的一個主要原因是將函數中的所有內容與代碼的其余部分隔離開來,但是如果我選擇在函數內部使用相同的變量名,這似乎是不可能的。 我的理解是,在函數中明確定義的任何內容都是該函數的本地內容,但如果字典被定義並作為輸入傳遞給函數,情況似乎並非如此。

Python 2.7.2+ (default, Oct  4 2011, 20:06:09) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.

==============案例1================

>>> def testfun1(a):
...     a=2
... 
>>> a=0
>>> testfun1(a)
>>> a
0

==============案例2================

>>> def testfun2(b):
...     b['test']=2
... 
>>> b={}
>>> testfun2(b)
>>> b
{'test': 2}

==============案例3================

>>> def testfun3():
...     c=2
... 
>>> c=0
>>> testfun3()
>>> c
0

==============案例4================(由這個問題解釋: 全局字典不需要關鍵字global來修改它們?

>>> def testfun4():
...     d['test']=10
... 
>>> d={}
>>> testfun4()
>>> d
{'test': 10}

Python 的“參數評估策略”與您可能習慣的語言略有不同 python 沒有顯式按值調用和按引用調用語義,而是通過共享調用 你本質上總是傳遞對象本身,對象的可變性決定了它是否可以被修改。 列表和字典是可變對象。 數字、字符串和元組不是。

您將字典傳遞給函數,而不是副本。 因此,當您修改它時,您也在修改原始副本。

為避免這種情況,您應該在調用函數之前或從函數內部復制字典(將字典傳遞給dict函數應該這樣做,即testfun4(dict(d))並將函數定義為def testfun4(d):

為了支持@Casey Kuball所說的,Python 中的每個對象都是通過引用傳遞的。 每個函數都會收到對您傳遞的實際對象的引用。 修改這些對象取決於它們是否是可變數據類型。

本質上,可以說像字典、集合和列表這樣的可變對象是通過引用傳遞的。 intstrtuple這樣的不可變對象是按值傳遞的。

您還應該注意,在某些情況下,可變對象在函數中被覆蓋,從而丟失了對傳遞給函數的實際對象的引用。

>>> def testfun(b):
...     b = b or {}  # Creates a new object if b is false
...     b['test'] = 2
... 
>>> b = {}
>>> testfun(b)
>>> b
{}

當您將整數或字符串等基本對象傳遞給函數時,如果您在函數內部更改它,則函數外部的相應對象不會發生任何變化,因為當您以基本對象開頭時,python 按值傳遞它。

但是,如果您將字典或列表傳遞給函數,則它們是通過引用傳遞的,這意味着您將具有這種行為:函數外部的對象已更改,如您所見。

編輯:另外,按值傳遞和按引用傳遞是有區別的:按值傳遞,是對對象進行“拷貝”,以便在函數中使用; 通過引用,完全相同的對象通過引用傳遞,並且在函數內部對其進行的修改在外部可見。 根據定義,python 通過值傳遞其不可變對象,並通過引用傳遞其可變對象。

global 關鍵字僅用於賦值(可能是del ,我從未嘗試過)。 對象突變是完全有效的。

你給函數傳遞了一個dict對象,在函數內部進行了修改,所以當然會在函數返回后進行修改。 對象不會被復制,所以你修改了你傳遞的同一個對象,這個問題與你顯式傳遞對象時的命名、相似名稱、范圍等無關。

暫無
暫無

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

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