Bir de─či┼čkeni referans olarak nas─▒l iletirim?


Al─▒nan cevaba git


Python dok├╝mantasyonu, parametrelerin referans veya de─čer taraf─▒ndan iletilip iletilmedi─či konusunda net de─čil gibi g├Âr├╝nmektedir ve a┼ča─č─▒daki kod, 'Orijinal' de─či┼čmemi┼č de─čerini ├╝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 referansla iletmek i├žin yapabilece─čim bir ┼čey var m─▒?


2446









Cevap say─▒s─▒n─▒ say: 26






Arg├╝manlar atama ile ge├žirilir . Bunun arkas─▒ndaki mant─▒k iki y├Ânl├╝d├╝r:

  1. ge├žirilen parametresinin a, referans bir nesneye (ancak bir referans de─čeri ile ge├žirilir)
  2. baz─▒ veri t├╝rleri de─či┼čkendir, ancak baz─▒lar─▒ de─čildir

Yani:

  • E─čer bir ge├žerseniz de─či┼čken bir y├Ântem haline nesneyi, y├Ântem ayn─▒ nesneye bir ba┼čvuruyu al─▒r ve siz g├Ânl├╝n├╝ze onu mutasyona, ancak y├Ânteminde referans rebind e─čer, d─▒┼č kapsam sonra bu konuda hi├žbir ┼čey biliyorum ve edecek Tamamlad─▒─č─▒n─▒zda, d─▒┼č referans yine de orijinal nesneyi g├Âsterecektir.

  • Bir ba┼čar─▒l─▒ olursa iletmenin bir y├Ântemi nesne, yine d─▒┼č ba┼čvuru rebind de─čildir, ve hatta nesne mutasyona olamaz.

Daha da netle┼čtirmek i├žin baz─▒ ├Ârnekler verelim.

Liste - de─či┼čken bir t├╝r

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

Girilen parametre outer_list bir kopyas─▒na referans oldu─čundan , de─či┼čtirmek i├žin mutasyona dayal─▒ liste y├Ântemlerini kullanabilir ve de─či┼čikliklerin d─▒┼č kapsamda yans─▒t─▒lmas─▒n─▒ sa─člayabiliriz.

┼×imdi parametre olarak iletilen referans─▒ de─či┼čtirmeye ├žal─▒┼čt─▒─č─▒m─▒zda ne 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']
 

Yana the_list parametre kendisine yeni bir liste atayarak, de─čeri taraf─▒ndan kabul edildi y├Ântemle d─▒┼č─▒nda kod g├Ârebildi─čini hi├žbir etkisi olmad─▒. the_list Bir kopyas─▒ olan outer_list referans ve biz vard─▒ the_list yeni listeye noktas─▒, ama de─či┼čtirmek i├žin hi├žbir yolu yoktu outer_list sivri.

Dize - de─či┼čmez bir t├╝r

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, the_string parametre de─čere g├Âre ge├žti─činden, ona yeni bir dize ataman─▒n, y├Ântemin d─▒┼č─▒ndaki kodun g├Ârebilece─či bir etkisi olmad─▒. the_string Bir kopyas─▒ olan outer_string referans ve biz vard─▒ the_string yeni bir dizeye noktas─▒, ama de─či┼čtirmek i├žin hi├žbir yolu yoktu outer_string sivri.

Umar─▒m bu i┼čleri biraz temizler.

EDIT: Bunun, @David'in "De─či┼čkeni ger├žek referansa g├Âre iletmek i├žin yapabilece─čim bir ┼čey var m─▒?" Diye sordu─ču soruyu cevaplamad─▒─č─▒ belirtildi. Bunun ├╝zerinde ├žal─▒┼čal─▒m.

Bunu nas─▒l ├ž├Âzece─čiz?

@ Andrea'n─▒n cevab─▒n─▒n g├Âsterdi─či gibi, yeni de─čeri geri verebilirsin. Bu, i┼člerin aktar─▒lma ┼čeklini de─či┼čtirmez, ancak geri almak 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)
 

Bir d├Ân├╝┼č de─čeri kullanmaktan ka├ž─▒nmak istiyorsan─▒z, de─čerinizi tutmak ve i┼čleve aktarmak veya bir s─▒n─▒f gibi mevcut bir s─▒n─▒f─▒ kullanmak i├žin bir s─▒n─▒f 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 g├Âr├╝n├╝yor olsa da.


2636







Sorun Python'da hangi de─či┼čkenlerin bulundu─čunun yanl─▒┼č anla┼č─▒lmas─▒ndan kaynaklanmaktad─▒r. Geleneksel dillerin ├žo─čuna al─▒┼čk─▒nsan─▒z, a┼ča─č─▒daki s─▒rada ne oldu─čuna dair zihinsel bir modeliniz vard─▒r:

 a = 1
a = 2
 

Bunun a de─čeri depolayan bir haf─▒za yeri oldu─čuna inan─▒yorsunuz 1 , ard─▒ndan de─čeri depolamak i├žin g├╝ncelleniyor 2 . Python'da i┼čler b├Âyle y├╝r├╝m├╝yor. Aksine, a de─čeri olan bir nesneye referans olarak ba┼člar 1 , ard─▒ndan de─čeri olan bir nesneye referans olarak atan─▒r 2 . Bu iki nesne ra─čmen bir arada devam edebilir a art─▒k ilki ifade etmez; Asl─▒nda, programdaki herhangi bir say─▒da ba┼čka referansla payla┼č─▒labilirler.

Parametreli bir i┼člevi ├ža─č─▒rd─▒─č─▒n─▒zda, i├žeri aktar─▒lan nesneyi ifade eden 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 onu referans olarak g├Âstermesinin bir yolu yoktur. yeni nesne ├ľrnekte:

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

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

self.variable string nesnesine bir ba┼čvuru 'Original' . Arad─▒─č─▒n─▒zda , nesneye Change ikinci bir referans olu┼čturun var . ─░┼člev i├žinde referans─▒ var farkl─▒ bir dize nesnesine atars─▒n─▒z 'Changed' , ancak ba┼čvuru self.variable ayr─▒d─▒r ve de─či┼čmez.

Bunun etraf─▒ndaki tek yol de─či┼čken bir nesneyi ge├žmek. Her iki referans da ayn─▒ nesneye g├Ânderme yapt─▒─č─▒ i├žin, nesnede yap─▒lan de─či┼čiklikler her iki yerde de yans─▒t─▒l─▒r.

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

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

637







Di─čer cevaplar─▒ olduk├ža 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 ┼čemay─▒ haz─▒rlad─▒m.
g├Âr├╝nt├╝ tan─▒m─▒n─▒ buraya girin


301







Bu de─čer by-pass veya ba┼čvuru-by-pass - nesne taraf─▒ndan ├ža─čr─▒land─▒r. Fredrik Lundh'un ┼čuna bak─▒n:

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

─░┼čte ├Ânemli bir teklif:

"... de─či┼čkenler [isimler] nesneler de─čil ; di─čer de─či┼čkenler taraf─▒ndan g├Âsterilemezler veya nesneler taraf─▒ndan belirtilemezler."

├ľrnekte, Change y├Ântem ├ža─čr─▒ld─▒─č─▒nda - bunun i├žin bir ad alan─▒ olu┼čturulur; ve var dize nesnesi i├žin bu ad alan─▒n─▒n i├žinde bir ad olur 'Original' . Bu nesnenin daha sonra iki ad alan─▒nda bir ad─▒ vard─▒r. Daha sonra, yeni bir dize nesnesine var = 'Changed' ba─član─▒r var ve b├Âylece y├Ântemin ad alan─▒ unutur 'Original' . Son olarak, bu ad alan─▒ unutulur ve 'Changed' bununla birlikte dize .


232







Referans / de─čer yerine atama ile ge├žen ┼čeyleri d├╝┼č├╝n├╝n . Bu ┼čekilde, her ┼čey a├ž─▒kt─▒r, normal g├Ârevde ne oldu─čunu anlad─▒─č─▒n─▒z s├╝rece ne olup bitti─čini.

Bu nedenle, bir listeyi bir fonksiyona / y├Ânteme ge├žirirken, liste parametre ismine atan─▒r. Listeye eklemek listenin de─či┼čtirilmesine neden olacakt─▒r. Listeyi i┼člev i├žinde yeniden atamak, as─▒l 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 t├╝rler de─či┼čtirilemedi─činden, de─čer taraf─▒ndan iletiliyor gibi g├Âr├╝nmektedir - int'yi bir i┼člev parametresine atayan bir i┼člev arac─▒na ge├žirme. Bunu yaln─▒zca yeniden atayabilirsiniz, ancak orijinal de─či┼čkenlerin de─čerini de─či┼čtirmez.


161







Effbot (aka Fredrik Lundh) Python'un de─či┼čken ge├ži┼č stilini "├ža─čr─▒ nesnesi" olarak tan─▒mlam─▒┼čt─▒r: http://effbot.org/zone/call-by-object.htm

Nesneler ├Âbek ├╝zerinde tahsis edilir ve onlara i┼čaret├žiler her yerden ge├žirilebilir.

  • B├Âyle bir atama yapt─▒─č─▒n─▒zda x = 1000 , ge├žerli ad alan─▒ndaki "x" dizesini bin i├žeren tamsay─▒ nesnesine bir i┼čaret├žiyle e┼čle┼čtiren bir s├Âzl├╝k giri┼či olu┼čturulur.

  • "X" ile g├╝ncelleme yapt─▒─č─▒n─▒zda x = 2000 , yeni bir tamsay─▒ nesnesi olu┼čturulur ve s├Âzl├╝k yeni nesneyi g├Âsterecek ┼čekilde g├╝ncellenir. Eski bin nesne de─či┼čmez (ve ba┼čka bir ┼čeyin nesneye at─▒fta bulunup bulunmad─▒─č─▒na ba─čl─▒ olarak canl─▒ olabilir veya olmayabilir).

  • B├Âyle yeni bir ├Âdev yapt─▒─č─▒n─▒zda y = x , "x" i├žin ayn─▒ nesneyi g├Âsteren "y" yeni bir s├Âzl├╝k giri┼či olu┼čturulur.

  • Dizeler ve tam say─▒lar gibi nesneler de─či┼čmezdir . Bu basit├že, nesneyi olu┼čturulduktan sonra de─či┼čtirebilecek hi├žbir y├Ântem olmad─▒─č─▒ anlam─▒na gelir. ├ľrne─čin, bir tamsay─▒ nesnesi bin kez olu┼čturulduktan sonra, asla de─či┼čmeyecektir. Matematik yeni tamsay─▒l─▒ nesneler olu┼čturarak yap─▒l─▒r.

  • Listeler gibi nesneler de─či┼čkendir . Bu, nesnenin i├žeri─činin, nesneyi g├Âsteren herhangi bir ┼čeyle de─či┼čtirilebilece─či anlam─▒na gelir. ├ľrne─čin, x = []; y = x; x.append(10); print y yazd─▒racak [10] . Bo┼č liste olu┼čturuldu. Hem "x" hem de "y" ayn─▒ listeye i┼čaret ediyor. Ekleme y├Ântemi (bir veritaban─▒na bir kay─▒t ekleme) mutasyon (g├╝ncellemeler) liste nesnesi ve sonu├ž her iki "x" ve "y" taraf─▒ndan g├Âr├╝lebilir (sadece bir veritaban─▒ g├╝ncelleme olarak bu veritaban─▒na her ba─člant─▒ i├žin g├Âr├╝n├╝r olacakt─▒r).

Umar─▒m bu konuyu sizin i├žin netle┼čtirir.


63







Teknik olarak, Python her zaman referans de─čerlerine g├Âre pass kullan─▒r . ─░fademi desteklemek i├žin di─čer cevab─▒m─▒ tekrarlayaca─č─▒m .

Python her zaman referans referans de─čerlerini kullan─▒r. ─░stisna yok. Herhangi bir de─či┼čken atama referans de─čerini kopyalamak anlam─▒na gelir. ─░stisna yok. Herhangi bir de─či┼čken referans de─čerine ba─čl─▒ isimdir. Her zaman.

Bir referans de─čeri hakk─▒nda hedef nesnenin adresi olarak d├╝┼č├╝nebilirsiniz. Kullan─▒ld─▒─č─▒nda, adres otomatik olarak kald─▒r─▒l─▒r. Bu ┼čekilde, referans de─čeriyle ├žal─▒┼čmak, do─črudan hedef nesneyle ├žal─▒┼čmak gibi g├Âr├╝n├╝yor. Ancak, her zaman aras─▒nda bir hedefe atlamak i├žin bir ad─▒m daha bir referans vard─▒r.

Python'un referans olarak ge├ženleri kulland─▒─č─▒n─▒ ispatlayan ├Ârnek:


Arg├╝man─▒ iletmenin resimli ├Ârne─či

E─čer arg├╝man de─čere g├Âre iletildiyse, d─▒┼č lst de─či┼čtirilemez. Ye┼čil, hedef nesnelerdir (siyah, i├žinde depolanan de─čer, k─▒rm─▒z─▒, nesne t├╝r├╝d├╝r), sar─▒, i├žinde referans de─čeri olan - ok ┼čeklinde ├žizilen haf─▒zad─▒r. Mavi kat─▒ ok, i┼čleve iletilen referans de─čeridir (kesik mavi ok yolu ile). ├çirkin koyu sar─▒ i├ž s├Âzl├╝kt├╝r. (Asl─▒nda ye┼čil bir elips olarak da ├žizilebilir. Renk ve ┼čekil yaln─▒zca i├ž oldu─čunu s├Âyler.)

id() Referans de─čerin ne oldu─čunu (yani hedef nesnenin adresi) ├Â─črenmek i├žin yerle┼čik i┼člevi kullanabilirsiniz.

Derlenmi┼č dillerde de─či┼čken, t├╝r├╝n de─čerini yakalayabilen bir bellek alan─▒d─▒r. Python'da de─či┼čken, referans de─čerini hedef nesneye tutan referans de─či┼čkenine ba─čl─▒ bir add─▒r (dahili olarak bir dize olarak yakalan─▒r). De─či┼čkenin ad─▒ dahili s├Âzl├╝kteki anahtard─▒r, bu s├Âzl├╝k ├Â─česinin de─čer k─▒sm─▒ referans de─čerini hedefe saklar.

Referans de─čerler Python'da gizlidir. Referans de─čerini kaydetmek i├žin a├ž─▒k bir kullan─▒c─▒ tipi yoktur. Ancak, referans de─či┼čken olarak bir liste ├Â─česini (veya di─čer uygun konteyner t├╝r├╝ndeki bir ├Â─čeyi) kullanabilirsiniz, ├ž├╝nk├╝ t├╝m kaplar ├Â─čeleri hedef hedeflere referans olarak saklarlar. Ba┼čka bir deyi┼čle, elemanlar asl─▒nda kap i├žinde bulunmaz - sadece elemanlara referanslar.


59


2012-09-15





Python'da de─či┼čken yok

Parametre ge├ži┼čini anlaman─▒n anahtar─▒ "de─či┼čkenler" hakk─▒nda d├╝┼č├╝nmeyi b─▒rakmakt─▒r. Python'da isimler ve nesneler var ve birlikte de─či┼čkenler gibi g├Âr├╝n├╝yorlar, ancak ├╝├ž├╝ her zaman ay─▒rt etmek faydal─▒d─▒r.

  1. Python'un adlar─▒ ve nesneleri vard─▒r.
  2. Atama bir nesneye bir isim ba─člar.
  3. Bir fonksiyona bir arg├╝man iletmek ayn─▒ zamanda bir nesneye bir isim (i┼člevin parametre ismi) ba─člar.

Hepsi bu kadar. De─či┼čebilirlik bu soru i├žin ├Ânemli de─čil.

├ľrnek:

 a = 1
 

Bu, ad─▒ a 1 de─čerini tutan integer t├╝r├╝ndeki bir nesneye ba─člar .

 b = x
 

Bu, ad─▒ b , o x anda ba─čl─▒ oldu─ču nesneye ba─člar . Daha sonra, ismin b art─▒k isimle hi├žbir ilgisi yoktur x .

Python 3 dil referans─▒ndaki b├Âl├╝m 3.1 ve 4.2'ye bak─▒n─▒z .

Sorudaki ├Ârnek nas─▒l okunur?

Soruda g├Âsterilen kodda, ifade (i┼člev kapsam─▒ndaki ) de─čeri tutan nesneye self.Change(self.variable) ba─člar ve atama (i┼člev g├Âvdesinde ) ayn─▒ ad─▒ tekrar atar: ba┼čka bir nesneye (bu olur) bir ipi de tutmak ama tamamen ba┼čka bir ┼čey olabilirdi). var Change 'Original' var = 'Changed' Change

Referans ile nas─▒l ge├žilir

(d├╝zenleme 2019-04-28)

Bu nedenle, de─či┼čtirmek istedi─činiz ┼čey de─či┼čtirilebilir bir nesne ise, her ┼čey etkili bir ┼čekilde referans yoluyla iletildi─či i├žin sorun yoktur.

Bir ise de─či┼čmez nesne (├Ârne─čin bir mant─▒ksal de─čer, say─▒, dize), hareket yolu bir de─či┼čken nesne sar─▒n etmektir.
Bu kirli h─▒zl─▒ ve-├ž├Âzeltisi (yerine tek eleman listesi self.variable ge├žmesi, [self.variable] ve fonksiyon olarak modifiye var[0] ).
Daha pitonik yakla┼č─▒m, ├Ânemsiz, tek ├Âzellikli bir s─▒n─▒f─▒ tan─▒tmak olacakt─▒r. ─░┼člev s─▒n─▒f─▒n bir ├Ârne─čini al─▒r ve niteli─či de─či┼čtirir.


46







Normalde kulland─▒─č─▒m basit bir p├╝f noktas─▒ sadece listeye sarmakt─▒r:

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

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

(Evet, bunun uygunsuz olabilece─čini biliyorum, ama bazen bunu yapmak i├žin yeterince basit.)


42







(d├╝zenleme - Blair, ┼ču anda do─čru olmas─▒ i├žin son derece pop├╝ler olan yan─▒t─▒n─▒ g├╝ncelledi)

En fazla oy alan mevcut yay─▒nlar─▒n (Blair Conrad taraf─▒ndan) sonu├žlar─▒na g├Âre do─čru olmas─▒na ra─čmen yan─▒lt─▒c─▒ oldu─čunu ve tan─▒mlar─▒na g├Âre s─▒n─▒rda yanl─▒┼č oldu─čunu not etmenin ├Ânemli oldu─čunu d├╝┼č├╝n├╝yorum. Python, kullan─▒c─▒n─▒n referansa g├Âre ya da de─čere g├Âre ge├žmesine izin veren bir├žok dil (C gibi) olmas─▒na ra─čmen, onlardan biri de─čildir.

David Cournapeau'nun cevab─▒ ger├žek cevab─▒ i┼čaret ediyor ve Blair Conrad'─▒n g├Ârevinde yer alan davran─▒┼člar─▒n neden tan─▒mlamalar a├ž─▒k de─čilken do─čru g├Âr├╝nd├╝─č├╝n├╝ a├ž─▒kl─▒yor.

Python'un de─čere g├Âre ge├žti─či ├Âl├ž├╝de, baz─▒ diller de─čer olarak ge├žirilir, ├ž├╝nk├╝ bir veri par├žas─▒ (bir "de─čer" veya "referans" olabilir) g├Ânderilmelidir. Ancak bu, Python'un bir C programc─▒s─▒n─▒n d├╝┼č├╝nece─či anlam─▒nda de─čerden ge├žti─či anlam─▒na gelmez.

Davran─▒┼č─▒ istiyorsan─▒z, Blair Conrad'─▒n cevab─▒ gayet iyi. Ancak Python'un neden de─čer ge├žmedi─čine veya referans ge├žmedi─činin somunlar─▒n─▒ ve c─▒vatalar─▒n─▒ bilmek istiyorsan─▒z, David Cournapeau'nun cevab─▒n─▒ okuyun.


37







Burada ger├žekten iyi cevaplar─▒n var.

 x = [ 2, 4, 4, 5, 5 ]
print x  # 2, 4, 4, 5, 5

def go( li ) :
  li = [ 5, 6, 7, 8 ]  # re-assigning what li POINTS TO, does not
  # change the value of the ORIGINAL variable x

go( x ) 
print x  # 2, 4, 4, 5, 5  [ STILL! ]


raw_input( 'press any key to continue' )
 

23







Bu durumda, var metoda ba┼čl─▒kl─▒ de─či┼čkene Change bir referans atan─▒r self.variable ve hemen bir dize atars─▒n─▒z var . Art─▒k i┼čaret etmiyor self.variable . A┼ča─č─▒daki kod par├žac─▒─č─▒, ile g├Âsterilen veri yap─▒s─▒n─▒ de─či┼čtirirseniz var ve self.variable bu durumda bir liste olursa ne olaca─č─▒n─▒ g├Âsterir :

 >>> class PassByReference:
...     def __init__(self):
...         self.variable = ['Original']
...         self.change(self.variable)
...         print self.variable
...         
...     def change(self, var):
...         var.append('Changed')
... 
>>> q = PassByReference()
['Original', 'Changed']
>>> 
 

Eminim ba┼čkalar─▒ bunu daha fazla a├ž─▒kl─▒─ča kavu┼čturabilir.


18







Python'un atama ge├ži┼č program─▒, C ++ 'n─▒n referans parametreleri se├žene─čiyle tamamen ayn─▒ de─čildir, ancak pratikte C dilinin (ve di─čerlerinin) arg├╝man ge├ži┼č modeline ├žok benzer oldu─ču ortaya ├ž─▒kar:

  • De─či┼čtirilemez arg├╝manlar ÔÇť de─čere g├Âre ÔÇŁ etkin bir ┼čekilde iletilir . Tamsay─▒lar ve dizeler gibi nesneler kopyalamak yerine nesne ba┼čvurusuyla iletilir, ancak de─či┼čtirilemez nesneleri hi├žbir ┼čekilde de─či┼čtiremedi─činiz i├žin, efekt bir kopya olu┼čturmak gibidir.
  • De─či┼čken arg├╝manlar ÔÇť i┼čaret├ži ile ÔÇŁ etkili bir ┼čekilde iletilir . Listeler ve s├Âzl├╝kler gibi nesneler, C'nin i┼čaret├žiler olarak dizileri ge├žme ┼čekline benzer ┼čekilde nesne referans─▒ ile de iletilir; i┼člevde, C dizileri gibi, de─či┼čken nesneler de de─či┼čtirilebilir. .

17







De─či┼čken bir nesneye sahip olman─▒z gerekti─čini s├Âyleyebildi─činiz gibi, k├╝resel de─či┼čkenleri kontrol etmenizi ├Ânerebilirim ├ž├╝nk├╝ size yard─▒mc─▒ olabilirler ve hatta bu t├╝r bir sorunu ├ž├Âzebilirler!

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

├Ârnek:

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

15







Buradaki cevaplarla ilgili bir├žok fikir var, ancak ek bir noktaya a├ž─▒k├ža a├ž─▒k├ža de─činilmedi─čini d├╝┼č├╝n├╝yorum. Python belgelerinden al─▒nt─▒ https://docs.python.org/2/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python

"Python'da, yaln─▒zca bir i┼člev i├žinde referans verilen de─či┼čkenler tamamen globaldir. Bir de─či┼čkene, i┼člev g├Âvdesinde herhangi bir yerde yeni bir de─čer atan─▒rsa, bunun yerel oldu─ču varsay─▒l─▒r. Bir de─či┼čkene i┼člev i├žinde yeni bir de─čer atan─▒rsa, de─či┼čken dolayl─▒ olarak yereldir ve a├ž─▒k├ža ÔÇťglobalÔÇŁ olarak a├ž─▒klaman─▒z gerekir.├ľncelikle biraz ┼ča┼č─▒rt─▒c─▒ olsa da, bir an─▒n de─čerlendirmesi bunu a├ž─▒klar.Bir yandan, atanm─▒┼č de─či┼čkenler i├žin global isteme istenmeyen yan etkilere kar┼č─▒ bir ├žubuk sa─člar. ├ľte yandan, t├╝m global referanslar i├žin global olsayd─▒, her zaman global kullan─▒yor olsayd─▒n─▒z, yerle┼čik bir i┼čleve ya da i├že aktar─▒lm─▒┼č bir mod├╝l├╝n bir bile┼čenine yap─▒lan her referans─▒ global olarak beyan etmeniz gerekirdi. Yan etkilerin belirlenmesi i├žin k├╝resel bildirgenin kullan─▒┼čl─▒l─▒─č─▒n─▒ yok edecekti. ÔÇŁ

De─či┼čken bir nesneyi bir i┼čleve ge├žirirken bile bu hala ge├žerlidir. Ve bana g├Âre, nesneye atama ve nesnede i┼člev ├╝zerinde ├žal─▒┼čma aras─▒ndaki davran─▒┼č fark─▒n─▒n nedenini a├ž─▒k├ža a├ž─▒kl─▒yor.

 def test(l):
    print "Received", l , id(l)
    l = [0, 0, 0]
    print "Changed to", l, id(l)  # New local object created, breaking link to global l

l= [1,2,3]
print "Original", l, id(l)
test(l)
print "After", l, id(l)
 

verir:

 Original [1, 2, 3] 4454645632
Received [1, 2, 3] 4454645632
Changed to [0, 0, 0] 4474591928
After [1, 2, 3] 4454645632
 

Bu nedenle global olarak tan─▒mlanmayan global bir de─či┼čkene yap─▒lan atama, yeni bir yerel nesne yarat─▒r ve orijinal nesneye ba─člant─▒y─▒ keser.


13


2014-09-12





pass by object Python'da kullan─▒lan kavram─▒n basit (umar─▒m) a├ž─▒klamas─▒ .
Bir nesneyi i┼čleve ne zaman iletirseniz, nesnenin kendisi (Python'daki nesne asl─▒nda di─čer programlama dillerinde bir de─čer dedi─činiz ┼čeydir) bu nesneye referans olarak ge├žmez. Ba┼čka bir deyi┼čle, arad─▒─č─▒n─▒zda:

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

my_list = [0, 1]
change_me(my_list)
 

Ger├žek nesne - [0, 1] (di─čer programlama dillerinde bir de─čer olarak adland─▒r─▒lacak) ge├žiliyor. Yani asl─▒nda fonksiyon ┼č├Âyle bir change_me ┼čey yapmaya ├žal─▒┼čacakt─▒r:

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

A├ž─▒k├žas─▒ bu fonksiyona ge├žen nesneyi de─či┼čtirmeyecek. ─░┼člev b├Âyle g├Âr├╝n├╝yorsa:

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

Ard─▒ndan ├ža─čr─▒ ┼č├Âyle sonu├žlan─▒r:

 [0, 1].append(2)
 

hangi a├ž─▒k├ža nesneyi de─či┼čtirecek. Bu cevap onu iyi a├ž─▒klar.


10







Python'da bu i┼člerin nas─▒l y├╝r├╝d├╝─č├╝ ile ilgili t├╝m harika a├ž─▒klamalar─▒n yan─▒ s─▒ra, sorun i├žin basit bir ├Âneri g├Âremiyorum. Nesneler ve ├Ârnekler yarat─▒yormu┼čsunuz gibi, ├Ârnek de─či┼čkenlerini ele alman─▒n ve bunlar─▒ de─či┼čtirmenin pythonic yolu ┼čudur:

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

    def Change(self):
        self.variable = 'Changed'
 

├ľrnek y├Ântemlerde normalde self ├Ârnek eri┼čim ├Âzelliklerine bak─▒n. ├ľrnek niteliklerini ayarlamak __init__ ve bunlar─▒ ├Ârnek y├Ântemlerinde okumak veya de─či┼čtirmek normaldir . Bu y├╝zden self ilk tart─▒┼čmay─▒ als 'a ge├žtiniz def Change .

Ba┼čka bir ├ž├Âz├╝m ise bunun gibi statik bir y├Ântem olu┼čturmak olacakt─▒r:

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

    @staticmethod
    def Change(var):
        var = 'Changed'
        return var
 

8







Dil m├╝mk├╝n k─▒lmasa da, bir nesneyi referans olarak iletmek i├žin k├╝├ž├╝k bir numara var. Java'da da ├žal─▒┼č─▒yor, tek bir ├Â─čenin listesi. ;-)

 class PassByReference:
    def __init__(self, name):
        self.name = name

def changeRef(ref):
    ref[0] = PassByReference('Michael')

obj = PassByReference('Peter')
print obj.name

p = [obj] # A pointer to obj! ;-)
changeRef(p)

print p[0].name # p->name
 

Bu ├žirkin bir kesmek, ama i┼če yar─▒yor. ;-P


6







Birka├ž Fortran kodunu Python'a h─▒zl─▒ca d├Ân├╝┼čt├╝rmek i├žin a┼ča─č─▒daki y├Ântemi kulland─▒m. Do─čru, as─▒l soru ortaya at─▒ld─▒─č─▒ i├žin referans olarak ge├žilmez, ancak baz─▒ durumlarda basit bir ├žal─▒┼čmad─▒r.

 a=0
b=0
c=0
def myfunc(a,b,c):
    a=1
    b=2
    c=3
    return a,b,c

a,b,c = myfunc(a,b,c)
print a,b,c
 

4







Referansa g├Âre ge├ži┼č python'a uyan hi├žbir ┼čey olmamas─▒na ve nadiren kullan─▒lmas─▒ gerekti─čine ra─čmen, halihaz─▒rda yerel bir de─či┼čkene atanm─▒┼č nesneyi almak veya hatta ├ža─čr─▒lan bir fonksiyonun i├žinden yerel bir de─či┼čken atamak i├žin ├žal─▒┼čabilecek baz─▒ ge├žici ├ž├Âz├╝mler vard─▒r.

Temel fikir, bu eri┼čimi yapabilen ve nesne olarak ba┼čka i┼člevlere ge├žirilebilen veya bir s─▒n─▒fta saklanan bir i┼čleve sahip olmakt─▒r.

Bunun bir yolu sar─▒c─▒ i┼člevinde ( global genel de─či┼čkenler i├žin) veya nonlocal (bir i┼člevdeki yerel de─či┼čkenler i├žin ) kullanmakt─▒r .

 def change(wrapper):
    wrapper(7)

x = 5
def setter(val):
    global x
    x = val
print(x)
 

Ayn─▒ fikir del bir de─či┼čkeni okumak ve uygulamak i├žin de ge├žerlidir .

Yaln─▒zca okumak lambda: x i├žin, ├ža─čr─▒ld─▒─č─▒nda x'in ge├žerli de─čerini d├Ând├╝ren bir ├ža─čr─▒labilir ifadeyi d├Ând├╝ren daha k─▒sa bir kullan─▒m yolu vard─▒r . Bu biraz uzak ge├žmi┼čte dillerde kullan─▒lan "ada g├Âre ├ža─č─▒r" gibi.

Bir de─či┼čkene eri┼čmek i├žin 3 paketleyiciyi ge├žmek biraz hantald─▒r, bu y├╝zden bunlar proxy ├Âzelli─čine sahip bir s─▒n─▒fa sar─▒labilir:

 class ByRef:
    def __init__(self, r, w, d):
        self._read = r
        self._write = w
        self._delete = d
    def set(self, val):
        self._write(val)
    def get(self):
        return self._read()
    def remove(self):
        self._delete()
    wrapped = property(get, set, remove)

# left as an exercise for the reader: define set, get, remove as local functions using global / nonlocal
r = ByRef(get, set, remove)
r.wrapped = 15
 

Pythons "yans─▒ma" deste─či, bu kapsamdaki i┼člevleri a├ž─▒k├ža tan─▒mlamaks─▒z─▒n belirli bir kapsamda bir ad / de─či┼čken atayabilecek bir nesnenin elde edilmesini m├╝mk├╝n k─▒lar:

 class ByRef:
    def __init__(self, locs, name):
        self._locs = locs
        self._name = name
    def set(self, val):
        self._locs[self._name] = val
    def get(self):
        return self._locs[self._name]
    def remove(self):
        del self._locs[self._name]
    wrapped = property(get, set, remove)

def change(x):
    x.wrapped = 7

def test_me():
    x = 6
    print(x)
    change(ByRef(locals(), "x"))
    print(x)
 

Burada ByRef s─▒n─▒f bir s├Âzl├╝k eri┼čimini sarar. B├Âylece, ├Âzellik eri┼čimine wrapped ge├žen s├Âzl├╝kteki bir ├Â─če eri┼čimine ├ževrilir. Yerle┼čik sonucun locals ve bir yerel de─či┼čkenin ad─▒n─▒n ge├žilmesi ile bu, yerel bir de─či┼čkene eri┼čerek sona erer. 3.5'ten itibaren yap─▒lan python belgeleri, s├Âzl├╝─č├╝n de─či┼čtirilmesinin i┼če yaramayabilece─čini ancak benim i├žin i┼če yarad─▒─č─▒n─▒ g├Âsteriyor.


3







python'un de─čerleri ve bunlara referanslar─▒ i┼čleme ┼čekli g├Âz ├Ân├╝ne al─▒nd─▒─č─▒nda, rastgele bir ├Ârnek niteli─čine ba┼čvurabilmeniz i├žin tek yol ada g├Âredir:

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

    def change(self, var):
        self.__dict__[var] = 'Changed'
 

Ger├žek kodda, tabii ki, dict aramas─▒ ├╝zerinde hata denetimi eklersiniz.


3







Python'daki Referans Referans─▒, C ++ / Java'daki referans referans─▒ndan olduk├ža farkl─▒d─▒r.

  • Java & C #: ilkel t├╝rler (dize dahil) de─čere g├Âre (kopyala) ge├žer, Referans t├╝r├╝ referansla iletilir (adres kopyala), b├Âylece ├ža─čr─▒lan i┼člevdeki parametrede yap─▒lan t├╝m de─či┼čiklikler arayan taraf─▒ndan g├Âr├╝lebilir.
  • C ++: Hem referans by-pass hem de pass-by-value de─čerine izin verilir. Bir parametre referans yoluyla iletilirse, parametrenin const olarak ge├žirilip ge├žirilmedi─čine ba─čl─▒ olarak bunu de─či┼čtirebilir veya de─či┼čtiremezsiniz. Bununla birlikte, const veya de─čil, parametre nesneye olan referans─▒ korur ve ba┼čvuru, ├ža─čr─▒lan i┼člev i├žindeki farkl─▒ bir nesneye i┼čaret etmek i├žin atanamaz.
  • Python Python ÔÇťpass-by-nesne referansÔÇŁ ifadesi genellikle edilmi┼č olan, ÔÇťNesne ba┼čvurular─▒ de─čer ge├žirilirÔÇŁ [burada Okuma] 1 . Hem arayan hem de fonksiyon ayn─▒ nesneye at─▒fta bulunur, ancak fonksiyondaki parametre sadece arayan nesnede bir kopyas─▒n─▒ tutan yeni bir de─či┼čkendir. C ++ gibi, bir parametre de de─či┼čtirilebilir veya i┼člevinde olmayabilir - Bu, ge├žirilen nesnenin t├╝r├╝ne ba─čl─▒d─▒r. ├ľrne─čin; De─či┼čtirilebilir nesne t├╝r├╝ ├ža─čr─▒lan i┼člevde de─či┼čtirilemez, oysa de─či┼čken nesne g├╝ncellenebilir veya yeniden ba┼člat─▒labilir. De─či┼čken de─či┼čkenin g├╝ncellenmesi veya yeniden atanmas─▒ / yeniden ba┼člat─▒lmas─▒ aras─▒ndaki ├Ânemli bir fark, g├╝ncellenmi┼č de─čerin ├ža─čr─▒lan fonksiyona geri yans─▒t─▒lmas─▒d─▒r, oysa yeniden ba┼člat─▒lan de─čer de─čildir. De─či┼čtirilebilir bir de─či┼čkene yeni bir nesne ataman─▒n kapsam─▒, pythondaki fonksiyonda yereldir. @ Blair-conrad taraf─▒ndan sa─članan ├Ârnekler bunu anlamak i├žin m├╝kemmeldir.

3







├ľrne─činiz nesne y├Ânelimli oldu─ču i├žin, benzer bir sonu├ž elde etmek i├žin a┼ča─č─▒daki de─či┼čiklikleri yapabilirsiniz:

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

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

# o.variable will equal 'Changed'
o = PassByReference()
assert o.variable == 'Changed'
 

2







S├Âzl├╝kler referansa g├Âre iletildi─činden, i├žinde referans verilen de─čerleri saklamak i├žin bir dict de─či┼čkenini kullanabilirsiniz.

 # returns the result of adding numbers `a` and `b`
def AddNumbers(a, b, ref): # using a dict for reference
    result = a + b
    ref['multi'] = a * b # reference the multi. ref['multi'] is number
    ref['msg'] = "The result: " + str(result) + " was nice!" # reference any string (errors, e.t.c). ref['msg'] is string
    return result # return the sum

number1 = 5
number2 = 10
ref = {} # init a dict like that so it can save all the referenced values. this is because all dictionaries are passed by reference, while strings and numbers do not.

sum = AddNumbers(number1, number2, ref)
print("sum: ", sum)             # the return value
print("multi: ", ref['multi'])  # a referenced value
print("msg: ", ref['msg'])      # a referenced value
 

1







Hi├žbir yerde ├Ârne─čin C ++ 'dan bilindi─či gibi referanslar─▒ sim├╝le etmek i├žin bir yakla┼č─▒mdan bahsedildi─či anla┼č─▒ld─▒─č─▒ i├žin, bir "g├╝ncelleme" fonksiyonunu kullanmak ve as─▒l de─či┼čken yerine (veya daha ├žok "isim") ge├žmek:

 def need_to_modify(update):
    update(42) # set new value 42
    # other code

def call_it():
    value = 21
    def update_value(new_value):
        nonlocal value
        value = new_value
    need_to_modify(update_value)
    print(value) # prints 42
 

Bu, ├žo─čunlukla "yaln─▒zca d─▒┼čar─▒da yap─▒lan referanslar" i├žin veya birden fazla i┼č par├žac─▒─č─▒ / i┼člemi olan bir durumda (g├╝ncelleme i┼člevini i┼č par├žac─▒─č─▒ / ├žoklu i┼člemeyi g├╝venli hale getirerek) kullan─▒┼čl─▒d─▒r.

A├ž─▒k├žas─▒, yukar─▒daki de─čerin okunmas─▒na izin vermiyor , sadece g├╝ncelliyor.


1







─░├žindeki nesne ├Âzellikleri bir ├Ârnek s├Âzl├╝─č├╝nde sakland─▒─č─▒ndan, referans nesneleri depolamak i├žin yaln─▒zca bo┼č bir s─▒n─▒f─▒ kullanabilirsiniz . ├ľrne─če bak─▒n─▒z.

 class RefsObj(object):
    "A class which helps to create references to variables."
    pass

...

# an example of usage
def change_ref_var(ref_obj):
    ref_obj.val = 24

ref_obj = RefsObj()
ref_obj.val = 1
print(ref_obj.val) # or print ref_obj.val for python2
change_ref_var(ref_obj)
print(ref_obj.val)
 

0