len()
ฟังก์ชั่นสำหรับ Python ในตัวมีค่าใช้จ่ายเท่าไหร่? (รายการ / tuple / สตริง / พจนานุกรม)
len()
ฟังก์ชั่นสำหรับ Python ในตัวมีค่าใช้จ่ายเท่าไหร่? (รายการ / tuple / สตริง / พจนานุกรม)
คำตอบ:
มันO (1) (เวลาคงไม่ได้ขึ้นอยู่กับความยาวจริงขององค์ประกอบ - เร็วมาก) ในทุกประเภทที่คุณได้กล่าวถึงบวกset
และอื่น ๆ array.array
เช่น
การโทร len () สำหรับชนิดข้อมูลเหล่านั้นคือ O (1) ในCPythonการใช้ภาษา Python นี่คือลิงค์ไปยังตารางที่ให้ความซับซ้อนของอัลกอริทึมของฟังก์ชันต่าง ๆ ใน CPython:
วัตถุเหล่านั้นติดตามความยาวของตัวเอง เวลาในการแยกความยาวนั้นมีขนาดเล็ก (O (1) ในรูปแบบ big-O) และส่วนใหญ่ประกอบด้วย [คำอธิบายคร่าวๆเขียนใน Python ข้อตกลงไม่ใช่คำศัพท์ C]: ค้นหา "len" ในพจนานุกรมและส่งไปยัง ฟังก์ชั่น built_in len ซึ่งจะค้นหา__len__
วิธีการของวัตถุและเรียกว่า ... ทั้งหมดที่ต้องทำคือreturn self.length
length
ปรากฏในพจนานุกรมโดยdir(list)
?
list.lenght
ตัวแปรที่แสดงนั้นถูกนำไปใช้ใน C ไม่ใช่ Python
การวัดด้านล่างแสดงหลักฐานว่า len()
เป็น O (1) สำหรับโครงสร้างข้อมูลที่ใช้บ่อย
หมายเหตุเกี่ยวกับtimeit
: เมื่อใช้-s
แฟล็กและมีการส่งสองสตริงไปtimeit
ยังสตริงแรกจะถูกดำเนินการเพียงครั้งเดียวและไม่ได้หมดเวลา
$ python -m timeit -s "l = range(10);" "len(l)"
10000000 loops, best of 3: 0.0677 usec per loop
$ python -m timeit -s "l = range(1000000);" "len(l)"
10000000 loops, best of 3: 0.0688 usec per loop
$ python -m timeit -s "t = (1,)*10;" "len(t)"
10000000 loops, best of 3: 0.0712 usec per loop
$ python -m timeit -s "t = (1,)*1000000;" "len(t)"
10000000 loops, best of 3: 0.0699 usec per loop
$ python -m timeit -s "s = '1'*10;" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop
$ python -m timeit -s "s = '1'*1000000;" "len(s)"
10000000 loops, best of 3: 0.0686 usec per loop
$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(10))};" "len(d)"
10000000 loops, best of 3: 0.0711 usec per loop
$ python -mtimeit -s"d = {i:j for i,j in enumerate(range(1000000))};" "len(d)"
10000000 loops, best of 3: 0.0727 usec per loop
$ python -mtimeit -s"import array;a=array.array('i',range(10));" "len(a)"
10000000 loops, best of 3: 0.0682 usec per loop
$ python -mtimeit -s"import array;a=array.array('i',range(1000000));" "len(a)"
10000000 loops, best of 3: 0.0753 usec per loop
$ python -mtimeit -s"s = {i for i in range(10)};" "len(s)"
10000000 loops, best of 3: 0.0754 usec per loop
$ python -mtimeit -s"s = {i for i in range(1000000)};" "len(s)"
10000000 loops, best of 3: 0.0713 usec per loop
$ python -mtimeit -s"from collections import deque;d=deque(range(10));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop
$ python -mtimeit -s"from collections import deque;d=deque(range(1000000));" "len(d)"
100000000 loops, best of 3: 0.0163 usec per loop
len()
และแก้ไขการวัดเพื่อใช้-s
ธงอย่างถูกต้อง
python -m timeit -s "l = range(10000);" "len(l); len(l); len(l)"
223 nsec ต่อหนึ่งวงpython -m timeit -s "l = range(100);" "len(l)"
66.2 nsec ต่อหนึ่งวง
len เป็น O (1) เนื่องจากใน RAM รายการจะถูกจัดเก็บเป็นตาราง (ชุดของที่อยู่ต่อเนื่อง) หากต้องการทราบว่าเมื่อใดที่ตารางหยุดคอมพิวเตอร์จำเป็นต้องมีสองสิ่ง: ความยาวและจุดเริ่มต้น นั่นคือเหตุผลที่ len () คือ O (1) คอมพิวเตอร์เก็บค่าไว้ดังนั้นมันจึงจำเป็นต้องค้นหา
ฉันคิดถึง len () ใน Python ขึ้นอยู่กับขนาดของรายการดังนั้นฉันมักจะเก็บความยาวในตัวแปรถ้าฉันใช้หลายครั้ง แต่วันนี้ในขณะที่การดีบั๊กผมสังเกตว่าแอตทริบิวต์ __len__ ในรายการวัตถุดังนั้น len () จะต้องดึงมันมาซึ่งทำให้ความซับซ้อน O (1) ดังนั้นฉันจึง googled ถ้ามีคนถามแล้วและเจอโพสต์นี้
__len__
เป็น funtion ไม่ใช่ตัวแปรที่แสดงความยาวของรายการ
list.__len__
ฟังก์ชั่นนั้นทำงานในเวลาที่แน่นอน มันทำ แต่ไม่ใช่เพียงเพราะมันเป็นฟังก์ชั่น เพราะมันใช้งานได้ดี