พิจารณาสิ่งต่อไปนี้:
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))
Truelenเพื่อทดสอบรายการที่ว่างเปล่าหรือไม่มีข้อมูลเพื่อทดสอบความยาวที่เฉพาะเจาะจงแน่นอนเพียงทดสอบความเท่าเทียมกัน:
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) # 2for 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