[] dan {} vs list () dan dict (), mana yang lebih baik?

113

Saya mengerti bahwa keduanya pada dasarnya adalah hal yang sama, tetapi dalam hal gaya, mana yang lebih baik (lebih Pythonic) yang digunakan untuk membuat daftar kosong atau dikt?

Noah McIlraith
sumber

Jawaban:

197

Dalam hal kecepatan, ini bukan persaingan untuk daftar kosong:

>>> from timeit import timeit
>>> timeit("[]")
0.040084982867934334
>>> timeit("list()")
0.17704233359267718
>>> timeit("{}")
0.033620194745424214
>>> timeit("dict()")
0.1821558326547077

dan untuk yang tidak kosong:

>>> timeit("[1,2,3]")
0.24316302770330367
>>> timeit("list((1,2,3))")
0.44744206316727286
>>> timeit("list(foo)", setup="foo=(1,2,3)")
0.446036018543964
>>> timeit("{'a':1, 'b':2, 'c':3}")
0.20868602015059423
>>> timeit("dict(a=1, b=2, c=3)")
0.47635635255323905
>>> timeit("dict(bar)", setup="bar=[('a', 1), ('b', 2), ('c', 3)]")
0.9028228448029267

Selain itu, menggunakan notasi braket memungkinkan Anda menggunakan pemahaman daftar dan kamus, yang mungkin menjadi alasan yang cukup.

Greg Haskins
sumber
4
Pemahaman dikte dan daftar dapat dilakukan dengan menggunakan nama bahasa Inggris juga. Contoh:list(i for i in range(10) if i % 2)
Zags
4
adakah alasan mengapa {} dan [] jauh lebih cepat? Saya pikir mereka hanyalah alias.
Justin D.
Waktu tampaknya tidak memberikan waktu yang akurat. Sesuai patokan, tampaknya membutuhkan ~ 200ms yang jauh lebih lambat dari panggilan http normal. Coba jalankan dict () secara normal di shell dan kemudian jalankan timeit ("dict ()"), Anda akan melihat perbedaan yang terlihat dalam eksekusi.
piyush
2
@piyush Sebenarnya, timeit()fungsi ini melaporkan jumlah total waktu untuk mengeksekusi sejumlah iterasi tertentu, yang secara 1000000default. Jadi contoh di atas adalah jumlah detik untuk menjalankan cuplikan kode jutaan kali. Misalnya timeit('dict()', number=1) // -> 4.0531158447265625e-06(satu iterasi) sementara timeit('dict()') // -> 0.12412905693054199(satu juta iterasi)
Greg Haskins
@GregHaskins jadi dalam hal ini, saya tidak melihat orang perlu khawatir tentang penggunaan dict () atau {}, kecuali melakukan perulangan melalui satu juta catatan & menggunakan dict () dalam loop.
piyush
37

Menurut saya []dan {}merupakan cara yang paling pythonic dan dapat dibaca untuk membuat daftar kosong / dicts.

Berhati-hatilah dengan set()itu, misalnya:

this_set = {5}
some_other_set = {}

Bisa membingungkan. Yang pertama membuat sebuah set dengan satu elemen, yang kedua membuat sebuah dict kosong dan bukan sebuah set.

orlp
sumber
4
{}selalu membuat dikt yang kosong. {1,2,3}membuat set di 2.7+ tetapi merupakan kesalahan sintaks di 2.6dan versi yang lebih lama.
ThiefMaster
1
Maaf? itu adalah variabel dengan nama some_epic_setyang menunjuk ke dictobjek kosong ... itu bukan himpunan kosong. Untuk set kosong yang perlu Anda gunakan set().
6502
2
@ 6502: Memang, tetapi ini adalah kesalahan umum yang {5}membuat himpunan dengan satu elemen, 5dan {}merupakan dict kosong.
orlp
1
Wow, tadi itu membingungkan. Tetap saja, Fractal of Bad Design itu tidak setingkat membingungkan. :-)
Prof. Falken
4
@EnderLook: Sebenarnya, dengan pembongkaran umum , Anda dapat menggunakan {*()}untuk mengosongkan setdengan sintaks literal. Saya menyebutnya operator monyet bermata satu. :-)
ShadowRanger
17

Dict harfiah mungkin kecil sedikit lebih cepat sebagai bytecode yang lebih pendek:

In [1]: import dis
In [2]: a = lambda: {}
In [3]: b = lambda: dict()

In [4]: dis.dis(a)
  1           0 BUILD_MAP                0
              3 RETURN_VALUE

In [5]: dis.dis(b)
  1           0 LOAD_GLOBAL              0 (dict)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

Hal yang sama berlaku untuk listvs.[]

ThiefMaster
sumber
8
Ini mengasumsikan bahwa BUILD_MAP dan LOAD_GLOBAL adalah waktu yang konstan dan membutuhkan waktu yang sama. Sangat tidak mirip. waktu itu memberikan perkiraan yang jauh lebih baik.
Jamie Pate
Lebih mungkin, CALL_FUNCTIONmengambil setidaknya waktu sebanyak BUILD_MAP(fungsi dipanggil dasarnya adalah BUILD_MAP), dan LOAD_GLOBALdibutuhkan hanya tambahan biaya overhead.
chepner
3

IMHO, menggunakan list()dan dict()membuat Python Anda terlihat seperti C. Ugh.

RichieHindle
sumber
3

Dalam kasus perbedaan antara [] dan list (), ada jebakan yang belum pernah saya lihat orang lain tunjukkan. Jika Anda menggunakan kamus sebagai anggota daftar, keduanya akan memberikan hasil yang sangat berbeda:

In [1]: foo_dict = {"1":"foo", "2":"bar"}

In [2]: [foo_dict]
Out [2]: [{'1': 'foo', '2': 'bar'}]

In [3]: list(foo_dict)
Out [3]: ['1', '2'] 
oxtay
sumber
Anda bisa mendapatkan hasil yang sama [foo_dict]dengan menggunakan list((foo_dict,)). The list()Metode mengambil iterable karena hanya parameter dan iterates di atasnya untuk menambahkan elemen ke dalam daftar. Ini akan menyebabkan kesalahan serupa dengan melakukan list(some_list)yang akan meratakan daftar.
sotrh
1

list () dan [] bekerja secara berbeda:

>>> def a(p=None):
...     print(id(p))
... 
>>> for r in range(3):
...     a([])
... 
139969725291904
139969725291904
139969725291904
>>> for r in range(3):
...     a(list())
... 
139969725367296
139969725367552
139969725367616

list () selalu membuat objek baru di heap, tetapi [] dapat menggunakan kembali sel memori karena berbagai alasan.

andreykyz
sumber
0

ada satu perbedaan dalam perilaku antara [] dan list () seperti yang ditunjukkan contoh di bawah ini. kita perlu menggunakan list () jika kita ingin daftar angka dikembalikan, jika tidak kita mendapatkan objek peta! Tidak yakin bagaimana menjelaskannya.

sth = [(1,2), (3,4),(5,6)]
sth2 = map(lambda x: x[1], sth) 
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>

sth2 = [map(lambda x: x[1], sth)]
print(sth2) # print returns object <map object at 0x000001AB34C1D9B0>
type(sth2) # list 
type(sth2[0]) # map

sth2 = list(map(lambda x: x[1], sth))
print(sth2) #[2, 4, 6]
type(sth2) # list
type(sth2[0]) # int
sebtac
sumber
di sini tampaknya ada penjelasan tentang perilaku menggunakan contoh fungsi range () >>> print (range (10)) # range (0, 10) range () berperilaku seperti daftar, tetapi ini bukan daftar. Ini adalah objek yang mengembalikan item berurutan dari sebuah urutan ketika Anda mengulanginya, itu tidak benar-benar membuat daftar, menghemat ruang. objek seperti itu dapat diulang, yaitu, cocok sebagai target untuk fungsi dan konstruksi yang mengharapkan sesuatu dari mana mereka dapat memperoleh item yang berurutan sampai persediaan habis. Daftar fungsi () membuat daftar dari iterable: >>> list (range (5)) # [0, 1, 2, 3, 4]
sebtac
1
konsekuensinya adalah [] menyimpan objek iterable; list () membuat daftar dari iterable yang sama
sebtac
0

Pasangan tanda kurung kotak menunjukkan salah satu objek daftar, atau subskrip indeks, my_List [x].

Pasangan kurung kurawal menunjukkan objek kamus.

a_list = ['hidup', 'mati', 1, 2]

a_dict = {pada: 1, mati: 2}

Rohit Chaurasiya
sumber
-5

Ini terutama masalah pilihan di sebagian besar waktu. Ini masalah preferensi.

Namun perlu diperhatikan bahwa jika Anda memiliki kunci numerik misalnya, Anda tidak dapat melakukan:

mydict = dict(1="foo", 2="bar")

Kamu harus melakukan:

mydict = {"1":"foo", "2":"bar"}
Ikke
sumber
7
Ini salah ... Anda perlu melakukannya mydict = {1:"foo", 2:"bar"}(tanpa tanda kutip untuk kunci).
6502
8
Ini tidak hanya "salah". Kuncinya adalah string / int tergantung pada apakah Anda mengutipnya atau tidak.
ThiefMaster