2011-11-18 10 views
6

Weźmy następujący kodMyślałem, że Python przekazał wszystko przez odniesienie?

#module functions.py 
def foo(input, new_val): 
    input = new_val 

#module main.py 
input = 5 
functions.foo(input, 10) 

print input 

myślałem wejście będzie teraz 10. Dlaczego nie jest to przypadek?

+0

Możesz się pomylić przez wywołanie zmiennej lokalnej "input" w definicji funkcji foo. Ponadto, co Sven powiedział w odpowiedziach. – phkahler

+6

Gdziekolwiek przeczytałeś, że Python przekazuje wszystko przez odniesienie, były one błędne. –

Odpowiedz

13

Wszystko jest przekazywane wartością, ale ta wartość jest odniesieniem do oryginalnego obiektu. Jeśli zmodyfikujesz obiekt, zmiany będą widoczne dla osoby dzwoniącej, ale nie możesz ponownie przypisać imion. Co więcej, wiele obiektów jest niezmiennych (int, float, stringi, krotki).

+8

"[Idiomatic Python] (http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#other-languages-have-variables)" dobrze ilustruje to zjawisko. –

+1

Python nie jest wartością typu call-by-value ani call-by-reference, zobacz moją odpowiedź dla szczegółów. –

+1

@skyhisi: Twoja odpowiedź jest w zasadzie taka sama jak moja, z wyjątkiem użycia niestandardowego terminu "zadzwoń przez obiekt", którego celowo uniknąłem, ponieważ nic nie wyjaśnia. –

8

Wewnątrz foo wiążemy lokalną nazwę input z innym obiektem (10). W kontekście wywołania nazwa input nadal odnosi się do obiektu 5.

5

Przypisanie w Pythonie nie modyfikuje obiektu w miejscu. Ponownie łączy nazwę, aby po input = new_val zmienna lokalna input otrzymała nową wartość.

Jeśli chcesz zmodyfikować „na zewnątrz” input, trzeba zawinąć go wewnątrz zmienny obiektu, takiego jak liście jeden element:

def foo(input, new_val): 
    input[0] = new_val 

foo([input]) 

Python nie przechodzą przez referencję dokładnie sposób działania przekazywania referencji w C++. W tym przypadku, co najmniej, to bardziej jakby każdy argument jest wskaźnikiem C/C++:

// effectively a no-op! 
void foo(object *input, object *new_val) 
{ 
    input = new_val; 
} 
+0

dzięki za odpowiedzi wszystkich ... ta metoda, którą zasugerowałeś, wydaje się prawie jak hack, czy to standardowa procedura? czy istnieją inne sposoby modyfikowania niezmiennych typów, które są bardziej pythonic? (Domyślam się, że "modyfikuj niezmienne typy" odpowiada na moje własne pytanie, ale mimo to zapytam ...) – Ferguzz

+0

@Ferguzz Nie można modyfikować obiektów niemożliwych z definicji. Ale czy o to właśnie chciałeś zapytać? Jak dotąd nie wymieniono jeszcze niezmiennych obiektów. Fakt, że 'var = ...' nie modyfikuje żadnego obiektu lub jakakolwiek inna zmienna nie ma nic wspólnego z niezmiennością. Po prostu nie można spowodować, aby jedno przypisanie zmiennej zmieniło inną zmienną, tak jak nie można wprowadzać zmian w jednej liście na innej liście. – delnan

+0

i odniosłem się do linii w tej odpowiedzi "zawiń ją wewnątrz zmiennego obiektu, takiego jak lista". Próbowałem zapytać, czy istnieje sposób na modyfikację zmiennej, jak w moim oryginalnym wpisie, bez robienia tego? – Ferguzz

3

Python jest ani wartość call-by-czy call-by-reference, to Call By Object.

"Argumenty są przekazywane przez Call-by-dzielenie, podobny do call-by-value, wyjątkiem że argumenty są obiektami i mogą być zmieniane tylko wtedy, gdy są one zmienne."

+1

Ładne podsumowanie, ale nadal uważam, że wywołanie po obiekcie nie różni się od wywołania po wartości, przy czym wszystkie "wartości" są obsługiwane (~ = wskaźniki) do obiektów. – Kos

Powiązane problemy