Bagaimana saya bisa melewatkan integer dengan referensi dengan Python?
Saya ingin mengubah nilai variabel yang saya teruskan ke fungsi. Saya telah membaca bahwa segala sesuatu dalam Python adalah nilai lewat, tetapi harus ada trik yang mudah. Misalnya, di Jawa Anda bisa melewati jenis referensi Integer
, Long
, dll
- Bagaimana cara melewatkan integer ke fungsi dengan referensi?
- Apa praktik terbaiknya?
python
function
pass-by-reference
pass-by-value
CodeKingPlusPlus
sumber
sumber
Jawaban:
Itu tidak cukup berhasil dengan Python. Python meneruskan referensi ke objek. Di dalam fungsi Anda, Anda memiliki objek - Anda bebas untuk mengubah objek itu (jika memungkinkan). Namun, bilangan bulat tidak dapat diubah . Salah satu solusinya adalah dengan meneruskan integer dalam wadah yang dapat dimutasi:
def change(x): x[0] = 3 x = [1] change(x) print x
Ini jelek / kikuk, tetapi Anda tidak akan melakukan yang lebih baik dengan Python. Alasannya adalah karena dalam Python, assignment (
=
) mengambil objek apa pun yang merupakan hasil dari sisi kanan dan mengikatnya ke apa pun yang ada di sisi kiri * (atau meneruskannya ke fungsi yang sesuai).Memahami hal ini, kita dapat melihat mengapa tidak ada cara untuk mengubah nilai objek yang tidak dapat diubah di dalam fungsi - Anda tidak dapat mengubah atributnya karena tidak dapat diubah, dan Anda tidak dapat menetapkan "variabel" sebagai yang baru. nilai karena kemudian Anda benar-benar membuat objek baru (yang berbeda dari yang lama) dan memberinya nama yang dimiliki objek lama di namespace lokal.
Biasanya solusinya adalah dengan mengembalikan objek yang Anda inginkan:
def multiply_by_2(x): return 2*x x = 1 x = multiply_by_2(x)
* Dalam contoh kasus pertama di atas,
3
sebenarnya diteruskan kex.__setitem__
.sumber
C
. (Mereka tidak harus didereferensi, misalnya). Dalam model mental saya, lebih mudah untuk memikirkan hal-hal sebagai "Nama" dan "Objek". Tugas mengikat "Nama" di kiri ke "Objek" di kanan. Saat Anda memanggil suatu fungsi, Anda meneruskan "Objek" (mengikatnya secara efektif ke nama lokal baru di dalam fungsi)..
operator hanya membedakan sisi kiri. Operator bisa berbeda dalam bahasa yang berbeda.Sebagian besar kasus di mana Anda perlu meneruskan dengan referensi adalah ketika Anda perlu mengembalikan lebih dari satu nilai kembali ke pemanggil. "Praktik terbaik" adalah menggunakan beberapa nilai pengembalian, yang jauh lebih mudah dilakukan dengan Python daripada bahasa seperti Java.
Berikut contoh sederhananya:
def RectToPolar(x, y): r = (x ** 2 + y ** 2) ** 0.5 theta = math.atan2(y, x) return r, theta # return 2 things at once r, theta = RectToPolar(3, 4) # assign 2 things at once
sumber
Tidak persis meneruskan nilai secara langsung, tetapi menggunakannya seolah-olah itu diteruskan.
x = 7 def my_method(): nonlocal x x += 1 my_method() print(x) # 8
Peringatan:
nonlocal
diperkenalkan di python 3global
sebagai penggantinonlocal
.sumber
Sungguh, praktik terbaik adalah mundur dan bertanya apakah Anda benar-benar perlu melakukan ini. Mengapa Anda ingin mengubah nilai variabel yang Anda berikan ke fungsi?
Jika Anda perlu melakukannya untuk peretasan cepat, cara tercepat adalah melewatkan
list
memegang bilangan bulat, dan tetap[0]
menggunakannya setiap kali menggunakannya, seperti yang ditunjukkan oleh jawaban mgilson.Jika Anda perlu melakukannya untuk sesuatu yang lebih penting, tulis a
class
yang memilikiint
atribut, jadi Anda bisa menyetelnya. Tentu saja ini memaksa Anda untuk menemukan nama yang bagus untuk kelas tersebut, dan untuk atributnya — jika Anda tidak dapat memikirkan apa pun, kembali dan baca kalimat itu beberapa kali, lalu gunakanlist
.Secara lebih umum, jika Anda mencoba mem-port beberapa idiom Java langsung ke Python, Anda salah melakukannya. Bahkan ketika ada sesuatu yang berhubungan langsung (seperti dengan
static
/@staticmethod
), Anda tetap tidak ingin menggunakannya di sebagian besar program Python hanya karena Anda akan menggunakannya di Java.sumber
Di Python, setiap nilai adalah referensi (penunjuk ke suatu objek), seperti non-primitif di Java. Juga, seperti Java, Python hanya memiliki nilai lewat. Jadi, secara semantik, keduanya hampir sama.
Karena Anda menyebutkan Java dalam pertanyaan Anda, saya ingin melihat bagaimana Anda mencapai apa yang Anda inginkan di Java. Jika Anda dapat menunjukkannya di Java, saya dapat menunjukkan kepada Anda bagaimana melakukannya persis sama dengan Python.
sumber
Sebuah numpy array tunggal-elemen bisa berubah dan belum untuk sebagian besar tujuan, dapat dievaluasi seolah-olah itu adalah variabel python numerik. Oleh karena itu, ini adalah penampung nomor referensi yang lebih nyaman daripada daftar elemen tunggal.
import numpy as np def triple_var_by_ref(x): x[0]=x[0]*3 a=np.array([2]) triple_var_by_ref(a) print(a+1)
keluaran:
3
sumber
class PassByReference: def Change(self, var): self.a = var print(self.a) s=PassByReference() s.Change(5)
sumber
Mungkin itu bukan cara pythonic, tapi Anda bisa melakukan ini
import ctypes def incr(a): a += 1 x = ctypes.c_int(1) # create c-var incr(ctypes.ctypes.byref(x)) # passing by ref
sumber
Mungkin sedikit lebih mendokumentasikan diri daripada trik daftar panjang 1 adalah trik tipe kosong yang lama:
def inc_i(v): v.i += 1 x = type('', (), {})() x.i = 7 inc_i(x) print(x.i)
sumber
Di Python, semuanya diteruskan oleh nilai, tetapi jika Anda ingin mengubah beberapa status, Anda dapat mengubah nilai integer di dalam daftar atau objek yang diteruskan ke metode.
sumber
everything is passed by value
itu tidak benar. Dokumen kutipan:arguments are passed using call by value (where the value is always an object reference, not the value of the object)
Jawaban yang benar, adalah dengan menggunakan kelas dan meletakkan nilai di dalam kelas, ini memungkinkan Anda meneruskan referensi persis seperti yang Anda inginkan.
class Thing: def __init__(self,a): self.a = a def dosomething(ref) ref.a += 1 t = Thing(3) dosomething(t) print("T is now",t.a)
sumber