Saya tahu Python tidak memiliki pointer, tetapi apakah ada cara untuk mendapatkan hasil ini 2
sebagai gantinya
>>> a = 1
>>> b = a # modify this line somehow so that b "points to" a
>>> a = 2
>>> b
1
?
Berikut contohnya: Saya ingin form.data['field']
dan form.field.value
selalu memiliki nilai yang sama. Ini tidak sepenuhnya diperlukan, tapi saya pikir akan menyenangkan.
Di PHP, misalnya, saya bisa melakukan ini:
<?php
class Form {
public $data = [];
public $fields;
function __construct($fields) {
$this->fields = $fields;
foreach($this->fields as &$field) {
$this->data[$field['id']] = &$field['value'];
}
}
}
$f = new Form([
[
'id' => 'fname',
'value' => 'George'
],
[
'id' => 'lname',
'value' => 'Lucas'
]
]);
echo $f->data['fname'], $f->fields[0]['value']; # George George
$f->data['fname'] = 'Ralph';
echo $f->data['fname'], $f->fields[0]['value']; # Ralph Ralph
Keluaran:
GeorgeGeorgeRalphRalph
Atau seperti ini di C ++ (menurut saya ini benar, tetapi C ++ saya berkarat):
#include <iostream>
using namespace std;
int main() {
int* a;
int* b = a;
*a = 1;
cout << *a << endl << *b << endl; # 1 1
return 0;
}
a, b = b, a
.Jawaban:
Ini layak, karena melibatkan nama-nama dihiasi dan pengindeksan - yaitu, benar-benar konstruksi berbeda dari barenames
a
danb
bahwa Anda bertanya tentang, dan untuk permintaan Anda sama sekali tidak mungkin. Mengapa meminta sesuatu yang tidak mungkin dan sama sekali berbeda dari (mungkin) hal yang sebenarnya Anda inginkan ?!Mungkin Anda tidak menyadari betapa berbedanya nama bar dan nama dekorasi. Saat Anda merujuk ke barename
a
, Anda mendapatkan objek yang benar-a
benar terikat terakhir dalam cakupan ini (atau pengecualian jika tidak terikat dalam cakupan ini) - ini adalah aspek yang dalam dan mendasar dari Python sehingga dapat tidak mungkin ditumbangkan. Saat Anda mengacu pada nama yang dihiasx.y
, Anda meminta sebuah objek (objek yangx
) untuk memberikan "y
atribut" - dan sebagai tanggapan atas permintaan itu, objek tersebut dapat melakukan komputasi yang sepenuhnya sewenang-wenang (dan pengindeksannya sangat mirip: itu juga memungkinkan perhitungan sewenang-wenang untuk dilakukan sebagai tanggapan).Sekarang, contoh "desiderata aktual" Anda misterius karena dalam setiap kasus dua tingkat pengindeksan atau pengambilan atribut terlibat, sehingga kehalusan yang Anda dambakan dapat diperkenalkan dengan banyak cara. Atribut lain apa yang
form.field
seharusnya dimiliki, misalnya, selainvalue
? Tanpa.value
perhitungan lebih lanjut , kemungkinan akan mencakup:dan
Kehadiran
.value
menyarankan memilih formulir pertama, ditambah pembungkus yang tidak berguna:Jika tugas seperti
form.field.value = 23
itu juga diharapkan untuk mengatur entriform.data
, maka pembungkusnya memang harus menjadi lebih kompleks, dan tidak semuanya tidak berguna:Contoh terakhir kira-kira sedekat mungkin, dengan Python, dengan arti "penunjuk" seperti yang Anda inginkan - tetapi sangat penting untuk memahami bahwa kehalusan seperti itu hanya dapat bekerja dengan pengindeksan dan / atau nama yang dihias , tidak pernah dengan nama bar seperti yang Anda minta!
sumber
Tidak mungkin Anda bisa melakukan itu hanya dengan mengubah baris itu. Anda dapat melakukan:
Itu membuat daftar, menetapkan referensi ke a, lalu b juga, menggunakan referensi untuk menyetel elemen pertama ke 2, lalu mengakses menggunakan variabel referensi b.
sumber
a
danb
merupakan daftar, bukan nilai dalam daftar. Variabel tidak mengubah tugas, objek adalah objek yang sama. Jika itu berubah, seperti dalam kasus mengubah bilangan bulat (masing-masing adalah objek yang berbeda),a
sekarang akan ditugaskan ke objek lain dan tidak ada yang memintab
untuk mengikutinya. Di sini,a
tidak sedang ditetapkan, melainkan nilai di dalam objek yang ditetapkan berubah. Karenab
masih terikat pada objek itu, itu akan mencerminkan objek itu dan perubahan nilai di dalamnya.Ini bukan bug, ini fitur :-)
Saat Anda melihat operator '=' di Python, jangan berpikir tentang tugasnya. Anda tidak menetapkan sesuatu, Anda mengikatnya. = adalah operator yang mengikat.
Jadi dalam kode Anda, Anda memberi nilai 1 nama: a. Kemudian, Anda memberi nilai pada 'a' nama: b. Kemudian Anda mengikat nilai 2 ke nama 'a'. Nilai yang terikat ke b tidak berubah dalam operasi ini.
Berasal dari bahasa mirip C, ini bisa membingungkan, tetapi setelah Anda terbiasa, Anda akan terbantu untuk membaca dan bernalar tentang kode Anda dengan lebih jelas: nilai yang memiliki nama 'b' tidak akan berubah kecuali Anda mengubahnya secara eksplisit. Dan jika Anda melakukan 'impor ini', Anda akan menemukan bahwa Zen of Python menyatakan bahwa Eksplisit lebih baik daripada implisit.
Perhatikan juga bahwa bahasa fungsional seperti Haskell juga menggunakan paradigma ini, dengan nilai yang tinggi dalam hal ketahanan.
sumber
a = 1; b = a; a = 2;
persis sama di Python, C, dan Java: b adalah 1. Mengapa fokus pada "= bukan tugas, ini mengikat"?a
danb
sedangkan di Python, keduanya merujuk ke "1" yang sama (menurut saya). Jadi, jika Anda bisa mengubah nilai 1 (seperti objek), itu akan berbeda. Yang menyebabkan beberapa masalah tinju / unboxing yang aneh, saya dengar.Iya! ada cara untuk menggunakan variabel sebagai penunjuk di python!
Saya menyesal mengatakan bahwa banyak dari jawaban yang salah sebagian. Pada prinsipnya setiap penugasan yang sama (=) berbagi alamat memori (periksa fungsi id (obj)), tetapi dalam praktiknya tidak demikian. Ada variabel yang tingkah lakunya sama ("=") berfungsi di istilah terakhir sebagai salinan ruang memori, sebagian besar dalam objek sederhana (misalnya objek "int"), dan variabel lain yang tidak (misalnya objek "list", "dict") .
Berikut adalah contoh penetapan penunjuk
Berikut adalah contoh tugas menyalin
Penugasan penunjuk adalah alat yang sangat berguna untuk aliasing tanpa membuang memori ekstra, dalam situasi tertentu untuk melakukan kode yang nyaman,
tetapi kita harus menyadari penggunaan ini untuk mencegah kesalahan kode.
Sebagai kesimpulan, secara default beberapa variabel adalah barenames (objek sederhana seperti int, float, str, ...), dan beberapa adalah pointer ketika ditugaskan di antara mereka (misalnya dict1 = dict2). Bagaimana cara mengenalinya? coba saja eksperimen ini dengan mereka. Dalam IDE dengan panel explorer variabel biasanya muncul sebagai alamat memori ("@axbbbbbb ...") dalam definisi objek mekanisme penunjuk.
Saya sarankan menyelidiki topik tersebut. Ada banyak orang yang tahu lebih banyak tentang topik ini dengan pasti. (lihat modul "ctypes"). Saya harap ini membantu. Nikmati penggunaan objek dengan baik! Hormat kami, José Crespo
sumber
Seperti yang Anda lihat
a
danb
hanya dua nama berbeda yang merujuk ke objek tetap yang sama (int)1
. Jika nanti Anda menulisa = 2
, Anda menetapkan ulang namaa
ke objek yang berbeda (int)2
, tetapib
terus merujuk ke1
:Apa yang akan terjadi jika Anda memiliki objek yang bisa berubah, seperti daftar
[1]
?Sekali lagi, kami merujuk ke objek yang sama (daftar)
[1]
dengan dua nama berbedaa
danb
. Namun sekarang kita dapat mengubah daftar ini sementara itu tetap menjadi objek yang sama, dana
,b
keduanya akan terus merujuk padanyasumber
Dari satu sudut pandang, semuanya adalah penunjuk dengan Python. Contoh Anda berfungsi sangat mirip dengan kode C ++.
(Persamaan yang lebih dekat akan menggunakan beberapa jenis
shared_ptr<Object>
alih-alihint*
.)Anda dapat melakukan ini dengan membebani
__getitem__
diform.data
kelas.sumber
form.data
bukan kelas. Apakah perlu membuatnya menjadi satu, atau dapatkah saya menggantinya dengan cepat? (Ini hanya dikt python) Selain itu, data harus memiliki referensi kembaliform
untuk mengakses bidang ... yang membuat penerapan ini jelek.Ini adalah penunjuk python (berbeda dari c / c ++)
sumber
Saya menulis kelas sederhana berikut sebagai, secara efektif, cara untuk meniru pointer dengan python:
Berikut adalah contoh penggunaan (dari halaman buku catatan jupyter):
Tentu saja, ini juga mudah untuk membuat ini berfungsi untuk item atau atribut suatu objek. Bahkan ada cara untuk melakukan apa yang diminta OP, menggunakan globals ():
Ini akan mencetak 2, diikuti oleh 3.
Mengacaukan namespace global dengan cara ini jelas merupakan ide yang buruk, tetapi ini menunjukkan bahwa adalah mungkin (jika tidak disarankan) untuk melakukan apa yang diminta OP.
Contohnya, tentu saja, tidak ada gunanya. Tetapi saya telah menemukan kelas ini berguna dalam aplikasi yang saya kembangkan: model matematika yang perilakunya diatur oleh banyak parameter matematika yang dapat diatur pengguna, dari beragam jenis (yang, karena bergantung pada argumen baris perintah, tidak diketahui pada waktu kompilasi). Dan begitu akses ke sesuatu telah dienkapsulasi dalam objek Parameter, semua objek tersebut dapat dimanipulasi dengan cara yang seragam.
Meskipun tidak terlihat seperti pointer C atau C ++, ini memecahkan masalah yang akan saya selesaikan dengan pointer jika saya menulis dalam C ++.
sumber
Kode berikut mengemulasi dengan tepat perilaku pointer di C:
Berikut adalah contoh penggunaan:
Tetapi sekarang saatnya memberikan kode yang lebih profesional, termasuk opsi untuk menghapus pointer, yang baru saja saya temukan di perpustakaan pribadi saya:
sumber