SORU
12 HAZİRAN 2009, Cuma


Nasıl referans bir değişken geçtim mi?

Python belgelerine parametreleri referans veya değer tarafından geçirilen olup olmadığı konusunda açık görünüyor, ve aşağıdaki kodu değişmeden değer üretir 'Orijinal'

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

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

Gerçek referans ile değişken geçmek için yapabileceğim bir şey var mı?

CEVAP
12 HAZİRAN 2009, Cuma


Değişkenler passed by assignment. Bunun arkasındaki gerekçe, iki yönlüdür:

  1. parametre geçti aslındabaşvuru(ama referans değeri tarafından geçirilen) bir nesne
  2. bazı veri türlerini değiştirilebilir, ama diğerleri değil

Yani:

  • Eğer başarılı olursakesilebilirnesnesine bir yöntem, bu yöntemi alır bir başvuru için, aynı nesne ve sen-ebilmek değişmek senin kalp zevk, ama eğer yeniden bağlayın, başvuru yöntemi, dış kapsam olacak hakkında hiçbir şey bilmiyorum, ve sonra senin işin bitti, dış referans olacak hala bir noktada orijinal nesne.

  • Eğer başarılı olursadeğişmezbir yöntem, nesne, hala dış referans bağlamanız yok, ve hatta nesne mutasyona edebilirsiniz.

Bunu daha açık hale getirmek için, hadi bazı örnekler var.

Liste - değişken bir tip

Hadi bir yönteme geçildi listesini değiştirmek için deneyin:

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

Çıkış:

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

Parametre geçirilen outer_list bir kopyasını değil, bir başvuru olduğu, mutasyona listesi yöntemlerini değiştirmek için kullanın ve değişiklikleri dış kapsam yansıması olabilir.

Şimdi bir parametre olarak iletilen başvuru değiştirmeye çalıştığınızda ne olur: 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

Çıkış:

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 parametre değeri tarafından kabul edilmesinden bu yana, yeni bir liste atama yöntemi dışında kod görebiliyordu hiçbir etkisi olmadı. the_list outer_list referans oldu, ve yeni bir liste için the_list noktası vardı, ama outer_list sivri yerleri değiştirmek için bir yolu yoktu.

Dize değişmez bir tip

Değişmez, dize içeriğini değiştirmek için yapabileceğimiz hiçbir şey yok

Şimdi, diyelim ki başvuru değiştirmeyi deneyin

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

Çıkış:

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 parametre değeri tarafından kabul edilmesinden bu yana, yeniden, yeni bir dize atama yöntemi dışında kod görebiliyordu hiçbir etkisi olmadı. the_string outer_string referans oldu, ve yeni bir dizeye the_string noktası vardı, ama outer_string sivri yerleri değiştirmek için bir yolu yoktu.

Bu işler biraz temizler umarım.

DÜZENLEME:Bu @David başlangıçta sorulan soruya cevap tutmaz oldu, "gerçek referans ile değişken geçmek için yapabileceğim bir şey var mı?". - O konuda çalışalım.

Bunu nasıl halledeceğiz?

@Andrea cevabı gösterdiği gibi, yeni değeri döndürür. Bu şeyler geçti, ama geri dışarı istediğiniz bilgileri gidelim mi değişmez:

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 istiyorsa, değeri ve işlevi haline geçmesi veya kullanım varolan bir sınıf için bir sınıf, bir liste gibi oluşturabilirsiniz:

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

Bu biraz hantal gibi görünse de.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Michael Lummio

    Michael Lumm

    25 Mayıs 2007
  • Phymec

    Phymec

    18 Temmuz 2009
  • THE RED DRAGON

    THE RED DRAG

    6 ŞUBAT 2009