[] และ {} vs list () และ dict () อันไหนดีกว่ากัน


คำตอบ:


197

ในแง่ของความเร็วไม่มีการแข่งขันสำหรับรายการ / คำสั่งที่ว่างเปล่า:

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

และสำหรับการไม่ว่างเปล่า:

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

นอกจากนี้การใช้เครื่องหมายวงเล็บยังช่วยให้คุณสามารถใช้ความเข้าใจในรายการและพจนานุกรมซึ่งอาจมีเหตุผลเพียงพอ


4
การทำความเข้าใจตามคำบอกและรายการสามารถทำได้โดยใช้ชื่อภาษาอังกฤษเช่นกัน ตัวอย่าง:list(i for i in range(10) if i % 2)
Zags

4
มีเหตุผลว่าทำไม {} และ [] จึงเร็วกว่ามาก ฉันคิดว่ามันเป็นแค่นามแฝง
Justin D.

เวลาดูเหมือนจะไม่ได้ให้เวลาที่ถูกต้อง ตามเกณฑ์มาตรฐานดูเหมือนว่าจะใช้เวลาประมาณ 200 มิลลิวินาทีซึ่งช้ากว่าการโทร http ปกติ ลองเรียกใช้ dict () ตามปกติในเชลล์แล้วเรียกใช้ timeit ("dict ()") คุณจะเห็นความแตกต่างที่มองเห็นได้ในการดำเนินการ
piyush

2
@piyush จริงๆแล้วtimeit()ฟังก์ชันจะรายงานระยะเวลาทั้งหมดในการดำเนินการซ้ำตามจำนวนที่ระบุซึ่งเป็น1000000ค่าเริ่มต้น ดังนั้นตัวอย่างข้างต้นคือจำนวนวินาทีในการเรียกใช้ข้อมูลโค้ดหนึ่งล้านครั้ง ตัวอย่างเช่นtimeit('dict()', number=1) // -> 4.0531158447265625e-06(การวนซ้ำหนึ่งครั้ง) ในขณะที่timeit('dict()') // -> 0.12412905693054199(การวนซ้ำเป็นล้านครั้ง)
Greg Haskins

@GregHaskins ดังนั้นในกรณีนี้ฉันไม่เห็นว่าจะมีใครกังวลเกี่ยวกับการใช้ dict () หรือ {} เว้นแต่จะวนซ้ำเป็นล้านระเบียนและใช้ dict () ในลูป
piyush

37

ในความคิดของฉัน[]และ{}เป็นวิธีที่ง่ายและอ่านง่ายที่สุดในการสร้างรายการ / คำสั่งที่ว่างเปล่า

โปรดระวังset()ตัวอย่างเช่น:

this_set = {5}
some_other_set = {}

อาจทำให้สับสนได้ ครั้งแรกสร้างชุดที่มีองค์ประกอบเดียวส่วนที่สองสร้างคำสั่งว่างเปล่าไม่ใช่ชุด


4
{}สร้างคำสั่งที่ว่างเปล่าเสมอ {1,2,3}สร้างชุดใน 2.7+ แต่เป็นข้อผิดพลาดทางไวยากรณ์ใน2.6เวอร์ชันเก่ากว่า
ThiefMaster

1
ขอโทษ? นั่นคือตัวแปรที่มีชื่อsome_epic_setที่ชี้ไปยังdictวัตถุว่าง... ไม่ใช่ชุดว่าง set()สำหรับเซตว่างคุณจำเป็นต้องใช้
6502

2
@ 6502: แน่นอน แต่มันเป็นข้อผิดพลาดทั่วไปที่{5}สร้างชุดที่มีองค์ประกอบเดียว5และ{}เป็นคำสั่งที่ว่างเปล่า
orlp

1
ว้าวมันสับสน ถึงกระนั้นมันก็ไม่ใช่ Fractal of Bad Design ระดับที่ทำให้สับสน :-)
ศ. Falken

4
@EnderLook: ที่จริงแล้วด้วยการเปิดกล่องทั่วไปคุณสามารถใช้{*()}เพื่อทำให้ว่างsetด้วยไวยากรณ์ตามตัวอักษร ผมเรียกมันว่าลิงตาเดียว :-)
ShadowRanger

17

ตัวหนังสือ Dict อาจจะมีเล็ก ๆบิตเร็วขึ้นเป็น bytecode มันสั้น:

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

เช่นเดียวกันกับlistvs[]


8
สิ่งนี้ถือว่า BUILD_MAP และ LOAD_GLOBAL เป็นเวลาคงที่และใช้เวลาเท่ากัน ไม่น่าเป็นไปได้สูง timeit ให้การประมาณที่ดีกว่ามาก
Jamie Pate

เป็นไปได้มากกว่าที่จะCALL_FUNCTIONใช้เวลาอย่างน้อยที่สุดเท่าที่BUILD_MAP(ฟังก์ชันที่ถูกเรียกโดยพื้นฐานคือBUILD_MAP) และLOAD_GLOBALใช้เป็นเพียงค่าใช้จ่ายเพิ่มเติม
chepner


3

ในกรณีของความแตกต่างระหว่าง [] และ list () มีข้อผิดพลาดที่ฉันไม่เคยเห็นใครชี้ให้เห็น หากคุณใช้พจนานุกรมเป็นสมาชิกของรายการทั้งสองจะให้ผลลัพธ์ที่แตกต่างกันอย่างสิ้นเชิง:

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

คุณจะได้รับผลเช่นเดียวกับโดยใช้[foo_dict] วิธีการใช้เวลา iterable ที่เป็นพารามิเตอร์เท่านั้นและ iterates มากกว่านั้นเพื่อเพิ่มองค์ประกอบในรายการ ซึ่งจะทำให้เกิดข้อผิดพลาดที่คล้ายกันโดยการทำเช่นนี้จะทำให้รายการแบน list((foo_dict,))list()list(some_list)
sotrh

1

list () และ [] ทำงานต่างกัน:

>>> 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 () สร้างวัตถุใหม่ในฮีปเสมอ แต่ [] สามารถนำเซลล์หน่วยความจำกลับมาใช้ใหม่ได้ด้วยเหตุผลหลายประการ


0

มีความแตกต่างอย่างหนึ่งในพฤติกรรมระหว่าง [] และ list () ดังตัวอย่างด้านล่างนี้ เราจำเป็นต้องใช้ list () หากเราต้องการให้รายการตัวเลขส่งคืนมิฉะนั้นเราจะได้รับวัตถุแผนที่! ไม่แน่ใจว่าจะอธิบายอย่างไร

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

ที่นี่ดูเหมือนจะเป็นการอธิบายพฤติกรรมโดยใช้ตัวอย่างของฟังก์ชัน range () >>> print (range (10)) # range (0, 10) range () ทำงานเหมือนรายการ แต่ไม่ใช่รายการ เป็นวัตถุที่ส่งคืนรายการต่อเนื่องของลำดับเมื่อคุณทำซ้ำมันไม่ได้ทำให้รายการประหยัดพื้นที่ วัตถุดังกล่าวสามารถทำซ้ำได้นั่นคือเหมาะสำหรับเป็นเป้าหมายสำหรับฟังก์ชันและโครงสร้างที่คาดหวังบางสิ่งจากที่พวกเขาจะได้รับไอเท็มต่อเนื่องจนกว่าจะหมด รายการฟังก์ชัน () สร้างรายการจาก iterables: >>> list (range (5)) # [0, 1, 2, 3, 4]
sebtac

1
ผลที่ตามมาคือ [] เก็บวัตถุที่ทำซ้ำได้; list () สร้างรายการจากรายการที่ทำซ้ำได้
sebtac

0

คู่วงเล็บกล่องหมายถึงวัตถุรายการหนึ่งหรือตัวห้อยดัชนี my_List [x]

คู่ปีกกาแสดงถึงวัตถุพจนานุกรม

a_list = ['on', 'off', 1, 2]

a_dict = {เปิด: 1, ปิด: 2}


-5

ส่วนใหญ่เป็นเรื่องของการเลือกเกือบตลอดเวลา มันเป็นเรื่องของความชอบ

อย่างไรก็ตามโปรดทราบว่าหากคุณมีปุ่มตัวเลขคุณจะไม่สามารถทำได้:

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

คุณต้องทำ:

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

7
นี่ไม่ถูกต้อง ... คุณต้องทำmydict = {1:"foo", 2:"bar"}(โดยไม่มีเครื่องหมายคำพูดสำหรับคีย์)
6502

8
ไม่ใช่แค่ "ผิด" คีย์คือสตริง / int ขึ้นอยู่กับว่าคุณอ้างหรือไม่
ThiefMaster
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.