[] ve {} ile list () ve dict () karşılaştırması, hangisi daha iyi?


113

Her ikisinin de aslında aynı şey olduğunu anlıyorum, ancak stil açısından, boş bir liste veya dikte oluşturmak için kullanılacak daha iyi (daha Pythonic) hangisi?

Yanıtlar:


197

Hız açısından, boş listeler / sözler için rekabet yok:

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

ve boş olmayanlar için:

>>> 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

Ayrıca, köşeli parantez gösterimini kullanmak, liste ve sözlük anlamalarını kullanmanıza izin verir, bu da yeterli bir sebep olabilir.


4
Dikte ve liste anlamaları da İngilizce isimler kullanılarak yapılabilir. Örnek:list(i for i in range(10) if i % 2)
Zags

4
{} ve [] 'nin bu kadar hızlı olmasının bir nedeni var mı? Bunların sadece takma adlar olduğunu sanıyordum.
Justin D.

Zaman doğru zaman vermiyor gibi görünüyor. Kriter olarak, normal http çağrılarından çok daha yavaş olan ~ 200ms sürüyor gibi görünüyor. Dict () öğesini normal olarak kabukta çalıştırmayı deneyin ve ardından timeit ("dict ()") çalıştırın, yürütmede gözle görülür bir fark göreceksiniz.
piyush

2
@piyush Gerçekte, timeit()işlev, 1000000varsayılan olarak belirtilen sayıda yinelemenin yürütülmesi için toplam süreyi bildirir . Dolayısıyla yukarıdaki örnekler, kod parçacığını bir milyon kez çalıştırmak için gereken saniye sayısıdır. Örneğin timeit('dict()', number=1) // -> 4.0531158447265625e-06(bir yineleme) while timeit('dict()') // -> 0.12412905693054199(bir milyon yineleme)
Greg Haskins

@GregHaskins, bu durumda, bir milyon kayıttan geçip döngüde dict () kullanmadıkça, dict () veya {} kullanma konusunda endişelenmemiz gerektiğini görmüyorum.
piyush

37

Bence []ve {}boş listeleri / dicts oluşturmak için en pythonic ve okunabilir yollarıdır.

set()Yine de dikkatli olun , örneğin:

this_set = {5}
some_other_set = {}

Kafa karıştırıcı olabilir. Birincisi, tek öğeli bir küme oluşturur, ikincisi bir küme değil , boş bir dikte oluşturur .


4
{}her zaman boş bir söz oluşturur. {1,2,3}2.7+ 2.6sürümünde bir küme oluşturur ancak ve daha eski sürümlerde bir sözdizimi hatasıdır .
ThiefMaster

1
afedersiniz? bu, adı some_epic_setboş bir dictnesneyi gösteren bir değişkendir ... boş bir küme değil. Boş bir set için kullanmanız gerekir set().
6502

2
@ 6502: Gerçekten, ancak {5}tek öğeli bir set oluşturan 5ve {}boş bir dikt olan yaygın bir tuzaktır.
orlp

1
Vay canına, kafa karıştırıcıydı. Yine de, Fraktal Kötü Tasarım seviyesi kafa karıştırıcı değil. :-)
Prof. Falken

4
@EnderLook: Aslında, genelleştirilmiş paket açma ile , değişmez sözdizimi ile {*()}bir boş yapmak için kullanabilirsiniz set. Ben buna tek gözlü maymun operatörü diyorum. :-)
ShadowRanger

17

Dict değişmezi bir olabilir küçücük onun baytkodu kısadır olarak daha hızlı bit:

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

Aynısı listvs için de geçerlidir[]


8
Bu, BUILD_MAP ve LOAD_GLOBAL'ın sabit zaman olduğunu ve aynı süreyi aldığını varsayar. Hiç alışılmadık bir şekilde. timeit çok daha iyi bir tahmin verir.
Jamie Pate

Büyük olasılıkla, CALL_FUNCTIONsürer en azından kadar zaman olarak BUILD_MAP(fonksiyon esas olarak adlandırılır niteliğinde BUILD_MAP) ve LOAD_GLOBALsadece ek yükü olduğunu sürer.
chepner


3

[] Ve list () arasında fark olması durumunda, başka kimsenin işaret ettiğini görmediğim bir tuzak var. Listenin bir üyesi olarak bir sözlüğü kullanırsanız, ikisi tamamen farklı sonuçlar verecektir:

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'] 

Sen aynı sonuçları elde edebilirsiniz [foo_dict]kullanarak list((foo_dict,)). list()O listeye unsurları eklemek için üzerinde tek parametre ve yineler olduğu gibi yöntem bir iterable sürer. Bu list(some_list), listeyi düzleştirecek şekilde benzer bir tuzağa neden olacaktır.
sotrh

1

list () ve [] farklı çalışır:

>>> 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 () her zaman öbek içinde yeni nesne yaratır, ancak [] bellek hücresini birçok nedenden dolayı yeniden kullanabilir.


0

Aşağıdaki örnekte gösterildiği gibi [] ile list () arasında davranış açısından bir fark vardır. eğer sayıların bir listesini döndürmek istiyorsak list () kullanmamız gerekir, aksi takdirde bir harita nesnesi elde ederiz! Nasıl açıklayacağımı bilmiyorum.

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

Burada range () fonksiyonu >>> print (range (10)) # range (0, 10) range () bir liste gibi davranır, ancak bu bir liste değildir. Bir dizinin ardışık öğelerini, üzerinde yinelediğinizde döndüren bir nesnedir, gerçekten listeyi oluşturmaz, yerden tasarruf sağlar. böyle bir nesne yinelenebilir, yani arz tükenene kadar birbirini takip eden öğeleri elde edebilecekleri bir şey bekleyen işlevler ve yapılar için bir hedef olarak uygundur. İşlev listesi () yinelenenlerden listeler oluşturur: >>> list (range (5)) # [0, 1, 2, 3, 4]
sebtac

1
sonuç [] yinelenebilir nesneyi saklar; list () aynı yinelenebilir listeden bir liste oluşturur
sebtac

0

Bir kutu parantez çifti, bir liste nesnesi veya bir indeks alt simgesi olan my_List [x] 'i belirtir.

Küme ayracı çifti, bir sözlük nesnesini belirtir.

a_list = ['açık', 'kapalı', 1, 2]

a_dict = {açık: 1, kapalı: 2}


-5

Çoğu zaman esas olarak bir seçim meselesidir. Bu bir tercih meselesi.

Bununla birlikte, örneğin sayısal tuşlarınız varsa şunları yapamayacağınızı unutmayın:

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

Yapmak zorundasın:

mydict = {"1":"foo", "2":"bar"}

7
Bu yanlış ... yapmanız gerekiyor mydict = {1:"foo", 2:"bar"}(anahtarlar için tırnak işareti olmadan).
6502

8
Bu sadece "yanlış" değil. Anahtarlar, alıntı yapıp yapmamanıza bağlı olarak dizeler / inlerdir.
ThiefMaster
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.