พิจารณาสิ่งต่อไปนี้:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
ฉันจะรับจำนวนองค์ประกอบในรายการได้items
อย่างไร
พิจารณาสิ่งต่อไปนี้:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
# FAKE METHOD:
items.amount() # Should return 3
ฉันจะรับจำนวนองค์ประกอบในรายการได้items
อย่างไร
คำตอบ:
วิธีรับขนาดของรายการ
เพื่อหาขนาดของรายการใช้ฟังก์ชัน builtin len
:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
และตอนนี้:
len(items)
ผลตอบแทน 3
ทุกอย่างใน Python เป็นวัตถุรวมถึงรายการ วัตถุทั้งหมดมีส่วนหัวของการจัดเรียงบางอย่างในการใช้งาน C
รายการและวัตถุบิวob_size
ด์อินอื่นที่คล้ายกันที่มี "ขนาด" ใน Python โดยเฉพาะมีแอททริบิวต์ที่เรียกว่าโดยที่จำนวนองค์ประกอบในวัตถุนั้นถูกแคช ดังนั้นการตรวจสอบจำนวนวัตถุในรายการจึงรวดเร็วมาก
แต่ถ้าคุณกำลังตรวจสอบถ้าขนาดของรายการเป็นศูนย์หรือไม่ไม่ได้ใช้len
- แทนใส่รายการในบริบทแบบบูล - มันถือว่าเป็นเท็จถ้าว่างที่แท้จริงมิฉะนั้น
len(s)
ส่งคืนความยาว (จำนวนรายการ) ของวัตถุ อาร์กิวเมนต์อาจเป็นลำดับ (เช่นสตริงไบต์ tuple รายการหรือช่วง) หรือคอลเล็กชัน (เช่นพจนานุกรมชุดหรือชุดที่ตรึง)
len
ถูกนำไปใช้กับ__len__
จากdocของ data data :
object.__len__(self)
เรียกว่าใช้งานฟังก์ชันใน
len()
ตัว ควรคืนความยาวของวัตถุเป็นจำนวนเต็ม> = 0 นอกจากนี้วัตถุที่ไม่ได้กำหนดเมธอด__nonzero__()
[ใน Python 2 หรือ__bool__()
ใน Python 3] และ__len__()
เมธอดส่งคืนค่าศูนย์จะถือว่าเป็นเท็จในบริบทบูลีน
และเรายังสามารถเห็นว่า__len__
เป็นวิธีการของรายการ:
items.__len__()
ผลตอบแทน 3
len
(ความยาว) ของและในความเป็นจริงเราเห็นว่าเราสามารถรับข้อมูลนี้สำหรับประเภทที่อธิบายไว้ทั้งหมด:
>>> all(hasattr(cls, '__len__') for cls in (str, bytes, tuple, list,
xrange, dict, set, frozenset))
True
len
เพื่อทดสอบรายการที่ว่างเปล่าหรือไม่มีข้อมูลเพื่อทดสอบความยาวที่เฉพาะเจาะจงแน่นอนเพียงทดสอบความเท่าเทียมกัน:
if len(items) == required_length:
...
แต่มีกรณีพิเศษสำหรับการทดสอบรายการความยาวเป็นศูนย์หรือผกผัน ในกรณีนั้นอย่าทดสอบความเท่าเทียมกัน
นอกจากนี้อย่าทำ:
if len(items):
...
เพียงทำ:
if items: # Then we have some items, not empty!
...
หรือ
if not items: # Then we have an empty list!
...
ฉันอธิบายว่าทำไมที่นี่แต่สั้น ๆif items
หรือif not items
เป็นทั้งที่สามารถอ่านได้และมีประสิทธิภาพมากกว่า
ในขณะที่สิ่งนี้อาจไม่เป็นประโยชน์เนื่องจากความจริงที่ว่ามันฟังก์ชั่น "ออกจากกล่อง" มีความหมายมากกว่าการแฮ็คที่ค่อนข้างง่ายจะสร้างคลาสที่มีlength
คุณสมบัติ:
class slist(list):
@property
def length(self):
return len(self)
คุณสามารถใช้มันได้เช่น:
>>> l = slist(range(10))
>>> l.length
10
>>> print l
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
โดยพื้นฐานแล้วมันจะเหมือนกับรายการวัตถุโดยมีประโยชน์เพิ่มเติมจากการมีlength
คุณสมบัติที่เป็นมิตรกับ OOP
เช่นเคยไมล์สะสมของคุณอาจแตกต่างกันไป
length = property(len)
และข้ามฟังก์ชัน wrapper บรรทัดเดียวและเก็บเอกสาร / วิปัสสนาของlen
คุณสมบัติของคุณ
นอกจากนี้len
คุณยังสามารถใช้operator.length_hint
(ต้องการ Python 3.4+) สำหรับปกติlist
ทั้งสองจะเทียบเท่า แต่length_hint
ทำให้สามารถรับความยาวของ list-iterator ซึ่งอาจเป็นประโยชน์ในบางสถานการณ์:
>>> 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
แต่length_hint
ตามนิยามแล้วเป็นเพียง "คำใบ้" ดังนั้นเวลาส่วนใหญ่len
จึงดีกว่า
__len__
ผมเคยเห็นหลายคำตอบบอกเข้าถึง สิ่งนี้ถูกต้องเมื่อจัดการกับคลาสที่มีอยู่ภายในlist
แต่อาจนำไปสู่ปัญหากับคลาสที่กำหนดเองเนื่องจากlen
(และlength_hint
) ใช้การตรวจสอบความปลอดภัยบางอย่าง ตัวอย่างเช่นทั้งสองไม่อนุญาตให้มีความยาวหรือความยาวเชิงลบที่เกินค่าที่แน่นอน ( sys.maxsize
ค่า) ดังนั้นจึงปลอดภัยกว่าที่จะใช้len
ฟังก์ชั่นแทน__len__
วิธีการ!
ตอบคำถามของคุณตามตัวอย่างที่ให้ไว้ก่อนหน้านี้:
items = []
items.append("apple")
items.append("orange")
items.append("banana")
print items.__len__()
__foo__
: นี่เป็นเพียงการประชุมเป็นวิธีที่ระบบ Python จะใช้ชื่อที่จะไม่ขัดแย้งกับชื่อผู้ใช้ 2. _foo
: นี่เป็นเพียงการประชุมวิธีสำหรับโปรแกรมเมอร์เพื่อระบุว่าตัวแปรเป็นแบบส่วนตัว (อะไรก็ตามที่มีความหมายใน Python) 3. __foo
: สิ่งนี้มีความหมายที่แท้จริง: ล่ามมาแทนที่ชื่อนี้ด้วย_classname__foo
เพื่อให้แน่ใจว่าชื่อจะไม่ทับซ้อนกับชื่อที่คล้ายกันในคลาสอื่น * ไม่มีรูปแบบอื่นของขีดล่างมีความหมายในโลกหลาม * ไม่มีความแตกต่างระหว่างคลาสตัวแปรโกลบอลและอื่น ๆ ในแบบแผนเหล่านี้
และเพื่อความสมบูรณ์ (การศึกษาเบื้องต้น) เป็นไปได้โดยไม่ต้องใช้len()
ฟังก์ชั่น ฉันจะไม่เอาผิดสิ่งนี้เป็นตัวเลือกที่ดีอย่าโปรแกรมเช่นนี้ใน PYTHONแต่มันมีจุดประสงค์สำหรับการเรียนรู้อัลกอริทึม
def count(list):
item_count = 0
for item in list[:]:
item_count += 1
return item_count
count([1,2,3,4,5])
(เครื่องหมายจุดคู่ในlist[:]
เป็นปริยายและเป็นตัวเลือกด้วย)
บทเรียนสำหรับโปรแกรมเมอร์ใหม่คือ: คุณไม่สามารถรับจำนวนไอเท็มในรายการโดยไม่นับในบางจุด คำถามจะกลายเป็น: เมื่อไหร่เวลาที่เหมาะสมที่จะนับพวกเขา ตัวอย่างเช่นรหัสประสิทธิภาพสูงเช่นการเชื่อมต่อการเรียกระบบสำหรับซ็อกเก็ต (เขียนเป็น C) connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
ไม่ได้คำนวณความยาวขององค์ประกอบ (ให้ความรับผิดชอบกับรหัสการโทร) ขอให้สังเกตว่าความยาวของที่อยู่จะถูกส่งไปตามเพื่อบันทึกขั้นตอนการนับความยาวก่อนหรือไม่ ตัวเลือกอื่น: การคำนวณมันอาจสมเหตุสมผลในการติดตามจำนวนรายการเมื่อคุณเพิ่มเข้าไปในวัตถุที่คุณส่ง จำไว้ว่าการใช้พื้นที่หน่วยความจำมากขึ้น ดูคำตอบ Naftuli เคย์
ตัวอย่างการติดตามความยาวเพื่อปรับปรุงประสิทธิภาพในขณะที่ใช้พื้นที่ในหน่วยความจำมากขึ้น โปรดทราบว่าฉันไม่เคยใช้ฟังก์ชั่น len () เพราะความยาวถูกติดตาม:
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[:]:
? ทำไมfor item in list:
ล่ะ นอกจากนี้ฉันจะใช้+= 1
เพื่อเพิ่ม
ในแง่ของการlen()
ใช้งานจริงนี่คือการใช้งาน C :
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
คือความยาวสูงสุดที่วัตถุสามารถมีได้ PyObject_Size()
เป็นฟังก์ชันที่คืนค่าขนาดของวัตถุ หากไม่สามารถกำหนดขนาดของวัตถุได้จะส่งคืน -1 ในกรณีดังกล่าวบล็อกรหัสนี้จะถูกดำเนินการ:
if (res < 0) {
assert(PyErr_Occurred());
return NULL;
}
และมีข้อยกเว้นเกิดขึ้น มิฉะนั้นบล็อกรหัสนี้จะถูกดำเนินการ:
return PyLong_FromSsize_t(res);
res
ซึ่งเป็นC
จำนวนเต็มถูกแปลงเป็นไพ ธ อนlong
และส่งคืน จำนวนเต็มหลามทั้งหมดจะถูกเก็บไว้longs
ตั้งแต่ Python 3