Pertimbangkan yang berikut ini:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
Bagaimana cara saya mendapatkan jumlah elemen dalam daftar items
?
Pertimbangkan yang berikut ini:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
Bagaimana cara saya mendapatkan jumlah elemen dalam daftar items
?
Jawaban:
Bagaimana cara mendapatkan ukuran daftar?
Untuk menemukan ukuran daftar, menggunakan fungsi builtin, len
:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
Dan sekarang:
len(items)
mengembalikan 3.
Segala sesuatu di Python adalah objek, termasuk daftar. Semua objek memiliki semacam header dalam implementasi C.
Daftar dan objek builtin serupa lainnya dengan "ukuran" di Python, khususnya, memiliki atribut yang disebut ob_size
, di mana jumlah elemen dalam objek di-cache. Jadi memeriksa jumlah objek dalam daftar sangat cepat.
Tetapi jika Anda memeriksa apakah ukuran daftar nol atau tidak, jangan gunakan len
- sebagai gantinya, masukkan daftar dalam konteks boolean - itu diperlakukan sebagai False jika kosong, Benar sebaliknya .
len(s)
Mengembalikan panjang (jumlah item) suatu objek. Argumennya bisa berupa urutan (seperti string, byte, tuple, daftar, atau rentang) atau koleksi (seperti kamus, set, atau set beku).
len
diimplementasikan dengan __len__
, dari dokumen model data :
object.__len__(self)
Dipanggil untuk mengimplementasikan fungsi bawaan
len()
. Harus mengembalikan panjang objek, bilangan bulat> = 0. Juga, objek yang tidak mendefinisikan metode__nonzero__()
[dengan Python 2 atau__bool__()
Python 3] dan__len__()
metode yang mengembalikan nol dianggap salah dalam konteks Boolean.
Dan kita juga bisa melihat itu __len__
adalah metode daftar:
items.__len__()
mengembalikan 3.
len
(panjang) dariDan sebenarnya kita melihat kita bisa mendapatkan informasi ini untuk semua jenis yang dijelaskan:
>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list,
xrange, dict, set, frozenset))
True
len
untuk menguji daftar kosong atau kosongUntuk menguji panjang tertentu, tentu saja, cukup menguji kesetaraan:
if len(items) == required_length:
...
Tetapi ada kasus khusus untuk pengujian untuk daftar panjang nol atau kebalikannya. Dalam hal itu, jangan menguji kesetaraan.
Juga, jangan lakukan:
if len(items):
...
Sebaliknya, lakukan saja:
if items: # Then we have some items, not empty!
...
atau
if not items: # Then we have an empty list!
...
Saya jelaskan mengapa di sini tetapi singkatnya, if items
atau if not items
keduanya lebih mudah dibaca dan lebih berkinerja.
Walaupun ini mungkin tidak berguna karena fakta bahwa itu akan jauh lebih masuk akal sebagai fungsi "di luar kotak", peretasan yang cukup sederhana adalah membangun kelas dengan length
properti:
class slist(list):
@property
def length(self):
return len(self)
Anda dapat menggunakannya seperti ini:
>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Pada dasarnya, ini persis identik dengan objek daftar, dengan manfaat tambahan dari memiliki length
properti ramah-OOP .
Seperti biasa, jarak tempuh Anda mungkin bervariasi.
length = property(len)
dan melewatkan fungsi pembungkus satu baris dan menyimpan dokumentasi / introspeksi len
dengan properti Anda.
Selain itu len
Anda juga dapat menggunakan operator.length_hint
(membutuhkan Python 3.4+). Untuk yang normal list
keduanya sama, tetapi length_hint
memungkinkan untuk mendapatkan panjang daftar-iterator, yang bisa berguna dalam keadaan tertentu:
>>> from operator import length_hint
>>> l = ["apple", "orange", "banana"]
>>> len(l)
3
>>> length_hint(l)
3
>>> list_iterator = iter(l)
>>> len(list_iterator)
TypeError: object of type 'list_iterator' has no len()
>>> length_hint(list_iterator)
3
Tapi length_hint
menurut definisi hanya "petunjuk", jadi sebagian besar waktu len
lebih baik.
Saya telah melihat beberapa jawaban yang menyarankan mengakses __len__
. Ini baik-baik saja ketika berhadapan dengan kelas bawaan seperti list
, tetapi bisa menimbulkan masalah dengan kelas khusus, karena len
(dan length_hint
) menerapkan beberapa pemeriksaan keamanan. Misalnya, keduanya tidak memungkinkan panjang negatif atau panjang yang melebihi nilai tertentu ( sys.maxsize
nilai). Jadi selalu lebih aman menggunakan len
fungsi daripada __len__
metode!
Menjawab pertanyaan Anda sebagai contoh juga diberikan sebelumnya:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__foo__
.: ini hanya sebuah konvensi, cara bagi sistem Python untuk menggunakan nama yang tidak akan bertentangan dengan nama pengguna. 2 _foo
.: ini hanya sebuah konvensi, cara bagi pemrogram untuk menunjukkan bahwa variabel bersifat pribadi (apa pun artinya dengan Python). 3 __foo
.: ini memiliki arti nyata: penerjemah menggantikan nama ini dengan _classname__foo
cara untuk memastikan bahwa nama tersebut tidak akan tumpang tindih dengan nama yang serupa di kelas lain. * Tidak ada bentuk garis bawah yang memiliki makna di dunia Python. * Tidak ada perbedaan antara kelas, variabel, global, dll dalam konvensi ini.
Dan untuk kelengkapan (terutama pendidikan), dimungkinkan tanpa menggunakan len()
fungsi. Saya tidak akan memaafkan ini sebagai opsi yang baik JANGAN PROGRAM SEPERTI INI DI PYTHON , tetapi ini melayani tujuan untuk mempelajari algoritma.
def count(list):
item_count = 0
for item in list[:]:
item_count += 1
return item_count
count([1,2,3,4,5])
(Usus besar dalam list[:]
adalah implisit dan karena itu juga opsional.)
Pelajaran di sini untuk programmer baru adalah: Anda tidak bisa mendapatkan jumlah item dalam daftar tanpa menghitungnya di beberapa titik. Pertanyaannya menjadi: kapan waktu yang tepat untuk menghitungnya? Misalnya, kode berperforma tinggi seperti sambungkan sistem panggilan untuk soket (ditulis dalam C) connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
, tidak menghitung panjang elemen (memberikan tanggung jawab itu pada kode panggilan). Perhatikan bahwa panjang alamat dilewatkan untuk menyimpan langkah penghitungan panjang terlebih dahulu? Pilihan lain: secara komputasi, mungkin masuk akal untuk melacak jumlah item saat Anda menambahkannya dalam objek yang Anda lewati. Pikiran bahwa ini membutuhkan lebih banyak ruang dalam memori. Lihat jawaban Naftuli Kay .
Contoh melacak panjang untuk meningkatkan kinerja sambil mengambil lebih banyak ruang di memori. Perhatikan bahwa saya tidak pernah menggunakan fungsi len () karena panjangnya dilacak:
class MyList(object):
def __init__(self):
self._data = []
self.length = 0 # length tracker that takes up memory but makes length op O(1) time
# the implicit iterator in a list class
def __iter__(self):
for elem in self._data:
yield elem
def add(self, elem):
self._data.append(elem)
self.length += 1
def remove(self, elem):
self._data.remove(elem)
self.length -= 1
mylist = MyList()
mylist.add(1)
mylist.add(2)
mylist.add(3)
print(mylist.length) # 3
mylist.remove(3)
print(mylist.length) # 2
for item in list[:]:
? Mengapa tidak for item in list:
? Juga, saya gunakan += 1
untuk menambah.
Dalam hal bagaimana len()
sebenarnya bekerja, ini adalah implementasi C-nya :
static PyObject *
builtin_len(PyObject *module, PyObject *obj)
/*[clinic end generated code: output=fa7a270d314dfb6c input=bc55598da9e9c9b5]*/
{
Py_ssize_t res;
res = PyObject_Size(obj);
if (res < 0) {
assert(PyErr_Occurred());
return NULL;
}
return PyLong_FromSsize_t(res);
}
Py_ssize_t
adalah panjang maksimum yang dapat dimiliki objek. PyObject_Size()
adalah fungsi yang mengembalikan ukuran suatu objek. Jika tidak dapat menentukan ukuran suatu objek, ia mengembalikan -1. Dalam hal ini, blok kode ini akan dieksekusi:
if (res < 0) {
assert(PyErr_Occurred());
return NULL;
}
Dan sebagai hasilnya muncul pengecualian. Jika tidak, blok kode ini akan dieksekusi:
return PyLong_FromSsize_t(res);
res
yang merupakan C
bilangan bulat, diubah menjadi python long
dan dikembalikan. Semua bilangan bulat python disimpan seperti longs
sejak Python 3.