lenmerupakan fungsi untuk mendapatkan panjang suatu koleksi. Ia bekerja dengan memanggil __len__metode objek. __something__atribut khusus dan biasanya lebih dari yang terlihat, dan umumnya tidak boleh dipanggil secara langsung.
Telah diputuskan pada suatu saat yang lalu mendapatkan panjang dari sesuatu harus menjadi fungsi dan bukan kode metode, alasan itu len(a)artinya akan jelas bagi pemula tetapi a.len()tidak akan sejelas. Ketika Python dimulai __len__bahkan tidak ada dan lenmerupakan hal khusus yang bekerja dengan beberapa jenis objek. Apakah situasi ini membuat kita benar-benar masuk akal atau tidak, itu akan tetap ada.
Seringkali terjadi bahwa perilaku "khas" dari operator atau bawaan adalah memanggil (dengan sintaks yang berbeda dan lebih bagus) metode ajaib yang sesuai (yang memiliki nama seperti __whatever__) pada objek yang terlibat. Seringkali operator atau bawaan memiliki "nilai tambah" (dapat mengambil jalur yang berbeda bergantung pada objek yang terlibat) - dalam kasus lenvs __len__, itu hanya sedikit pemeriksaan kewarasan pada bawaan yang hilang dari metode ajaib:
>>>class bah(object):...def __len__(self):return"an inch"...>>> bah().__len__()'an inch'>>> len(bah())Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError:'str' object cannot be interpreted as an integer
Saat Anda melihat panggilan ke lenbuilt-in, Anda yakin bahwa, jika program berlanjut setelah itu daripada memunculkan pengecualian, panggilan tersebut mengembalikan integer, non-negatif, dan kurang dari 2 ** 31 - saat Anda melihat panggilan ke xxx.__len__(), Anda tidak memiliki kepastian (kecuali bahwa pembuat kode tidak terbiasa dengan Python atau tidak bagus ;-).
Built-in lainnya memberikan nilai tambah lebih dari sekadar pemeriksaan kewarasan dan keterbacaan. Dengan mendesain secara seragam semua Python untuk bekerja melalui panggilan ke bawaan dan penggunaan operator, tidak pernah melalui panggilan ke metode ajaib, programmer terhindar dari beban mengingat kasus mana yang mana. (Kadang-kadang kesalahan menyelinap di: hingga 2.5, Anda harus memanggil foo.next()- di 2.6, sementara itu masih berfungsi untuk kompatibilitas mundur, Anda harus memanggil next(foo), dan di 3.*, metode ajaib dinamai dengan benar __next__alih-alih "oops-ey" next! - ).
Jadi aturan umumnya adalah jangan pernah memanggil metode ajaib secara langsung (tetapi selalu secara tidak langsung melalui built-in) kecuali Anda tahu persis mengapa Anda perlu melakukan itu (misalnya, ketika Anda mengganti metode seperti itu dalam subkelas, jika subclass harus tunduk pada superclass yang harus dilakukan melalui panggilan eksplisit ke metode ajaib).
Saya adalah pengguna Python pemula (bukan pemrogram pemula yang berpikir) dan saya tidak yakin tentang "Ketika Anda melihat panggilan ke len built-in, Anda yakin bahwa, jika program berlanjut setelah itu daripada memunculkan pengecualian". Saya mencoba ini: def len(x): return "I am a string." print(len(42)) print(len([1,2,3]))dan dicetak I am stringdua kali. Bisakah Anda menjelaskannya lebih lanjut?
Darek Nędza
4
@ DarekNędza Ini tidak ada hubungannya dengan hal di atas, yaitu tentang builtin len. Anda baru saja menentukan fungsi len Anda, yang tentu saja dapat mengembalikan apa pun yang Anda inginkan. OP berbicara tentang builtin len, yang memanggil metode__len__ khusus (bukan fungsi) pada objek yang sedang dipertimbangkan.
Veky
@Veky Bagaimana saya bisa yakin bahwa saya memanggil fungsi built-in lenbukan beberapa fungsi lain (seperti dalam contoh saya) yang kebetulan memiliki nama yang sama - len. Tidak ada peringatan seperti "Anda mendefinisikan ulang fungsi built-in len" atau sesuatu seperti ini. Menurut saya, saya tidak bisa memastikan apa yang dikatakan Alex dalam jawabannya.
Darek Nędza
3
Alex secara eksplisit mengatakan jika Anda menelepon builtin, maka Anda yakin ..._. Dia tidak mengatakan apa-apa tentang memastikan Anda menelepon builtin. Tetapi jika Anda ingin tahu bahwa, Anda dapat: len in vars(__builtins__).values().
Veky
1
Sayangnya, ini adalah contoh lain dari kurangnya kelas dasar yang sama untuk objek dengan Python. Peralihan konteks sintaksis selalu gila. Dalam beberapa kasus, menggunakan metode garis bawah adalah idiom umum, dalam kasus lain seseorang harus menggunakan sesuatu seperti fungsi untuk melakukan sesuatu yang umum ke banyak objek. Ini juga aneh karena banyak objek tidak memiliki penggunaan semantik untuk len. Terkadang model objek lebih seperti C ++, kitchen sinky ..
uchuugaka
28
Anda bisa menganggap len () secara kasar setara dengan
def len(x):return x.__len__()
Salah satu keuntungannya adalah memungkinkan Anda untuk menulis hal-hal seperti
somelist =[[1],[2,3],[4,5,6]]
map(len, somelist)
dari pada
map(list.__len__, somelist)
atau
map(operator.methodcaller('__len__'), somelist)
Ada perilaku yang sedikit berbeda. Misalnya dalam kasus ints
>>>(1).__len__()Traceback(most recent call last):File"<stdin>", line 1,in<module>AttributeError:'int' object has no attribute '__len__'>>> len(1)Traceback(most recent call last):File"<stdin>", line 1,in<module>TypeError: object of type 'int' has no len()
Jawaban:
len
merupakan fungsi untuk mendapatkan panjang suatu koleksi. Ia bekerja dengan memanggil__len__
metode objek.__something__
atribut khusus dan biasanya lebih dari yang terlihat, dan umumnya tidak boleh dipanggil secara langsung.Telah diputuskan pada suatu saat yang lalu mendapatkan panjang dari sesuatu harus menjadi fungsi dan bukan kode metode, alasan itu
len(a)
artinya akan jelas bagi pemula tetapia.len()
tidak akan sejelas. Ketika Python dimulai__len__
bahkan tidak ada danlen
merupakan hal khusus yang bekerja dengan beberapa jenis objek. Apakah situasi ini membuat kita benar-benar masuk akal atau tidak, itu akan tetap ada.sumber
Seringkali terjadi bahwa perilaku "khas" dari operator atau bawaan adalah memanggil (dengan sintaks yang berbeda dan lebih bagus) metode ajaib yang sesuai (yang memiliki nama seperti
__whatever__
) pada objek yang terlibat. Seringkali operator atau bawaan memiliki "nilai tambah" (dapat mengambil jalur yang berbeda bergantung pada objek yang terlibat) - dalam kasuslen
vs__len__
, itu hanya sedikit pemeriksaan kewarasan pada bawaan yang hilang dari metode ajaib:Saat Anda melihat panggilan ke
len
built-in, Anda yakin bahwa, jika program berlanjut setelah itu daripada memunculkan pengecualian, panggilan tersebut mengembalikan integer, non-negatif, dan kurang dari 2 ** 31 - saat Anda melihat panggilan kexxx.__len__()
, Anda tidak memiliki kepastian (kecuali bahwa pembuat kode tidak terbiasa dengan Python atau tidak bagus ;-).Built-in lainnya memberikan nilai tambah lebih dari sekadar pemeriksaan kewarasan dan keterbacaan. Dengan mendesain secara seragam semua Python untuk bekerja melalui panggilan ke bawaan dan penggunaan operator, tidak pernah melalui panggilan ke metode ajaib, programmer terhindar dari beban mengingat kasus mana yang mana. (Kadang-kadang kesalahan menyelinap di: hingga 2.5, Anda harus memanggil
foo.next()
- di 2.6, sementara itu masih berfungsi untuk kompatibilitas mundur, Anda harus memanggilnext(foo)
, dan di3.*
, metode ajaib dinamai dengan benar__next__
alih-alih "oops-ey"next
! - ).Jadi aturan umumnya adalah jangan pernah memanggil metode ajaib secara langsung (tetapi selalu secara tidak langsung melalui built-in) kecuali Anda tahu persis mengapa Anda perlu melakukan itu (misalnya, ketika Anda mengganti metode seperti itu dalam subkelas, jika subclass harus tunduk pada superclass yang harus dilakukan melalui panggilan eksplisit ke metode ajaib).
sumber
def len(x): return "I am a string." print(len(42)) print(len([1,2,3]))
dan dicetakI am string
dua kali. Bisakah Anda menjelaskannya lebih lanjut?__len__
khusus (bukan fungsi) pada objek yang sedang dipertimbangkan.len
bukan beberapa fungsi lain (seperti dalam contoh saya) yang kebetulan memiliki nama yang sama -len
. Tidak ada peringatan seperti "Anda mendefinisikan ulang fungsi built-in len" atau sesuatu seperti ini. Menurut saya, saya tidak bisa memastikan apa yang dikatakan Alex dalam jawabannya.len in vars(__builtins__).values()
.Anda bisa menganggap len () secara kasar setara dengan
Salah satu keuntungannya adalah memungkinkan Anda untuk menulis hal-hal seperti
dari pada
atau
Ada perilaku yang sedikit berbeda. Misalnya dalam kasus ints
sumber
operator.methodcaller
bukanoperator.attrgetter
.Anda dapat memeriksa dokumen Pythond :
sumber