Pendekatan saya untuk menamai tupel di Julia – Beragampengetahuan
Oleh: Blog Bogumił Kamiński
Repost dari:
Named tuple adalah salah satu tipe data yang paling umum digunakan di Julia.
Dalam posting ini, saya ingin membahas bagaimana saya memikirkan tipe ini dan menggunakannya dalam praktik.
Posting ini ditulis di bawah Julia 1.9.
Petunjuk untuk menggunakan Julia di bagian Named Datasets tentukan:
Elemen-elemen dari tuple dapat diberi nama sembarang, dalam hal ini a bernama tupel Dibuat (…)
Named tuples sangat mirip dengan tuples, kecuali bahwa fieldnya mungkin tambahan
diakses dengan nama menggunakan sintaks titik (x.a) selain sintaks pengindeksan biasa (x[1]).
Dan diberikan contoh berikut:
julia> x = (a=2, b=1+2)
(a = 2, b = 3)
julia> x[1]
2
julia> x.a
2
Definisi ini menekankan hal itu NamedTuple mirip dengan a Tuple kecuali itu
komponen dapat memiliki nama.
Namun, saya merasa lebih alami untuk memikirkan a NamedTuple sebagai konstruksi anonim,
opsional dapat diindeks bilangan bulat untuk mendapatkan akses ke elemen-elemennya.
Izinkan saya memberikan beberapa alasan mengapa menurut saya ini adalah model mental yang lebih baik.
Mari kita lihat Tuple ketik dulu. Bangun tupel dasar:
julia> t = (1, "a")
(1, "a")
julia> typeof
Tuple{Int64, String}
Perhatikan jenis itu t adalah subtipe dari contoh Tuple{Integer, AbstractString}:
julia> t isa Tuple{Integer, AbstractString}
true
Perilaku kategoris ini disebut kovarians.
Lebih dari itu Tuple{Integer, AbstractString} tidak konkret:
julia> isconcretetype(Tuple{Integer, AbstractString})
false
Ini berarti Anda tidak dapat membuat kumpulan jenis ini.
Jika Anda mencoba panggilan berikut:
julia> t2 = Tuple{Integer, AbstractString}
(1, "a")
julia> typeof(t2)
Tuple{Int64, String}
Tidak ada yang berubah. Hasil t2 tuple dengan parameter tertentu Int64 Dan String.
Anda mungkin bertanya berapa banyak fitur ini NamedTuple membagikan? Jawabannya adalah tidak.
Mari kita periksa:
julia> nt = (a=1, b="a")
(a = 1, b = "a")
julia> typeof(nt)
NamedTuple{(:a, :b), Tuple{Int64, String}}
Jenis nt bukan subtipe contoh NamedTuple{(:a, :b), Tuple{Integer, AbstractString}}:
julia> nt isa NamedTuple{(:a, :b), Tuple{Integer, AbstractString}}
false
Namun, itu adalah subtipe dari UnionAll jenis NamedTuple{(:a, :b), <:Tuple{Integer, AbstractString}}.
julia> nt isa NamedTuple{(:a, :b), <:Tuple{Integer, AbstractString}}
true
Perilaku kategoris ini disebut invarian dan dibagikan dengan struct jenis.
Selanjutnya, Anda dapat membangun nilai yang memiliki NamedTuple{(:a, :b), Tuple{Integer, AbstractString}} ketik (jadi spesifik):
julia> isconcretetype(NamedTuple{(:a, :b), Tuple{Integer, AbstractString}})
true
julia> nt2 = NamedTuple{(:a, :b), Tuple{Integer, AbstractString}}((1, "a"))
NamedTuple{(:a, :b), Tuple{Integer, AbstractString}}((1, "a"))
julia> typeof(nt2)
NamedTuple{(:a, :b), Tuple{Integer, AbstractString}}
Sekali lagi, perilakunya sama dengan untuk struct jenis.
Fakta bahwa Anda dapat secara dinamis mengatur parameter dari kumpulan bernama sebagian besar berguna
jika Anda memiliki data yang heterogen. Ini sebuah contoh.
Kode otorisasi:
julia> [(a=1, b=missing), (a=missing, b="x")]
2-element Vector{NamedTuple{(:a, :b)}}:
(a = 1, b = missing)
(a = missing, b = "x")
julia> typeof.([(a=1, b=missing), (a=missing, b="x")])
2-element Vector{DataType}:
NamedTuple{(:a, :b), Tuple{Int64, Missing}}
NamedTuple{(:a, :b), Tuple{Missing, String}}
Di sini kami telah membuat vektor dengan elemen dari tipe yang berbeda.
Kode yang menggunakannya akan menjadi tidak stabil. Namun, kita bisa membuat jenis yang sama
(akan lebih ramah kompiler; ini akan sesuai jika Anda berurusan dengan data yang sangat besar):
julia> @NamedTuple{a::Union{Int,Missing}, b::Union{String,Missing}}.([(a=1, b=missing), (a=missing, b="x")])
2-element Vector{NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}}:
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}((1, missing))
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}((missing, "x"))
Perbedaannya adalah bahwa sekarang kompiler akan mengetahui jenis setiap bidang dalam tupel bernama kami
(dan Julia dengan anggun menangani yang kecil UnionS).
Perhatikan bahwa saya menggunakan @NamedTuple{a::Union{Int,Missing}, b::Union{String,Missing}} panggilan makro
untuk cara yang nyaman untuk menentukan NamedTuple jenis. Mari kita coba (dengan cara lain untuk menuliskannya):
julia> @NamedTuple{a::Union{Int,Missing}, b::Union{String,Missing}}
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}
julia> @NamedTuple begin
a::Union{Int,Missing}
b::Union{String,Missing}
end
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}
Sekarang, bahkan pada tingkat sintaksis, kemiripannya dengan struct definisi jelas.
Mari kita definisikan dua jenis:
julia> const S1 = @NamedTuple begin
a::Union{Int,Missing}
b::Union{String,Missing}
end
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}
julia> struct S2
a::Union{Int,Missing}
b::Union{String,Missing}
end
Itu S1 Dan S2 hampir tidak bisa dibedakan. Satu-satunya perbedaan adalah:
S1adalah subtipe dariNamedTupleUnionAllketikaS2hanya subtipe dariAny;S1menerima tuple sebagai argumen tunggal, whileS2menerima dua argumen;S1dapat diindeks, sementaraS2Bukan;- menambahkan metode ke fungsi asing untuk
S1adalah sejenis pembajakan.
Mari kita buat contoh dari S1 Dan S2 dan diskusikan perbedaan yang disebutkan di atas.
Pertama, perbedaan konstruktor:
julia> x1 = S1((1, "a"))
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}((1, "a"))
julia> x2 = S2(1, "a")
S2(1, "a")
Kita bisa melihat perbedaan pada konstruktornya. Perlu sepasang tanda kurung tambahan untuk S1.
Akan menggoda untuk mendefinisikan:
julia> S1(x, y) = S1((x, y))
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}
julia> S1(1, "a")
NamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}}((1, "a"))
Ini akan berhasil. Tetapi jika Anda menulis kode perpustakaan, Anda tidak boleh melakukan ini.
Alasannya adalah Anda baru saja menambahkan metode untukNamedTuple{(:a, :b), Tuple{Union{Missing, Int64}, Union{Missing, String}}} jenis
dan tipe ini merupakan bagian dari Base Julia. Perilaku seperti itu dikenal sebagai pembajakan tipe
dan berpotensi merusak beberapa kode pihak ketiga (dalam hal ini risikonya minimal,
tapi ada baiknya membiasakan diri).
Perbedaannya adalah dengan jenis kustom Anda S2 Anda bebas menambahkan metode
fungsi apa pun yang Anda suka (bahkan pihak ketiga), karena Anda sendiri S2. Karena itu
(selama Anda mendefinisikan metode dengan benar) Anda tidak akan merusak kode apa pun dengan melakukannya.
Mari kita beri contoh. Kami membahas manfaat dari NamedTuple melaluistruct apakah dapat diindeks:
julia> x1[1]
1
julia> x2[1]
ERROR: MethodError: no method matching getindex(::S2, ::Int64)
Namun, Anda dapat dengan mudah memperbaikinya:
julia> Base.getindex(x::S2, i::Int) = getfield(x, i)
julia> x2[1]
1
Apa yang kami lakukan dengan menambahkan metode ke Base.getindex bukan jenis pembajakan karenaS2 adalah salah satu yang kita miliki.
Perbedaan utama antara S1 Menjadi S2 yaitu, seperti yang kami sebutkan,S1 adalah subkategori dari NamedTuplesehingga akan diterima oleh fungsi
bekerja dengan tupel bernama, sebagai lawan dari S2. Berikut adalah contoh kecil:
julia> empty(x1)
NamedTuple()
julia> empty(x2)
ERROR: MethodError: no method matching empty(::S2)
Sekali lagi – kita dapat dengan mudah menambahkan metode untuk Base.empty Karena S2 jika kita mau, seperti yang kita lakukan
dengan Base.getindex di atas.
Contoh yang diberikan bernama tuple ini berbagi beberapa fitur dengan tupel dan beberapa fitur dengan struct.
Pengalaman saya adalah bahwa itu lebih menyerupai struktur dalam kenyataan. Ada dua alasan:
- Saya jarang mengindeks atau mengulangi tupel bernama, saya biasanya mengakses bidangnya berdasarkan nama.
- Dalam pengiriman bernama, tuple berperilaku seperti struct (ini cukup konsisten saat menulis kode Anda).
Saya masih suka menganggap tuple bernama sebagai a struktur anonim. Meskipun kita bisa memberikannya sebuah alias
seperti yang kita lakukan dengan S1 menurut definisi, ini jarang dilakukan. Biasanya tipe beton dari tuple bernama
masih dinamis dan saya hanya mendefinisikan fungsi saya untuk NamedTuple UnionAll.
Selamat meretas!
Terkait
Software Terbaru Saat Ini
Aplikasi yang sedang trend saat ini
object oriented programming, programming language, programming adalah, web programming, belajar programming, tournament software, software, software adalah, contoh software, apa itu software, pengertian software, aplikasi, aplikasi penghasil uang, aplikasi bokep, aplikasi video, programming
#Pendekatan #saya #untuk #menamai #tupel #Julia