如何經過引用傳遞變量?

Python文檔彷佛尚不清楚參數是經過引用仍是經過值傳遞,而且如下代碼產生不變的值「原始」 html

class PassByReference:
    def __init__(self):
        self.variable = 'Original'
        self.change(self.variable)
        print(self.variable)

    def change(self, var):
        var = 'Changed'

我能夠作些什麼來經過實際引用傳遞變量嗎? python


#1樓

從技術上講, Python始終使用按引用傳遞值 。 我將重複其餘答案以支持個人發言。 數據庫

Python始終使用按引用傳遞值。 也不例外。 任何變量分配都意味着複製參考值。 沒有例外。 任何變量都是綁定到參考值的名稱。 老是。 編程

您能夠將參考值視爲目標對象的地址。 該地址在使用時會自動取消引用。 這樣,使用參考值,彷佛您能夠直接使用目標對象。 可是,二者之間老是存在一個參考,距離目標還有一步之遙。 app

這是證實Python使用引用傳遞的示例: 編程語言

傳遞參數的圖解示例

若是參數經過值傳遞,則外部lst沒法修改。 綠色是目標對象(黑色是內部存儲的值,紅色是對象類型),黃色是內部具備參考值的存儲器-繪製爲箭頭。 藍色實心箭頭是傳遞給函數的參考值(經過虛線藍色箭頭路徑)。 醜陋的深黃色是內部詞典。 (實際上也能夠將其繪製爲綠色橢圓形。顏色和形狀僅表示它是內部的。) 函數

您可使用id()內置函數來了解參考值是什麼(即目標對象的地址)。 spa

在編譯語言中,變量是可以捕獲類型值的內存空間。 在Python中,變量是綁定到引用變量的名稱(在內部以字符串形式捕獲),該變量將引用值保存到目標對象。 變量的名稱是內部字典中的鍵,該字典項的值部分將參考值存儲到目標。 指針

參考值隱藏在Python中。 沒有用於存儲參考值的任何明確的用戶類型。 可是,您能夠將list元素(或任何其餘合適的容器類型的元素)用做參考變量,由於全部容器的確會將這些元素存儲爲對目標對象的引用。 換句話說,元素實際上不包含在容器內,僅包含對元素的引用。 code


#2樓

這是Python中使用的pass by object概念的簡單解釋(我但願如此)。
每當將對象傳遞給函數時,都會傳遞對象自己(Python中的對象其實是您在其餘編程語言中稱爲值的對象),而不是對該對象的引用。 換句話說,當您致電時:

def change_me(list):
   list = [1, 2, 3]

my_list = [0, 1]
change_me(my_list)

正在傳遞實際對象-[0,1](在其餘編程語言中將其稱爲值)。 所以,實際上,函數change_me將嘗試執行如下操做:

[0, 1] = [1, 2, 3]

這顯然不會改變傳遞給函數的對象。 若是函數看起來像這樣:

def change_me(list):
   list.append(2)

而後,該調用將致使:

[0, 1].append(2)

這顯然會改變對象。 這個答案很好地解釋了。


#3樓

Effbot(又名Fredrik Lundh)將Python的變量傳遞樣式描述爲按對象調用: http : //effbot.org/zone/call-by-object.htm

對象在堆上分配,指向它們的指針能夠在任何地方傳遞。

  • 當您進行x = 1000類的賦值時,將建立一個字典條目,該條目將當前名稱空間中的字符串「 x」映射到一個指向包含1000的整數對象的指針。

  • 當使用x = 2000更新「 x」時,將建立一個新的整數對象,而且字典將更新爲指向該新對象。 舊的一千個對象保持不變(取決於其餘是否引用了該對象,該對象是否能夠存活)。

  • 當您進行新的賦值(例如y = x ,將建立一個新的字典條目「 y」,該條目指向與「 x」條目相同的對象。

  • 諸如字符串和整數之類的對象是不可變的 。 這僅表示沒有任何方法能夠在建立對象後更改該對象。 例如,一旦建立了整數對象1000,它就永遠不會改變。 數學是經過建立新的整數對象完成的。

  • 像列表這樣的對象是可變的 。 這意味着能夠經過指向該對象的任何內容來更改該對象的內容。 例如, x = []; y = x; x.append(10); print y x = []; y = x; x.append(10); print y x = []; y = x; x.append(10); print y將打印[10] 。 空列表已建立。 「 x」和「 y」都指向同一列表。 append方法會更改(更新)列表對象(例如向數據庫中添加記錄),而且結果對於「 x」和「 y」都是可見的(就像數據庫更新對於該數據庫的每一個鏈接都是可見的同樣)。

但願能爲您解決問題。


#4樓

如您所言,您須要有一個可變的對象,可是讓我建議您檢查一下全局變量,由於它們能夠幫助您甚至解決此類問題!

http://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

例:

>>> def x(y):
...     global z
...     z = y
...

>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'z' is not defined

>>> x(2)
>>> x
<function x at 0x00000000020E1730>
>>> y
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'y' is not defined
>>> z
2

#5樓

Python中沒有變量

理解參數傳遞的關鍵是中止考慮「變量」。 Python中有名稱和對象,它們一塊兒看起來像變量,可是始終區分這三個名稱頗有用。

  1. Python具備名稱和對象。
  2. 分配將名稱綁定到對象。
  3. 將參數傳遞給函數還會將名稱(函數的參數名稱)綁定到對象。

這就是所有。 可變性與這個問題無關。

例:

a = 1

這會將名稱a綁定到具備值1的整數類型的對象。

b = x

這會將名稱b綁定到名稱x當前綁定到的同一對象。 此後,名稱b與名稱x無關。

請參閱Python 3語言參考中的3.14.2節。

如何閱讀問題中的例子

在問題所示的代碼中,語句self.Change(self.variable)將名稱var (在Change函數的範圍內self.Change(self.variable)綁定到持有值'Original'和賦值var = 'Changed' (在函數體Change )再次爲該對象分配了相同的名稱:另外一個對象(碰巧也包含一個字符串,但可能徹底是其餘東西)。

如何經過參考

(編輯2019-04-28)

所以,若是要更改的對象是可變對象,則沒有問題,由於全部內容均經過引用有效地傳遞。

若是它是一個不可變的對象(例如布爾,數字,字符串),則將其包裝在一個可變的對象中。
對此的快速解決方案是一個元素列表(而不是self.variable ,傳遞[self.variable]並在函數中修改var[0] )。
更加Python化的方法是引入一個瑣碎的,一屬性類。 該函數接收該類的實例並操縱該屬性。

相關文章
相關標籤/搜索