ทำไมรายการไพ ธ อนจึงมีป๊อป () แต่ไม่ดัน ()


265

ไม่มีใครรู้ว่าทำไมlist.appendฟังก์ชั่นของไพ ธ อนไม่ได้ถูกเรียกlist.pushว่ามีฟังก์ชั่นlist.popที่ลบและส่งคืนองค์ประกอบสุดท้าย (ดัชนีที่ -1) และlist.appendความหมายสอดคล้องกับการใช้งานนั้นหรือไม่


21
<nitpick> เป็นวิธีการไม่ใช่ฟังก์ชัน </nitpick>
Tim Pietzcker

49
ฉันคิดว่านี่เป็นคำถามที่ยอดเยี่ยมถึงแม้ว่ามันควรจะเป็นประโยค: "ทำไมรายการไพ ธ อนจึงมีป๊อป () แต่ไม่ดัน ()"
Uri

6
popสามารถดึงรายการออกจากที่ใดก็ได้ในรายการ appendไม่สามารถ "ผลัก" บางสิ่งบางอย่างลงในรายการกลาง
endolith

@TimPietzcker <nitpick ^ 2> วิธีการเป็นจริงยังฟังก์ชั่นวิธีการ (ฟังก์ชั่นสมาชิก) เป็นส่วนย่อยของฟังก์ชั่น :)
jave.web

คำตอบ:


246

เนื่องจาก "ผนวก" มีอยู่ก่อนที่จะมีการคิด "ป๊อป" Python 0.9.1รองรับ list.append ในต้นปี 1991 โดยการเปรียบเทียบนี่เป็นส่วนหนึ่งของการอภิปรายเกี่ยวกับcomp.lang.pythonเกี่ยวกับการเพิ่ม pop ในปี 1997 Guido เขียนว่า:

ในการติดตั้งสแต็กหนึ่งจะต้องเพิ่ม list.pop () ดั้งเดิม (และไม่ฉันไม่ได้ต่อต้านอันนี้โดยเฉพาะบนหลักการของหลักการใด ๆ ) list.push () สามารถเพิ่มสมมาตรกับ list.pop () แต่ฉันไม่ใช่แฟนตัวยงของชื่อหลายชื่อสำหรับการดำเนินการเดียวกัน - ไม่ช้าก็เร็วคุณจะต้องอ่านโค้ดที่ใช้อีกตัวหนึ่งดังนั้น คุณต้องเรียนรู้ทั้งสองอย่างซึ่งเป็นภาระทางปัญญามากขึ้น

คุณยังสามารถดูว่าเขาพูดถึงแนวคิดว่าหากการผลัก / ป๊อป / ใส่ / ดึงควรอยู่ที่องค์ประกอบ [0] หรือหลังจากองค์ประกอบ [-1] ซึ่งเขาโพสต์การอ้างอิงไปยังรายการไอคอน:

ฉันคิดว่าทั้งหมดนี้ดีที่สุดในการนำลิสต์วัตถุไปใช้ถ้าคุณต้องการสแต็กหรือคิวที่มีความหมายเฉพาะเขียนคลาสเล็ก ๆ ที่ใช้ลิสต์

กล่าวอีกนัยหนึ่งสำหรับสแต็กที่นำไปใช้โดยตรงในรายการ Python ซึ่งรองรับการผนวกอย่างรวดเร็ว () และ del list [-1] อยู่แล้วมันสมเหตุสมผลที่ list.pop () จะทำงานตามค่าเริ่มต้นในองค์ประกอบสุดท้าย แม้ว่าภาษาอื่น ๆ จะทำมันแตกต่างกัน

โดยนัยที่นี่คือคนส่วนใหญ่จำเป็นต้องผนวกเข้ากับรายการ แต่มีโอกาสน้อยที่จะถือว่ารายการเป็นแบบกองซ้อนซึ่งเป็นสาเหตุที่ list.append เข้ามาก่อนหน้านี้มาก


16
@poige การyou're going to *read* code that uses the other one (...) which is more cognitive loadจดจำว่า "ไม่มีการพุช" แนะนำการโหลดทางปัญญาเมื่อคุณเขียนโค้ดเท่านั้น การจำ "การพุชเป็นคำพ้องความหมายที่แท้จริงสำหรับการต่อท้าย" จะแนะนำการโหลดทางปัญญาเมื่อใดก็ตามที่คุณอ่านอันที่คุณเห็นว่าใช้บ่อย ดูstackoverflow.com/questions/3455488/…สำหรับข้อมูลเพิ่มเติมเกี่ยวกับสาเหตุที่คนคิดว่าการอ่านมักจะสำคัญกว่าความสามารถในการเขียน
stevenjackson121

2
ทำให้ไม่มีข้อแก้ตัว / ความรู้สึก
poige

15

เพราะมันผนวก; มันไม่ได้ผลัก "การผนวก" เพิ่มลงในส่วนท้ายของรายการ "การเพิ่ม" จะเพิ่มไว้ด้านหน้า

คิดว่าคิวกับสแต็ค

http://docs.python.org/tutorial/datastructures.html

แก้ไข:เพื่อให้ประโยคที่สองของฉันชัดเจนยิ่งขึ้น "การผนวก" อย่างชัดเจนหมายถึงการเพิ่มบางอย่างลงในส่วนท้ายของรายการโดยไม่คำนึงถึงการใช้งานพื้นฐาน ตำแหน่งที่จะเพิ่มองค์ประกอบใหม่เมื่อ "push" เป็นสิ่งที่ชัดเจนน้อยกว่า การใส่สแต็กลงไปนั้นเป็นการวางบางสิ่งที่ "บนสุด" แต่ที่จริงแล้วมันไปอยู่ในโครงสร้างข้อมูลพื้นฐานทั้งหมดขึ้นอยู่กับการนำไปใช้งาน ในทางกลับกันการกดไปที่คิวหมายถึงการเพิ่มไปยังส่วนท้าย


4
กวดวิชาดูเหมือนว่าจะแนะนำว่ามันเพียงแค่ผลักดันและผุดจากท้าย: "วิธีการรายการทำให้มันง่ายมากที่จะใช้รายการเป็นสแต็กที่องค์ประกอบสุดท้ายที่เพิ่มเป็นองค์ประกอบแรกที่ดึงมา (" สุดท้ายเข้าก่อนออกก่อน " ”). ในการเพิ่มไอเท็มที่ด้านบนสุดของสแต็กให้ใช้ผนวก () เพื่อดึงไอเท็มจากด้านบนสุดของสแต็กให้ใช้ pop () โดยไม่มีดัชนีที่ชัดเจน "
Uri

110
"ผลัก" ไม่ว่าจะเป็นการเพิ่มด้านหน้า ทุกการดำเนินงานของสแต็คที่เคยได้รับการเขียนโดยคนมีสติ "ดัน" เข้าสู่ด้านบน (สิ้นสุด) ของสแต็คที่ไม่ได้ด้านล่าง (เริ่มต้น) ของสแต็ค
กีบ

4
การแก้ไข: ทุกการใช้งาน * ตามอาเรย์ การใช้งานลิสต์ของลิสต์จะผลักไปที่ส่วนหัว
กีบ

16
จาวาสคริปต์pushเพิ่มไปยังจุดสิ้นสุด
Kobi

2
ไม่ต้องคำนึงถึงlist.popความหมายของบัญชีlist.appendดันองค์ประกอบลงในรายการเมื่อดูเป็นสแต็ก
fortran

10

เพราะมันจะผนวกองค์ประกอบเข้ากับรายการหรือไม่ มักจะใช้ดันเมื่อพูดถึงกอง


7
รายการสามารถเป็นสแต็กได้ :-)
Jason Baker

@JasonBaker คุณสามารถใช้กองซ้อนโดยใช้รายการ แต่นั่นไม่ได้หมายความว่ารายการ == กองซ้อน คุณสามารถใช้กองซ้อนโดยใช้คิวหากคุณต้องการจริงๆ (มันจะไม่มีประสิทธิภาพอย่างน่ากลัว แต่เป็นไปได้!)
Mark E. Haase

ความสับสนนั้นมาจากความจริงที่ว่าสแต็คไม่มี "เริ่มต้น" หรือ "สิ้นสุด" เหมือนรายการ แต่เป็น "อันดับสูงสุด" และ "ล่าง" การเพิ่มสแต็คหมายถึงการวางองค์ประกอบไว้ด้านบนและ "ดัน" ลง "การผลัก" ที่ด้านหน้าทำให้ไม่มีเหตุผล (อย่างน้อยก็ไม่ใช้ภาษา) และเพื่อสร้างความสับสนให้มากขึ้น C ++ ใช้ "push_front" และ "push_back"
JesperE

9

เพราะ "ผนวก" หมายถึง "เพิ่มในตอนท้ายของรายการ" โดยสังหรณ์ใจ ถ้ามันถูกเรียกว่า "push" มันจะไม่ชัดเจนว่าเรากำลังเพิ่มเนื้อหาที่ส่วนท้ายหรือส่วนหัวของรายการ


12
สิ่งนี้ไม่สมเหตุสมผลเนื่องจากมีการpopผ่าตัด ตั้งแต่pushและpopโดยทั่วไปแล้วจะมีการดำเนินการสแต็กและไปด้วยกันก็ควรจะคาดหวังว่าพวกเขาจะทำงานในปลายเดียวกันของรายการ
jamesdlin

7

ไม่ใช่คำตอบอย่างเป็นทางการไม่ว่าจะด้วยวิธีการใด (เพียงเดาตามการใช้ภาษา) แต่ Python อนุญาตให้คุณใช้รายการเป็นสแต็ค (เช่นหัวข้อ 5.1.1 ของบทช่วยสอน ) อย่างไรก็ตามรายการยังคงเป็นรายการแรกของรายการทั้งหมดดังนั้นการดำเนินการที่ใช้ร่วมกันกับข้อกำหนดรายการใช้งาน (เช่นผนวก) แทนที่จะใช้คำซ้อน (เช่นกด) เนื่องจากการทำงานของป๊อปไม่ใช่สิ่งที่พบได้ทั่วไปในรายการ (แม้ว่าจะสามารถใช้ 'removeLast' ได้) แต่ก็เป็นการกำหนดป๊อป () แต่ไม่ใช่การกด ()


3

ตกลงความเห็นส่วนตัวที่นี่ แต่ผนวกและผนวกท้ายแสดงถึงตำแหน่งที่แม่นยำในชุด

พุชและป๊อปเป็นแนวคิดที่สามารถนำไปใช้กับปลายทั้งสองของชุด ... ตราบใดที่คุณสอดคล้องกัน ... ด้วยเหตุผลบางอย่างสำหรับฉัน Push () ดูเหมือนว่าควรนำไปใช้กับด้านหน้าของ ตั้ง ...


3
เนื่องจากคุณนำมาใช้หากอาร์เรย์มีฟังก์ชั่น. ผนวก () ดังนั้นทำไมไม่มีฟังก์ชั่นที่สอดคล้องกัน. prepend () ฉันสามารถเรียนรู้ที่จะใช้. insert (0, val) เพื่อเติมเงิน แต่ฉันก็อายโดยไม่มีฟังก์ชัน. delete (pos, val) ที่สอดคล้องกัน ref: docs.python.org/2/library/array.html
MarkHu

3

FYI ไม่ใช่เรื่องยากมากที่จะสร้างรายการที่มีวิธีการพุช:

>>> class StackList(list):
...     def push(self, item):
...             self.append(item)
... 
>>> x = StackList([1,2,3])
>>> x
[1, 2, 3]
>>> x.push(4)
>>> x
[1, 2, 3, 4]

สแต็กเป็นประเภทข้อมูลที่ค่อนข้างเป็นนามธรรม แนวคิดของ "pushing" และ "popping" ส่วนใหญ่ไม่ขึ้นอยู่กับการใช้งานสแต็กจริง ๆ ตัวอย่างเช่นในทางทฤษฎีคุณสามารถสร้างสแต็กแบบนี้ได้ (แม้ว่าฉันจะไม่รู้ว่าทำไมคุณถึงชอบ):

l = [1,2,3]
l.insert(0, 1)
l.pop(0)

... และฉันไม่ได้ใช้รายการที่เชื่อมโยงเพื่อสร้างสแต็ก


1

พุชเป็นพฤติกรรมสแต็กที่กำหนดไว้ ถ้าคุณผลัก A ไปที่สแต็ก (B, C, D) คุณจะได้รับ (A, B, C, D)

ถ้าคุณใช้ python ต่อท้ายชุดข้อมูลที่ได้จะเป็นดังนี้ (B, C, D, A)

แก้ไข: ว้าว pedantry ศักดิ์สิทธิ์

ฉันจะสมมติว่ามันจะชัดเจนจากตัวอย่างของฉันซึ่งเป็นส่วนหนึ่งของรายการด้านบนและส่วนที่เป็นด้านล่าง สมมติว่าพวกเราที่นี่ส่วนใหญ่อ่านจากซ้ายไปขวาองค์ประกอบแรกของรายการใด ๆ จะอยู่ทางซ้ายเสมอ


1
ไม่เป็นความจริงป๊อปจะนำออกจากส่วนท้ายของรายการไม่ใช่จากด้านหน้า
fortran

4
อ่านหน้าที่คุณเชื่อมโยงไปถึง push หมายถึงผลักไปที่ด้านบนสุดของสแต็ก จุดสิ้นสุดคือ "ด้านบน" ขึ้นอยู่กับการใช้งาน ในการเรียงตามอาเรย์กดจะดันไปยังจุดสิ้นสุดของอาร์เรย์ ใน stack-list-based-based push จะผลักไปที่จุดเริ่มต้น
กีบ

0

อาจเป็นเพราะ Python เวอร์ชันดั้งเดิม ( C Python) เขียนด้วยภาษา C ไม่ใช่ C ++

ความคิดที่ว่ารายการนั้นเกิดจากการผลักสิ่งต่าง ๆ ลงไปด้านหลังของบางสิ่งบางอย่างอาจไม่เป็นที่รู้จักกันดีว่าเป็นความคิดที่จะผนวกมันเข้าด้วยกัน


ส่วนที่สองเป็นคำตอบที่ดี แต่สิ่งที่เกี่ยวข้องกับการนำไปใช้ใน C / C ++?
เจสันเบเกอร์

@Jason: ใน STL ของ C ++ push_back () เป็นวิธีที่คุณผนวกเข้ากับรายการ ฉันพยายามที่จะถ่ายทอดความคิดเมตาว่าความคิดที่ว่ารายการที่เกิดขึ้นจากการผลักอาจมีแนวโน้มที่จะปรากฏขึ้นหากคุณทำงานใน C ++ ทำให้รู้สึกอะไร?
ผ่อนคลาย

หากคุณมีชนิดรายการที่นำไปใช้เป็นอาร์เรย์ที่ต่อเนื่องกัน (เวกเตอร์ใน C ++, รายการใน Python, อาร์เรย์ใน Perl) ดังนั้นคุณควรมี "push" วางองค์ประกอบใหม่ที่ส่วนท้าย คุณจะได้โปรดทราบว่า perl 4 ควรเป็น "push" และ "pop" เป็นฟังก์ชันในอาร์เรย์เหมือนกับส่วนต่อท้าย / ป๊อปของ Python และ push_back / pop_back ของ C ++ และก่อนที่ STL จะถูกเสนออย่างเป็นทางการกับ C ++ ดังนั้นจึงไม่มีอะไรเกี่ยวข้องกับ STL ของ C ++ เพื่อสร้างความเข้าใจใหม่ในสิ่งต่าง ๆ
Andrew Dalke

หนึ่งในสิ่งที่ฉันพลาดในการเรียนรู้ Python จากพื้นหลัง Perl คือความสามารถในการใช้การดำเนินการ push (), pop (), shift () และ unshift () เพื่อเพิ่ม / ลบองค์ประกอบไปยัง / จากจุดสิ้นสุดเดียวกัน อาเรย์ แม้ว่าฉันสามารถห่อรายการ Python ในคลาส "Stackish" หรือคลาส "Queueish" ได้อย่างง่ายดาย แต่ก็ไม่ได้ดูง่าย (หรือมีประสิทธิภาพ) ในการทำทั้งสองอย่างพร้อมกัน
Peter

-2

ดันและป๊อปทำให้รู้สึกในแง่ของคำอุปมาของกองซ้อนของแผ่นหรือถาดในโรงอาหารหรือบุฟเฟ่ต์โดยเฉพาะอย่างยิ่งในประเภทของผู้ถือที่มีสปริงภายใต้ดังนั้นแผ่นด้านบนเป็น (มากหรือน้อย ... ในทางทฤษฎี) ในที่เดียวกันไม่ว่าจะมีแผ่นใต้แผ่นกี่แผ่น

หากคุณนำถาดออกน้ำหนักของสปริงจะน้อยกว่าเล็กน้อยและสแต็กจะ "ปรากฏ" ขึ้นเล็กน้อยหากคุณใส่แผ่นกลับเข้าไปมันจะ "ดัน" ถาดลงมา ดังนั้นหากคุณคิดว่ารายการเป็นสแต็กและองค์ประกอบสุดท้ายว่าอยู่ด้านบนสุดคุณก็ไม่ควรสับสนมาก

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