目錄
正確答案
清單 - 可變類型
字串 - 不可變型別
我們如何解決這個問題?
首頁 後端開發 Python教學 如何透過引用傳遞變數?

如何透過引用傳遞變數?

Feb 09, 2024 pm 08:00 PM
作用域

如何透過引用傳遞變數?

問題內容

我寫這個類別是為了測試:

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

    def change(self, var):
        var = 'Changed'
登入後複製

當我嘗試建立實例時,輸出是 original。所以python中的參數似乎是按值傳遞的。那是對的嗎?如何修改程式碼才能達到引用傳遞的效果,使得輸出為changed

有時人們會感到驚訝,像x = 1 這樣的程式碼(其中x 是參數名稱)不會影響呼叫者的參數,但像 x[0] = 1 這樣的程式碼卻會影響呼叫者的參數。發生這種情況是因為儘管有= 語法,但項目分配切片分配變異現有物件的方法,而不是重新分配變數。請參閱為什麼函數可以修改呼叫者感知到的某些參數,但不能修改其他參數?了解詳情。

另請參閱按引用傳遞與按值傳遞之間有什麼區別?用於重要的、與語言無關的術語討論。


正確答案


參數是透過賦值傳遞。這背後的理由有兩個:

  1. 傳入的參數實際上是物件的引用(但引用是按值傳遞的)
  2. 某些資料型別是可變的,但其他資料型別則不然

所以:

  • 如果將一個可變物件傳遞給方法,則該方法將獲得對相同物件的引用,並且您可以隨心所欲地改變它,但是如果您在方法時,外部作用域對此一無所知,完成後,外部引用仍將指向原始物件。

  • 如果將不可變物件傳遞給方法,您仍然無法重新綁定外部引用,甚至無法變更該物件。

為了更清楚地說明這一點,讓我們舉一些例子。

清單 - 可變類型

讓我們試著修改傳遞給方法的清單:

def try_to_change_list_contents(the_list):
    print('got', the_list)
    the_list.append('four')
    print('changed to', the_list)

outer_list = ['one', 'two', 'three']

print('before, outer_list =', outer_list)
try_to_change_list_contents(outer_list)
print('after, outer_list =', outer_list)
登入後複製

輸出:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']
登入後複製

由於傳入的參數是對 outer_list 的引用,而不是它的副本,因此我們可以使用變異列表方法來更改它,並將更改反映在外部範圍中。

現在讓我們看看當我們嘗試更改作為參數傳入的參考時會發生什麼:

#
def try_to_change_list_reference(the_list):
    print('got', the_list)
    the_list = ['and', 'we', 'can', 'not', 'lie']
    print('set to', the_list)

outer_list = ['we', 'like', 'proper', 'english']

print('before, outer_list =', outer_list)
try_to_change_list_reference(outer_list)
print('after, outer_list =', outer_list)
登入後複製

輸出:

before, outer_list = ['we', 'like', 'proper', 'english']
got ['we', 'like', 'proper', 'english']
set to ['and', 'we', 'can', 'not', 'lie']
after, outer_list = ['we', 'like', 'proper', 'english']
登入後複製

由於 the_list 參數是按值傳遞的,因此為其指派新清單不會對方法外部的程式碼產生任何影響。 the_listouter_list 引用的副本,我們讓 the_list 指向一個新列表,但無法更改 outer_list 指向的位置。

字串 - 不可變型別

它是不可變的,因此我們無法更改字串的內容

#

現在,讓我們嘗試更改引用

def try_to_change_string_reference(the_string):
    print('got', the_string)
    the_string = 'in a kingdom by the sea'
    print('set to', the_string)

outer_string = 'it was many and many a year ago'

print('before, outer_string =', outer_string)
try_to_change_string_reference(outer_string)
print('after, outer_string =', outer_string)
登入後複製

輸出:

before, outer_string = it was many and many a year ago
got it was many and many a year ago
set to in a kingdom by the sea
after, outer_string = it was many and many a year ago
登入後複製

同樣,由於 the_string 參數是按值傳遞的,因此為其指派新字串不會對方法外部的程式碼看到任何影響。 the_stringouter_string 引用的副本,我們讓 the_string 指向一個新字串,但無法更改 outer_string 指向的位置。

我希望這能讓事情變得更清楚。

編輯:有人指出,這並沒有回答 @david 最初提出的問題:「我可以做些什麼來透過實際引用傳遞變數嗎?」。讓我們努力吧。

我們如何解決這個問題?

正如@andrea的回答所示,您可以傳回新值。這不會改變傳入內容的方式,但可以讓您獲得想要的資訊:

def return_a_whole_new_string(the_string):
    new_string = something_to_do_with_the_old_string(the_string)
    return new_string

# then you could call it like
my_string = return_a_whole_new_string(my_string)
登入後複製

如果您確實想避免使用返回值,您可以建立一個類別來保存您的值並將其傳遞給函數或使用現有的類,例如列表:

def use_a_wrapper_to_simulate_pass_by_reference(stuff_to_change):
    new_string = something_to_do_with_the_old_string(stuff_to_change[0])
    stuff_to_change[0] = new_string

# then you could call it like
wrapper = [my_string]
use_a_wrapper_to_simulate_pass_by_reference(wrapper)

do_something_with(wrapper[0])
登入後複製

雖然這看起來有點麻煩。

以上是如何透過引用傳遞變數?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

c語言中typedef struct的用法 c語言中typedef struct的用法 May 09, 2024 am 10:15 AM

c語言中typedef struct的用法

java中的variable expected怎麼解決 java中的variable expected怎麼解決 May 07, 2024 am 02:48 AM

java中的variable expected怎麼解決

js中閉包的優缺點 js中閉包的優缺點 May 10, 2024 am 04:39 AM

js中閉包的優缺點

c++中的include什麼意思 c++中的include什麼意思 May 09, 2024 am 01:45 AM

c++中的include什麼意思

C++ 智慧指標:全面剖析其生命週期 C++ 智慧指標:全面剖析其生命週期 May 09, 2024 am 11:06 AM

C++ 智慧指標:全面剖析其生命週期

js中this的指向有幾種情況 js中this的指向有幾種情況 May 06, 2024 pm 02:03 PM

js中this的指向有幾種情況

c++中函數的定義和呼叫可以巢狀嗎 c++中函數的定義和呼叫可以巢狀嗎 May 06, 2024 pm 06:36 PM

c++中函數的定義和呼叫可以巢狀嗎

閉包在 Java 中是如何實現的? 閉包在 Java 中是如何實現的? May 03, 2024 pm 12:48 PM

閉包在 Java 中是如何實現的?

See all articles