Soru Bir değişkeni referans olarak nasıl geçebilirim?


Python belgeleri, parametrelerin referansa veya değere aktarılıp aktarılmadığı konusunda net değildir ve aşağıdaki kod değişmemiş değer 'Orijinal' üretmektedir.

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

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

Değişkeni gerçek referans ile geçmek için yapabileceğim bir şey var mı?


2055
2018-06-12 10:23


Menşei


Kısa bir açıklama / açıklama için ilk cevabı gör bu stackoverflow sorusu. Dizeler değişmez olduğundan, bunlar değiştirilmeyecek ve yeni bir değişken oluşturulacaktır, böylece "dış" değişken hala aynı değere sahiptir. - PhilS
BlairConrad'ın cevabındaki kod iyidir, ancak DavidCournapeau ve DarenThomas tarafından sağlanan açıklama doğrudur. - Ethan Furman
Seçilen cevabı okumadan önce lütfen bu kısa metni okumaya dikkat edin. Diğer diller "değişkenler" var, Python "isimleri" var. "Değişkenler" ve "referanslar" yerine "isimler" ve "nesneler" üzerine düşünün ve çok fazla benzer problemden kaçınmalısınız. - lqc
Neden bu gereksiz yere bir sınıf kullanıyor? Bu Java değil: P - Peter R
Başka bir geçici çözüm bu şekilde bir 'referans' oluşturmaktır: ref = type ('', (), {'n': 1}) stackoverflow.com/a/1123054/409638 - robert


Cevaplar:


Argümanlar ödevle geçti. Bunun ardındaki mantık iki yönlüdür:

  1. Geçilen parametre aslında bir referans bir nesneye (ancak referans değer ile geçirilir)
  2. bazı veri türleri değişebilir, ancak diğerleri değil

Yani:

  • Eğer bir değişken Bir yönteme nesne, yöntem aynı nesneye bir başvuru alır ve onu kalbinizin zevkine dönüştürür, ancak yöntemi referansta yeniden isimlendirirseniz, dış kapsam bu konuda hiçbir şey bilmez ve işiniz bittikten sonra, dış referans hala orijinal nesneyi gösterecektir.

  • Eğer bir değişmez bir yönteme karşı nesne, yine de dış referansı yeniden yapılandıramazsınız ve nesneyi bile değiştiremezsiniz.

Daha net bir hale getirmek için, bazı örnekler verelim.

Liste - değiştirilebilir tip

Bir yönteme geçirilen listeyi değiştirmeye çalışalım:

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)

Çıktı:

before, outer_list = ['one', 'two', 'three']
got ['one', 'two', 'three']
changed to ['one', 'two', 'three', 'four']
after, outer_list = ['one', 'two', 'three', 'four']

Geçirilen parametre bir referans olduğu için outer_listbir kopyasını değil, değiştirmek için mutasyona tabi tutulan liste yöntemlerini kullanabiliriz ve değişiklikleri dış kapsamda yansıtabiliriz.

Şimdi parametre olarak iletilen referansı değiştirmeye çalıştığımızda neler olacağını görelim:

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)

Çıktı:

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']

Beri the_list Parametre değeriyle aktarıldı, yeni bir liste atayarak yöntemin dışındaki kodun görebileceği bir etki yoktu. the_list bir kopyasıydı outer_list referans ve biz vardı the_list yeni bir listeye işaret et, fakat nerede değiştirileceğini hiçbir şekilde değiştiremedim outer_list işaretlendi.

Dize - değişmez tip

Bu değişmez, bu yüzden dizenin içeriğini değiştirmek için yapabileceğimiz bir şey yok.

Şimdi referansı değiştirmeye çalışalım.

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)

Çıktı:

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

Yine beri the_string parametresi, değerden geçirildi ve yeni bir dizenin atanması, yöntemin dışındaki kodun görebileceği bir etkiye sahip değildi. the_string bir kopyasıydı outer_string referans ve biz vardı the_string yeni bir dizeye işaret eder, ama nerede değiştirmenin bir yolu yoktu outer_string işaretlendi.

Umarım bu durumu biraz temizler.

DÜZENLE: Bu durumun, “Orijinal referansa göre değişkeni iletmek için yapabileceğim bir şey var mı?” Diye sorduğu soruya cevap vermediği belirtilmiştir. Hadi bunun üzerinde çalışalım.

Bunu nasıl aşarız?

Andrea'nın cevabı gösterdiği gibi, yeni değeri de geri alabilirsin. Bu, işlerin aktarılma şeklini değiştirmez, ancak geri dönmek istediğiniz bilgileri almanıza izin verir:

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)

Eğer gerçekten bir dönüş değeri kullanmaktan kaçınmak istiyorsanız, değerinizi tutmak ve onu işleve aktarmak veya bir liste gibi var olan bir sınıfı kullanmak için bir sınıf yaratabilirsiniz:

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])

Her ne kadar bu biraz hantal görünüyor.


2225
2018-06-12 11:18



O zaman, aynen, "referans olarak" geçtiğinizde, C'den aynıdır. değere göre referans ... "Referans ile" tanımlayın: P - Andrea Ambu
Şartlarını anladığımdan emin değilim. Bir süreliğine C oyunundan çıktım, ama geri döndüğümde, "referansla geçmek" olmadı - şeyleri geçebilirdiniz ve her zaman değerden geçiyordu, bu yüzden parametre listesinde ne varsa kopyalandı. Ama bazen bir şey, bir bellek parçası (ilkel, dizi, yapı, her neyse) izleyebilecek bir işaretçiydi, ancak işlevle işiniz bittiğinde, dış kapsamdan kopyalanan işaretçiyi değiştiremezdiniz. , orijinal işaretçi hala aynı adrese işaret etti. C ++, farklı şekilde davranan referansları tanıttı. - Blair Conrad
@Zac Bowling Gerçekten ne söylediğini anlamıyorum, pratik anlamda, bu cevap için. Bir Python yeni üyesi ref / val tarafından geçmeyi öğrenmek istediyse, o zaman bu yanıtın paket servisi şu şekildedir: 1- Sen kutu parametrenin yeni bir nesneye başvurmasını istemediğiniz sürece, bir değişkenin argümanları olarak aldığı referansı, bir değişkenin 'dış' değerini değiştirmek için kullanın. 2- Değişmez bir türe atama her zaman Dış değişkene yaptığınız referansı kıran yeni bir nesne oluşturun. - Cam Jackson
@CamJackson, daha iyi bir örneğe ihtiyacınız var - sayılar Python'da da değişmez nesnelerdir. Ayrıca şunu söylemek doğru olmaz. herhangi eşitliğin sol tarafında abonelik olmadan atama, değişmez olsun ya da olmasın yeni bir nesneye adını yeniden atayacaktır? def Foo(alist): alist = [1,2,3] irade değil Listenin içeriğini arayanların bakış açısından değiştirebilir. - Mark Ransom
-1. Gösterilen kod iyi, nasıl tamamen yanlış olduğu konusunda açıklama. DavidCournapeau veya DarenThomas tarafından verilen cevaplara, neden olduğu gibi doğru açıklamalar için bakın. - Ethan Furman


Problem, Python'da hangi değişkenlerin yanlış anlaşılmasından kaynaklanmaktadır. Geleneksel dillerin çoğuna alışkınsanız, aşağıdaki sırayla neler olduğuna dair bir zihinsel modeliniz vardır:

a = 1
a = 2

Buna inanıyorsun a değeri depolayan bir hafıza yeridir 1sonra değeri depolamak için güncellenir 2. Python'da işler böyle yürümüyor. Daha doğrusu, a değeri olan bir nesneye referans olarak başlar 1sonra, değeri olan bir nesneye referans olarak yeniden atanır. 2. Bu iki nesne bir arada var olmaya devam edebilir. a artık ilkine atıfta bulunmuyor; Aslında bunlar program içerisinde başka herhangi bir sayıda referansla paylaşılabilir.

Bir parametresi olan bir işlevi çağırdığınızda, iletilen nesneye başvuran yeni bir başvuru oluşturulur. Bu, işlev çağrısında kullanılan referanstan ayrıdır, bu nedenle bu referansı güncellemenin ve bir yeni nesne Örneğinde:

def __init__(self):
    self.variable = 'Original'
    self.Change(self.variable)

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

self.variable string nesnesine bir referanstır 'Original'. Aradığın zaman Change ikinci bir referans oluşturursunuz var nesneye İşlev içinde referansı yeniden atarsınız. var farklı bir string nesnesine 'Changed'ama referans self.variable ayrı ve değişmez.

Bunun etrafındaki tek yol, değişken bir nesneyi geçmek. Her iki referans da aynı nesneye başvurduğundan, nesnede yapılan her iki değişiklik de yansıtılır.

def __init__(self):         
    self.variable = ['Original']
    self.Change(self.variable)

def Change(self, var):
    var[0] = 'Changed'

530
2017-11-15 17:45



İyi özlü açıklama. "Bir işlev çağırdığınızda ..." paragrafınız, 'Python işlev parametrelerinin başvurulardan kaynaklandığı, değere göre geçirildiği' oldukça şifreli ifadeden duyduğum en iyi açıklamalardan biridir. Sanırım bu paragrafı tek başına anlarsanız, her şey bir anlamda mantıklı ve mantıklı bir sonuç olarak akar. O zaman yeni bir nesne oluştururken ve var olanı değiştirirken farkında olmanız gerekir. - Cam Jackson
Ancak referansı nasıl yeniden atayabilirsiniz? 'Var' adresini değiştiremeyeceğinizi düşündüm, ancak "Değişti" dizginiz artık 'var' hafıza adresinde saklanacaktı. Açıklamanız, "Değiştirildi" ve "Orijinal" in bunun yerine bellekte farklı yerlere benzediğini ve "var" ı farklı bir adrese geçirdiğinizi gösteriyor. Bu doğru mu? - Glassjawed
@Glassjawed, sanırım anlıyorsun. "Değiştirildi" ve "Orijinal", farklı bellek adreslerindeki iki farklı dize nesnesidir ve "var", diğerine işaret etmek için işaretleme diğerine geçilir. - Mark Ransom
Bu en iyi açıklamadır ve kabul edilen cevap olmalıdır. Kısa, özlü ve açık. Diğerleri ise 'referans değerden geçirilir', 'nesne olmak', vb. Gibi yeni ve kafa karıştırıcı terimlerle para kazanır. Bu cevap her şeyi temizler. Teşekkürler :) - ajay
id () işlevini kullanmak, konuların netleştirilmesine yardımcı olur, çünkü Python yeni bir nesne oluşturduğunda bunu netleştirir (bu yüzden, bence de). - Tim Richardson


Diğer cevapları uzun ve karmaşık buldum, bu yüzden Python'un değişkenleri ve parametreleri nasıl ele aldığını açıklamak için bu basit diyagramı oluşturdum. enter image description here


243
2017-09-04 16:05



Diğer cevapları aramamama rağmen, diyagramınız temeldeki konsepti aydınlatıyor. uzun ve karmaşık. - Bruce Wayne
Çok zarif bir açıklama. Diğer cevapların da uzun ve karmaşık olduğunu düşünüyorum. Aferin! - kirk.burleson
A'nın değişebilir olup olmadığı farketmez. B'ye farklı bir şey atarsanız A değişmez. Bir nesne değişebilir ise, emin olabilirsiniz. Ama bunun doğrudan bir isimle atama ile ilgisi yok .. - Martijn Pieters♦
Güncelleme için teşekkürler, çok daha iyi! Çoğu insanın bir aboneliğe ataması nedir? Örneğin. B[0] = 2doğrudan ödeve B = 2. - Martijn Pieters♦
"A, B'ye atandı" Bu belirsiz değil mi? Sıradan ingilizcede, A=B veya B=A. - Hatshepsut


Bu, ne de-değer-değer ya da referans-referanstır - bu, nesneye göre çağrıştır. Gördün mü, Fredrik Lundh:

http://effbot.org/zone/call-by-object.htm

İşte önemli bir alıntı:

"... değişkenler [isimler] değil nesneler; Diğer değişkenler tarafından belirtilemez veya nesneler tarafından belirtilemezler. "

Örneğinde, ne zaman Change yöntem denir ad bunun için yaratılmış; ve var dize nesnesi için bu ad alanında bir isim olur 'Original'. Bu nesnenin daha sonra iki ad alanında bir adı vardır. Sonraki, var = 'Changed' bağlandığı var yeni bir string nesnesine ve böylece yöntemin isim alanı unutur 'Original'. Son olarak, bu isim unutuldu ve dize 'Changed' onunla birlikte.


220
2018-06-12 12:55



Satın almayı zor buluyorum. Bana göre sadece Java, parametreler bellekteki nesneler için işaretçilerdir ve bu işaretçiler yığın üzerinden geçirilir veya kaydeder. - Luciano
Bu java gibi değil. Aynı olmadığı durumlardan biri de değişmez nesnelerdir. Önemsiz işlevi düşünün lambda x: x. Bunu x = [1, 2, 3] ve x = (1, 2, 3) için uygulayın. İlk durumda, döndürülen değer girişin bir kopyası ve ikinci durumda aynı olacaktır. - David Cournapeau
Hayır kesinlikle Java'nın nesneler için semantiği gibi. "İlk durumda, döndürülen değer girişin bir kopyası ve ikinci durumda aynı olacaktır" ile ne demek istediğinden emin değilim. ama bu ifade açıkça yanlış görünüyor. - Mike Graham
Java ile tam olarak aynıdır. Nesne referansları, değere göre geçirilir. Farklı düşünen herkes Python kodunu bir swap Bunun gibi iki referansı değiştirebilen işlev: a = [42] ; b = 'Hello'; swap(a, b) # Now a is 'Hello', b is [42] - cayhorstmann
Java'daki nesneleri geçirdiğinizde Java ile tamamen aynıdır. Ancak, Java, ilkel değerini kopyalayarak geçirilen ilkel öğelere de sahiptir. Böylece bu durumda farklıdırlar. - Claudiu


Geçilen şeyleri düşünün atama yoluyla referans / değer yerine. Bu şekilde, her şey açıktır, normal atama sırasında ne olduğunu anladığınız sürece neler oluyor.

Böylece, bir listeye bir fonksiyon / metot aktarılırken, liste parametre adına atanır. Listeye eklemek, listenin değiştirilmesine neden olur. Listeyi yeniden atama içeride işlev orijinal listeyi değiştirmeyecektir, çünkü:

a = [1, 2, 3]
b = a
b.append(4)
b = ['a', 'b']
print a, b      # prints [1, 2, 3, 4] ['a', 'b']

Değişmez tipler değiştirilemediğinden görünmek değere göre geçirilmek gibi - int işlevine geçirme int işlev parametrelerini atamak anlamına gelir. Bunu yalnızca yeniden atayabilirsiniz, ancak orijinal değişkenler değerini değiştirmez.


142
2018-06-12 12:17



İlk bakışta bu cevap orijinal soruyu tersine çeviriyor gibi görünüyor. İkinci bir okumadan sonra, bunun konuyu oldukça açık bir hale getirdiğini fark etmeye başladım. Bu "isim ataması" konseptine iyi bir şekilde ulaşmak için şu adrese ulaşabilirsiniz: Pythonista gibi kod: Idiomatic Python - Christian Groleau


Effbot (Fredrik Lundh), Python'un değişme stilini çağrı-nesne olarak tanımlamıştır: http://effbot.org/zone/call-by-object.htm

Nesneler yığına tahsis edilir ve onlara işaretçiler her yere iletilebilir.

  • Gibi bir ödev yaptığınızda x = 1000, geçerli ad alanındaki "x" dizesini bin içeren tamsayı nesnesine bir işaretçi ile eşleyen bir sözlük girişi oluşturulur.

  • "X" ile güncellediğinizde x = 2000, yeni bir tamsayı nesnesi oluşturulur ve sözlük yeni nesneye işaret edecek şekilde güncelleştirilir. Eski bin tane nesne değişmez (ve başka herhangi bir nesneye atıfta bulunup bulunmadığına bağlı olarak canlı olabilir veya olmayabilir).

  • Gibi yeni bir ödev yaptığınızda y = x"x" için giriş ile aynı nesneyi işaret eden "y" adlı yeni bir sözlük girişi oluşturulur.

  • Dizeler ve tamsayılar gibi nesneler değişmez. Bu basitçe, oluşturulduktan sonra nesneyi değiştirebilecek hiçbir yöntem olmadığı anlamına gelir. Örneğin, bir bin tamsayı nesnesi oluşturulduğunda, hiçbir zaman değişmeyecektir. Matematik, yeni tamsayı nesneleri oluşturarak yapılır.

  • Listeler gibi nesneler değişken. Bu, nesnenin içeriğinin nesneye işaret eden herhangi bir şeyle değiştirilebileceği anlamına gelir. Örneğin, x = []; y = x; x.append(10); print y basacak [10]. Boş liste oluşturuldu. Hem "x" hem de "y" aynı listeye işaret eder. eklemek yöntem, liste nesnesini (bir veritabanına bir kayıt eklemek gibi) değiştirir (güncelleştirir) ve sonuç hem "x" hem de "y" için görünürdür (tıpkı bir veritabanı güncellemesi, bu veritabanına yapılan her bağlantı için görünür olduğu gibi).

Umarım bu konuyu açıklığa kavuşturur.


53
2018-03-29 04:41



Bunu bir geliştiriciden öğrenmeyi çok takdir ediyorum. Doğru mu id() pepr'ın cevabı önerdiği gibi, işlev işaretçinin (nesne referansı) değerini döndürür? - Honest Abe
@HonestAbe Evet, CPython’da İD() adresi döndürür. Ama PyPy ve Jython gibi diğer pitonlarda İD() sadece benzersiz bir nesne tanımlayıcısıdır. - Raymond Hettinger
Diğer cevaplar beni şaşırttı ve kafası karıştı. Bu her şeyi temizledi. Teşekkürler. - shongololo
Bu yanıt, ayrıca bir atamanın varolan bir adı yeni bir nesneye bağladığını gösteren id () 'i kullanma ipucu, tüm iş parçacığının en iyisidir. - Tim Richardson
Bu cevap cezai olarak mahkum edildi. - wandadars


Teknik olarak, Python her zaman referans değerlerine göre geçiş kullanır. Tekrarlayacağım diğer cevabım ifademi desteklemek için.

Python her zaman referans-değer değerleri kullanır. İstisna yoktur. Herhangi bir değişken atama referans değerinin kopyalanması anlamına gelir. İstisna yok. Herhangi bir değişken referans değerine bağlı isimdir. Her zaman.

Referans değerinin hedef nesnenin adresi olarak düşünebilirsiniz. Kullanıldığı zaman adres otomatik olarak iptal edilir. Bu şekilde referans değeriyle çalışmak, doğrudan hedef nesne ile çalışıyor gibi görünüyor. Ama her zaman arasında bir referans var, hedefe atlamak için bir adım daha.

İşte Python'un referans olarak geçmeyi kullandığını kanıtlayan örnek:

Illustrated example of passing the argument

Eğer argüman değerden geçerse, dış lst değiştirilemedi. Yeşil, hedef nesnelerdir (siyah, içinde depolanan değerdir, kırmızı nesne tipi kırmızıdır), sarı, içteki referans değeri olan bir hafızadır - ok olarak çizilmiş. Mavi katı ok, işleve (kesikli mavi ok yolu ile) aktarılan referans değerdir. Çirkin koyu sarı iç sözlüktür. (Aslında yeşil bir elips olarak da çizilebilir. Renk ve şekil sadece iç olduğunu söylüyor.)

Kullanabilirsiniz id() referans değerinin ne olduğunu (yani, hedef nesnenin adresi) öğrenmek için yerleşik işlev.

Derlenmiş dillerdeki bir değişken, türün değerini yakalayabilen bir bellek alanıdır. Python'da bir değişken, hedef nesneyi referans değerini tutan referans değişkenine bağlı bir addır (içsel olarak bir dize olarak yakalanır). Değişkenin adı, iç sözlükteki anahtardır, bu sözlük öğesinin değer kısmı, referans değerini hedefe depolar.

Referans değerler Python'da gizlenmiştir. Referans değerini saklamak için açık bir kullanıcı tipi yok. Bununla birlikte, bir liste elemanını (veya başka bir uygun konteyner tipindeki eleman) referans değişken olarak kullanabilirsiniz, çünkü tüm kaplar elemanları aynı zamanda hedef nesnelere referans olarak depolar. Başka bir deyişle, elemanlar aslında kabın içinde yer almaz - sadece elementlere yapılan referanslar.


53
2017-09-15 18:53



Aslında bu referans değerine göre onaylandı. Bu cevap için +1, örnek iyi değildi. - BugShotGG
Yeni terminoloji icat etmek ("referans değere geçmek" veya "nesneye göre ara" gibi) yararlı değildir). "Çağrı (değer | referans | isim)" standart terimlerdir. "referans" standart bir terimdir. Referansları değere göre aktarmak, standart terminolojiyi kullanarak Python, Java ve diğer dillerin bir dizi davranışını doğru bir şekilde tanımlar. - cayhorstmann
@cayhorstmann: Sorun şu ki Python değişkeni Diğer dillerde olduğu gibi aynı terminoloji anlamı yoktur. Bu yoldan, referans ile arayın burada iyi uymuyor. Ayrıca nasılsınız? kesinlikle terimi tanımlar referans? Gayri resmi olarak, Python yolu, nesnenin adresini geçerek kolayca tanımlanabilir. Ancak, Python'un potansiyel olarak dağıtılmış bir uygulamasına uymuyor. - pepr
Bu cevabı beğeniyorum, ancak örneğin gerçekten yardımcı olup olmadığını veya akışa zarar vereceğini düşünebilirsiniz. Ayrıca, 'referans değeri'ni' nesne referansı 'ile değiştirirseniz, burada görüldüğü gibi' resmi 'olarak değerlendirebileceğimiz terminolojiyi kullanırdınız: Tanımlama Fonksiyonları - Honest Abe
Bu teklifin sonunda belirtilen bir dipnot bulunmaktadır: "Aslında, nesne referansı ile çağrı Daha iyi bir açıklama olurdu, çünkü bir değişebilir nesne geçtiyse, arayan kişi callee'nin yaptığı değişiklikleri görecektir ... " Diğer dillerle kurulan terminolojiye uymaya çalışmaktan kaynaklanan karışıklığın neden olduğu konusunda hemfikirim. Semantikler bir yana, anlaşılması gerekenler şunlardır: sözlükler / ad alanları, ad bağlama işlemleri ve isim → işaretçi → nesnesi arasındaki ilişki (zaten bildiğiniz gibi). - Honest Abe


Normalde kullandığım basit bir oyun sadece bir listeye sarmaktır:

def Change(self, var):
    var[0] = 'Changed'

variable = ['Original']
self.Change(variable)      
print variable[0]

(Evet, bunun rahatsız edici olabileceğini biliyorum, ancak bazen bunu yapmak için yeterince basittir.)


36
2017-08-05 22:52



Python sorununa önemli bir çözüm getiren az miktarda metin için +1, referansa sahip değil. (Bu sayfadaki herhangi bir yerde olduğu gibi burada da takip eden bir yorum / soru olarak: Python'un neden C # gibi bir "ref" anahtar sözcüğü sağlayamadığı açık değildir, bu sadece arayanın argümanını Bu, ve listenin 0 öğesi olarak işlev içindeki argümana referansları tedavi edin.) - M Katz
Güzel. Ref tarafından geçmek için, [] 'da sarın. - Justas
Büyük, tüm pontification kaçınmak için aferin. - Puffin


(edit - Blair muazzam popüler cevabını güncelledi, böylece şimdi doğru çıktı)

En çok oyu alan (Blair Conrad) mevcut gönderinin sonucuna göre doğru olmakla birlikte, yanıltıcı olduğunu ve tanımlarına dayanarak sınır çizgisinin yanlış olduğunu belirtmenin önemli olduğunu düşünüyorum. Kullanıcının referansla geçmesine ya da değere göre geçmesine izin veren birçok dil (C gibi) olsa da, Python bunlardan biri değildir.

David Cournapeau'nun cevabı, gerçek cevaba işaret ediyor ve Blair Conrad'ın görevindeki davranışların neden tanımları doğru olmasa da neden doğru olduğunu açıklıyor.

Python'un değere göre geçtiği ölçüde, bazı diller veri (bir "değer" veya bir "referans") olması gerektiğinden, tüm diller değerden geçmektedir. Bununla birlikte, bu, Python'un bir C programlayıcısının düşüneceği anlamda değerden geçtiği anlamına gelmez.

Davranışları istersen, Blair Conrad'ın cevabı iyi. Ama eğer Python'un neden değerden geçmediğini ya da referans olarak geçmediğinin somunlarını ve civatalarını bilmek istiyorsanız, David Cournapeau'nun cevabını okuyun.


34
2018-06-27 12:33



Evet, David Cournapeau'nun verdiği bağlantıların daha eksiksiz bir açıklama olduğunu düşünüyorum. - David Sykes
Tüm dillerin değere göre çağrı yapıldığı doğru değildir. C ++ veya Pascal'da (ve bilmediğim pek çok başkaları), referans olarak aradınız. Örneğin, C ++’da void swap(int& x, int& y) { int temp = x; x = y; y = temp; } iletilen değişkenleri değiştirir. Pascal'da kullanıyorsun var yerine &. - cayhorstmann
Bunu uzun zaman önce cevapladığımı sandım ama göremiyorum. Tamlığı için - cayhorstmann cevabımı yanlış anladı. Ben her şeyin değeri ile çağrı olduğunu söylemiyordum Çoğu insanın C / C ++ ile ilgili ilk öğrendiği terimlerle. Bu sadece bazı değer iletilir (değer, isim, işaretçi vb.) ve Blair'in orijinal yanıtında kullanılan terimlerin yanlış olduğu. - KobeJohn