Penjelasan Beranotasi Simon Willison tentang Dataklasses David Beazley
David Beazley di Twitter:
Jadi, saya baru saja menerbitkan putaran jahat yang nikmat ini di kelas data. Ini kecil dan kelas yang dihasilkan mengimpor sekitar 15-20 lebih cepat daripada kelas data. https://github.com/dabeaz/dataklasses
Saya memutuskan untuk membuat versi kode aslinya yang beranotasi berat untuk mencari tahu sendiri cara kerjanya.
"x", "y") def __init__ (diri sendiri, x, y): diri sendiri.x=xdiri sendiri.y=y def __repr__( diri sendiri): kembalif"Koordinat({diri sendiri.x!r}, {diri sendiri.y!R})"def__eq__(diri sendiri, lainnya): jikasendiri.__kelas__adalahlainnya. __kelas__: kembali (diri sendiri,x, diri sendiri.y,) == (lainnya.x , lainnya.y,) kalau tidak: kembaliTidak Diimplementasikan
Trik kunci: pembuatan kode
Kunci untuk memahami cara kerja kode adalah dengan memahami bahwa itu menggunakan pembuatan kode. David mengintrospeksi properti kelas beranotasi, dari kelas itu sendiri dan superclass mana pun, lalu menghitung jumlahnya. Dia kemudian menghasilkan metode yang terlihat seperti ini:
def__init__(diri sendiri, _0, _1): sendiri._0=_0diri sendiri ._1=_1
Kemudian gunakan func.__code__.replace(co_names=repl_co_names, co_varnames=repl_co_varnames) metode untuk mengganti nama itu _0 dan _1 variabel kembali ke x dan y.
Saya belum mengerti mengapa dia melakukan ini sebagai lawan menghasilkan kode menggunakan x dan y secara langsung. Saya akan memperbarui ini dengan penjelasan setelah saya menemukannya!
Pembaruan: Jacob Kaplan-Moss menjelaskannya di sini!
Itu benar-benar liar trik inti dari ini, dan apa yang membuatnya cepat:
bytecode untuk
__init__(sendiri, x, y)
persis sama dengan bytecode untuk __init__(self, foo, bar)!
Jadi itu berarti Dave dapat men-cache kode yang dihasilkan untuk "any __init__ berfungsi dengan dua argumen" dan kemudian
re -gunakan kode yang sama persis untuk 2-arity selanjutnya __init__s!
Salinan beranotasi saya
Pertama, termasuk pesan hak cipta seperti yang dipersyaratkan oleh pesan hak cipta:
# dataklasses.py # # https://github.com/dabeaz/dataklasses## Pengarang : David Beazley (@dabeaz).# http://www.dabeaz.com## Hak cipta (C) 2021-2022. ## Izin diberikan untuk menggunakan , salin, dan ubah kode ini di any # cara selama pesan hak cipta dan disclaimer ini tetap ada # kode sumber. Tidak ada garansi. Coba gunakan kode untuk # lebih baik.
Anotasi saya dimulai di sini (Saya juga menjalankannya hingga Hitam).
__semua__=# Ini memastikan "dari impor dataklasses *" hanya akan mengimpor simbol dataklass darifungsiimpor
lru_cache
,
mengurangi # Dekorator ini mengambil fungsi yang mengembalikan kode sumber Python dan mengkompilasinya # itu menjadi fungsi Python. Jadi jika func(fields) mengembalikan string berikut: ## def __init__(sendiri, a): # diri.a=a# # Nilai yang dikembalikan adalah itu fungsi yang dikompilasi. Dengan beberapa penyempurnaan.defkodegen(fungsi): # Ini menyimpan hasil jadi jika Anda melewati numfields yang sama tidak perlu # melakukan pekerjaan yang sama dua kali .## Ini adalah pengoptimalan kinerja utama untuk kode ini – ini berarti # kode yang dihasilkan sama dapat digunakan kembali untuk setiap kelas yang memiliki kesamaan # jumlah argumen!@lru_cachedefmake_func_code(numfields) : # numfields di len(fields) nama= [f”_{n}“forninrange(numfields)] # nama sekarang [“_0”, “_1”, “_2”] tergantung pada numfields # # Kami memanggil func() dengan daftar nama itu dan exec() the# mengembalikan kode sumber. Argumen ketiga untuk exec() adalah# locals() – ini adalah kamus yang fungsi exec() # akan diisi dengan simbol baru. ## Kami menggunakan d:={} operator walrus di sini sehingga kami dapat# lihat kamus itu dengan nama d sebentar lagi.eksekutif(
func(
nama), global(), d := {}) # d.popitem() kembali pasangan (kunci, nilai) pertama di # kamus. Kita tahu bahwa kamus locals() # hanya akan memiliki satu simbol di dalamnya, karena# kita sekarang bahwa kode dikembalikan oleh fungsi(nama) saja# mendefinisikan satu fungsi. Jadi ini mengembalikan nilai# dari item pertama di locals(), function objectkembalid.popitem
()[1] # Dekorasi ini() adalah nilai kembalian dari dekorator,# yang artinya kode berikut: # # @codegen# def make__init__(bidang): # # …# Mengubah make__init__ menjadi fungsi yang ditentukan oleh dekorasi()defdekorasi(bidang): # Seperti yang ditunjukkan di atas, ini menggunakan exec() untuk mengkompilasi dan mengembalikan # badan fungsi yang dibuat menggunakan kode sumber yang dihasilkan fungsi=make_func_code(
len(
bidang)) # Tapi ingat: karena kami men-cache dan menggunakan kembali badan metode, ini memiliki # jelek _0, _1 parameter dan variabel yang ingin kita buat lebih bagus. # co_names: tuple nama selain argumen dan fungsi lokalco_names=fungsi.__code__.co_name s# Untuk contoh Koordinat, nama_bersama=(“_0”, “_1”)# co_varnames: tuple nama argumen dan variabel lokal co_varnames = fungsi.__kode__.co_varnames# Untuk contoh Koordinat, co_varnames=(“self”, “_0”, “_1” )# Kami akan mengganti co_names dan co_varnames dengan modifikasi# versi – jadi kita perlu membuat dua tupel pengganti untuk mereka. # # start :=co_names.index(“_0”) menggunakan operator walrus untuk keduanya# cari tahu indeks berbasis 0 dari simbol _0 dan menetapkannya ke s# # Kami menggunakan (*a, *b, *c) untuk membuat tupel baru yang merupakan hasil dari # menggabungkan ketiga tupel input tersebut.repl_co_names
= (
# Iris semuanya dalam co_names hingga simbol _0 pertama
*co_names[start+len(fields) :],
# Kemudian masukkan bidang, yang merupakan properti kelas beranotasi *bidang, # Sekarang semuanya dalam co_names berikut *co_names[start+len(fields) :], ) # Untuk Koordinat ini sekarang (“x”, “y”)repl_co_varnames= ( # Kami hanya memodifikasi co_varnames jika _0 adalah salah satunya, jika tidak # kami membiarkannya tidak berubah. ( *co_varnames[: (start:=co_varnames.index(“_0”))], *
bidang,
*
co_varnames[start+len(fields) :], ) jika“_0”dico_varnameselseco_varnames ) # Untuk Koordinat ini sekarang (“self”, “x”, “y”)# type(func) mengembalikan objek internal Python yang disebut “fungsi”# yang dapat dipanggil dan memiliki tanda tangan fungsi ini: ## fungsi(kode, global, nama=Tidak ada, argdefs=Tidak ada, penutupan=Tidak ada)## Ini menciptakan objek fungsi baru kembaliTipe(fungsi)( # func.__code__.replace docstring mengatakan: # “Kembalikan salinan objek kode dengan nilai baru untuk bidang yang ditentukan” # Jadi kami menulis ulang co_names dan co_varnames di sini fungsi.__kode__.mengganti(co_names=
repl_co_names
, co_varnames=repl_co_varnames ), fungsi.__globals__, ) kembalidekorasidefall_hints(cls): # Ini mengintrospeksi kelas untuk menemukan semua anggota kelas beranotasi # Dalam Koordinat cas e ini mengembalikan {‘x’: , ‘y’: } # # “x” untuk lambda itu dimulai sebagai {} kamus kosong itu dan setiap kali# adalah kamus dengan hal-hal baru yang ditambahkan ke dalamnya.## reversed(Coordinates.__mro__) loop melalui setiap superclass saat ini # kelas, dimulai dari “objek”.## Jadi lambda dipanggil melawan setiap superclass secara bergantian, dan setiap kali itu# membaca bidang __annotations__, jika tersedia. # # Coordinates.__annotations__ mengembalikan {‘x’: int, ‘y’: int}## dict1 | dict2 di Python mengembalikan dict baru yang menggabungkan dua sebelumnya ## Jadi fungsi ini mengembalikan kamus gabungan dari __annotations__ from# setiap kelas dalam hierarki superclass. kembali kurangi ( lambdax, y: x|
getattr
(y, “__annotations__”, {}),
terbalik
(cls.__mro__), {} ) # Berikutnya adalah fungsi yang menghasilkan metode yang berbeda. Ingat mereka lulus # bidang yang adalah {‘x’: , ‘y’:
} @codegendefmake__init__(bidang): # Memanggil “,”.join(dict) bergabung saja kunci kamus itukode=“def __init__(sendiri, “+“,”.Ikuti(
bidang)
+ “): n” # Jadi di sini kita memiliki: # def __init__ (sendiri, x, y): kembalikode+“n“ .Ikuti(f” diri sendiri.{nama}={nama}n“untuknamadibidang)
# Ini menambahkan:
# self.x=x # self.y=y@kodegendefmake__repr__(bidang): kembali ( “def __repr__(self): n“# type(self).__name__ memberi kita nama kelas: “Koordinat”‘ return f”{type(self).__name__}(‘# Ini memberi kita {self.x!r}, {self.y! r} yang dalam f-string# memberi kami __repr__() versi properti objek tersebut +“, “.Ikuti(“{diri sendiri.”+nama+ “!R}” untuknamadibidang) +‘)”n‘ ) # Jadi ini menghasilkan: # def __repr__(self): # return f”Koordinat({self.x!r}, {self.y!r})” @kodegendefmake__eq__(bidang): selfvals =“,”.Ikuti(f”diri sendiri.{nama}“untuknamadibidang ) lain-lain=“,,”.Ikuti(f”lainnya.{
nama}“
untuk namadibidang ) kembali ( “def __eq__(diri sendiri, orang lain): n“” jika self.__class__ adalah other.__class__: n“f” kembali ({selfvals},)==({lainnya S},)n“ ” kalau tidak: n“” return NotImplementedn“ ) # Ini menghasilkan: # def __eq__(diri sendiri, orang lain): # jika self.__class__ adalah yang lain.__class__: # return (self,x, self.y,)==(other.x, other.y)# kalau tidak: # return NotImplemented@kodegendefmake__iter__(bidang): kembali“def __iter__(sendiri): n” +“n“.Ikuti( f” menghasilkan diri sendiri.{ nama}“untuk namadibidang ) @kodegendefmake__hash__(bidang): self_tuple=“(“+“,,”.Ikuti(f”diri.{nama}” untuknamadi
cls): bidang=all_hints(cls) # bidang sekarang {‘x’: , ‘y’: }clsdict=vars(cls) # clsdict terlihat seperti ini: # {‘__module__’: ‘__main__’,
# '__annotations__': {'x': , 'y': },
# ‘__dict__’: ,# ‘__weakref__’: , # ‘__doc__’: Tidak ada} # # Tujuan dari fungsi ini terutama untuk menambahkan __init__ dan# __repr__ dan __eq__ metode, tetapi hanya jika belum didefinisikan jikabukan“__init__”diclsdict:
(bidang) # Tidak yakin mengapa ini dikomentari sekarang: # jika tidak ‘__iter__’ di clsdict: cls.__iter__=make__iter__(fields) # jika tidak ‘__hash__’ di clsdict: cls.__hash__=make__hash__(fields)cls.__match_args__=bidang# Ini terkait dengan pengetikan struktural Python: # https://www.python.org/dev/peps/pep-0622/#special-attribute-match-argskembali cl s# Contoh penggunaanjika__nama__ ==“__utama__”: @dataklass kelasKoordinat: x: inty: int
Dibuat 2021-12-19T20:30:57-08:00, diperbarui 2021-12-19T21:38:45-08:00 · Riwayat · Edit
Colby Covington memprediksi pengajuan 'Rekor… Colby Covington telah membangun pertarungan dengan mantan juara kelas ringan sementara UFC Dustin Poirier bahkan sebelum dia Washington menemukan quarterbacknya ini. Tetapi dalam sebuah wawancara baru-baru ini, Covington mengungkapkan bahwa…
Saya pikir saya menaklukkan insomnia. Kemudian saya… Seperti yang diceritakan oleh Erica RellingerMalam kami menguburkan ayahku, aku tidak tidur. Pada malam kedua setelah kematiannya saya berjalan sampai kelelahan dan tidak tidur. Pada malam ketiga, pikiran saya berdenyut…
Bagaimana menjaga kesehatan mental Anda jika Anda… Pada tahun 2019, Amy Hart didiagnosis menderita kanker kolorektal pada usia 34 tahun. Setelah perawatan yang mencakup operasi pengangkatan usus besarnya, Hart sekarang bebas dari penyakit tersebut, tetapi masih menghadapi…
KAPAN CC SABTHIA MENJADI JACK INI?! Saya benar-benar terkejut, tanpa malu-malu, dan ternganga melihat kilau yang dialami CC Sabathia sejak pensiun dari MLB. Biasanya kami melihat para pemain memperlakukan diri mereka sendiri dan melepaskan diri mereka…
Redding memuji BMW untuk "perbaikan besar" dalam tes Misano Tes dua hari minggu lalu di Misano menandai tamasya pertama Redding untuk BMW 2022, pembalap Inggris itu melakukan penampilan tes pertamanya dengan pabrikan Jerman di Estoril dan Jerez Desember lalu.…
Jurnalisme teknologi kurang beragam dibandingkan… 982 Orang. 14 Outlet. 80% Putih. 2% Hitam. 18% Lainnya. Grafik Distribusi Ras di Perusahaan Teknologi Besar dan Media Besar.Setelah saya mempublikasikan posting saya menunjuk keluar dari kemunafikan Big Tech…
Ketidaktahuan bukanlah berkah dalam hal seks menopause Seperti yang diceritakan oleh Erica RellingerKetika saya mulai memasuki perimenopause 13 tahun yang lalu, saya belum pernah mendengar kata itu. Menopause tidak pernah disebutkan apalagi Bahas Di keluarga saya atau…
Lebih Banyak Kreator Yang Menghasilkan Uang Secara… Dalam hal minat media dan dolar VC, apa yang disebut "ekonomi pencipta" sedang panas-panasnya. Investor menggelontorkan $1,3 miliar ke perusahaan yang berharap dapat membantu pembuat konten online memonetisasi bakat mereka…
Saya tidak menyesal terinfeksi HIV karena itu… Seperti yang diceritakan oleh Aviva PatzSeptember 18, 2022, Ho Hari Kesadaran HIV/AIDS dan Penuaan Nasional.Sulit dipercaya bahwa HIV bisa menjadi berkah, tetapi bagi saya, itu benar.Ini karena itu memberi saya…
Alasan Selamat Tinggal: Cara Melangkah untuk… Kami tahu, kami tahu. Anjing Anda memakan pekerjaan rumah Anda sehingga Anda tidak dapat menjadwalkan pemeriksaan tahunan. Kita semua membuat alasan. Dan memang benar bahwa banyak dari kita yang sibuk…
10 VPN Terbaik Untuk Meningkatkan Keamanan Internet… Pengungkapan: Tujuan kami adalah menampilkan produk dan layanan yang menurut kami menarik dan berguna bagi Anda. Jika Anda membelinya, Pengusaha dapat memperoleh sebagian kecil dari pendapatan dari penjualan dari mitra…
Tanya HN: Mengapa kita begitu bergantung pada Google… Dikutip dari Lam Luu di atas (jika Anda tidak memiliki quora login): Mari kita melakukan beberapa akuntansi. Browser modern (semu) harus: Parsing 4 bahasa berbeda: HTTP, HTML, javascript, dan CSSEnkripsi…
12 Cara Meningkatkan Kepercayaan Diri Anda di 2022 Pendapat yang dikemukakan oleh kontributor Entrepreneur adalah milik mereka sendiri. Percaya diri adalah salah satu kualitas terpenting yang harus dimiliki dalam hidup. Ini berdampak pada Anda pada tingkat pribadi, profesional…
Perawatan diri dengan anggaran terbatas: 5 ide… Hidup sepertinya selalu ramai dengan acara, kumpul-kumpul, dan kumpul keluarga, tapi jangan lupa luangkan waktu untuk menjaga kesehatan diri dan utamakan perawatan diri.Berinvestasi pada diri sendiri tidak harus melibatkan hari…
Jika Anda Percaya Salah Satu dari 5 Hal Ini, Anda… Apa yang membuat seseorang menjadi pemimpin yang efektif? Yang terbaik adalah kreatif daripada reaktif, kata Bill Adams, salah satu pendiri dan CEO perusahaan pengembangan kepemimpinan, Leadership Circle. Itulah temuan dari…
Rahasia Meraih Hati Teman yang Menjauh Pernahkah Anda Merasa Dikucilkan oleh Teman? Berikut Beberapa Tips untuk Mengatasinya Pernahkah Anda merasa dijauhi oleh teman-teman? Merasa kesepian dan sendirian? Jangan khawatir, Anda tidak sendirian. Banyak orang yang pernah…
Setengah abad kemudian, saya akhirnya bebas dari hepatitis C Seperti yang diceritakan oleh Erica RellingerSiswa kelas satu memiliki banyak energi, dan guru mereka harus mengikutinya. Saya bisa melanjutkan hari-hari itu, dari tahun 60-an hingga 80-an, tapi hanya itu yang…
Tips Jitu Tingkatkan Kualitas Konten Website Anda Mencari Inspirasi dan Saran yang Menarik dan Bermanfaat Di dunia yang terus berubah ini, kita semua mencari inspirasi dan saran yang dapat membantu kita menghadapi kehidupan. Tips yang menarik dapat…
Francis Ngannou Menggoda Tyson Fury Fight Setelah… Katelyn Mulcahy/Getty ImagesFrancis Ngannou tampaknya siap untuk bertarung melawan Tyson Fury berdasarkan tanggapan hari Minggu kepada juara tinju kelas berat: Francis Ngannou @francis_ngannouhttps://t.co/BJRyYfzZQr pic.twitter.com/vLpuDl3SxLNgannou mengalahkan Cyril Gane dengan keputusan di…
Semua yang Perlu Anda Ketahui Tentang Menulis Buku,… Hai, saya Jay Steinfeld, dan saya adalah penulis pemula. Saya juga mengumumkan pensiun saya dari menulis buku.Saya akan menjelaskan sedikit tentang pensiun.Tapi mari kita mulai dengan hal-hal menarik , pertama.Saya…
Hidup dengan herpes telah menjadi perjalanan penerimaan diri Seperti yang diceritakan pada Kimberly RexSaya mengalami gejala pertama saya pada hari Minggu di bulan Juli 2011. Saya berusia 28 tahun. Setelah menghabiskan akhir pekan dengan pria yang pernah saya…
Saya mendapatkan bentuk terbaik dalam hidup saya… Seperti yang diceritakan kepada Nicole Audrey SpectorSaya tahu bahwa saya membiarkan stres menguasai diri saya, terutama jika berkaitan dengan kebiasaan makan yang buruk, tetapi saya tidak menyadari betapa buruknya hal…
Kamaru Usman mengatakan dia mengajukan petisi ke UFC… Apa yang kamu lakukan jika kamu ingin menjadi juara dua divisi tetapi temanmu memegang sabuk di kelas berat di atas? Mengapa, Anda naik dua kelas berat. Usman mengatakan dia tertarik…
Kyrie Irving beringsut menuju kembalinya ke… Guard Brooklyn Nets Kyrie Irving menjadi berita utama sebelum dimulainya musim NBA setelah mengungkapkan pendiriannya tentang mandat New York City. Sikap Irving membatasi permainannya menjadi 14 pertandingan jalan musim ini…
Paulo Costa merobek 'macho palsu' Sean… 18 Maret 2022 11:20 ET Paulo Costa memiliki beberapa pilihan kata untuk Sean Strickland setelah dia mengubah nadanya pada pertarungan potensial. Strickland (25-3 MMA, 12-3 UFC) memanggil Costa pada November…
Rahasia Meningkatkan Percaya Diri: Langkah Mudah… Membangun Rasa Percaya Diri yang Kuat: Panduan Langkah demi Langkah Pernahkah Anda merasa minder atau tidak yakin pada diri sendiri? Jika ya, Anda tidak sendirian. Banyak orang yang berjuang dengan…
Mendapatkan bantuan untuk kesehatan mental Anda… Juli Bulan Kesadaran Kesehatan Mental Minoritas Nasional. Seperti yang diceritakan oleh Erica RellingerSaya adalah seorang remaja pertama kali saya melihat dokter sendiri. Itu di Chinatown, jadi dokter yang saya temui…
Chris Weidman bersumpah untuk kembali tahun ini… Anda belum pernah melihat mantan UFC terakhir juara kelas menengah Chris Weidman. Weidman, 37, mengalami patah kaki yang mengerikan di awal pertarungan dengan Uriah Hall pada bulan April lalu tahun…
Sejarah Indonesia Kelas 12 Semester 1: Kisah… Sebagai pelajar kelas 12, memahami sejarah Indonesia semester 1 tentunya menjadi tantangan tersendiri. Banyaknya materi dan menghafalkannya tentu membuat kamu kewalahan. Belum lagi soal ujian yang semakin dekat, membuat kamu…