Tại sao danh sách python có pop () nhưng không đẩy ()


265

Có ai biết tại sao list.appendhàm của Python không được gọi là list.pushđã list.poploại bỏ và trả về phần tử cuối cùng (được lập chỉ mục ở -1) và list.appendngữ nghĩa phù hợp với cách sử dụng đó không?


21
<nitpick> Đây là một phương thức, không phải là một chức năng. </ nitpick>
Tim Pietzcker

49
Tôi nghĩ rằng đây là một câu hỏi tuyệt vời, mặc dù có lẽ nên được đặt câu: "Tại sao danh sách trăn có pop () nhưng không đẩy ()".
Uri

6
popcó thể bật các mục từ bất cứ nơi nào trong một danh sách. appendkhông thể "đẩy" thứ gì đó vào giữa danh sách.
endolith

@TimPietzcker <nitpick ^ 2> Phương thức thực sự cũng là một hàm, phương thức (hàm thành viên) là một tập hợp con của hàm :)
jave.web

Câu trả lời:


246

Bởi vì "chắp thêm" đã tồn tại từ lâu trước khi "pop" được nghĩ đến. Python 0.9.1 được hỗ trợ list.append vào đầu năm 1991. Để so sánh, đây là một phần của cuộc thảo luận về comp.lang.python về việc thêm pop vào năm 1997. Guido đã viết:

Để thực hiện một ngăn xếp, người ta sẽ cần thêm một list.pop () nguyên thủy (và không, tôi không chống lại cái này đặc biệt dựa trên bất kỳ nguyên tắc nào). list.push () có thể được thêm vào để đối xứng với list.pop () nhưng tôi không phải là một fan hâm mộ lớn của nhiều tên cho cùng một hoạt động - sớm hay muộn bạn sẽ đọc mã sử dụng mã kia, vì vậy bạn cần học cả hai, đó là tải nhận thức nhiều hơn.

Bạn cũng có thể thấy anh ấy thảo luận về ý tưởng nếu đẩy / pop / put / pull nên ở phần tử [0] hoặc sau phần tử [-1] nơi anh ấy đăng một tham chiếu đến danh sách của Icon:

Tôi nghĩ rằng tất cả những điều này là tốt nhất ngoài việc thực hiện đối tượng danh sách - nếu bạn cần một ngăn xếp hoặc một hàng đợi, với ngữ nghĩa cụ thể, hãy viết một lớp nhỏ sử dụng danh sách

Nói cách khác, đối với các ngăn xếp được triển khai trực tiếp dưới dạng danh sách Python, vốn đã hỗ trợ nhanh append () và del list [-1], điều đó có nghĩa là list.pop () hoạt động theo mặc định trên phần tử cuối cùng. Ngay cả khi các ngôn ngữ khác làm điều đó khác đi.

Ngụ ý ở đây là hầu hết mọi người cần phải thêm vào một danh sách, nhưng nhiều người ít có cơ hội coi danh sách là ngăn xếp, đó là lý do tại sao list.append xuất hiện sớm hơn rất nhiều.


16
@poige you're going to *read* code that uses the other one (...) which is more cognitive loadGhi nhớ "không có sự thúc đẩy" chỉ giới thiệu tải nhận thức khi bạn viết mã. Ghi nhớ "đẩy là một từ đồng nghĩa chính xác để chắp thêm" giới thiệu tải nhận thức bất cứ khi nào bạn đọc cái mà bạn thấy ít được sử dụng hơn. Xem stackoverflow.com/questions
43255488 /

2
Làm cho không có lý do / ý nghĩa
poige

15

Bởi vì nó bổ sung; nó không đẩy. "Nối" thêm vào cuối danh sách, "đẩy" thêm vào phía trước.

Hãy nghĩ về một hàng đợi so với một ngăn xếp.

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

Chỉnh sửa: Để sắp xếp lại câu thứ hai của tôi chính xác hơn, "Bổ sung" rất rõ ràng ngụ ý thêm một cái gì đó vào cuối danh sách, bất kể việc triển khai cơ bản. Trường hợp một yếu tố mới được thêm vào khi "đẩy" không rõ ràng. Đẩy lên một ngăn xếp là đặt một cái gì đó lên "trên cùng", nhưng nơi nó thực sự đi vào cấu trúc dữ liệu cơ bản hoàn toàn phụ thuộc vào việc thực hiện. Mặt khác, đẩy lên một hàng đợi ngụ ý thêm nó vào cuối.


4
Hướng dẫn dường như gợi ý rằng nó chỉ đơn giản là đẩy và bật ra từ cuối: "Các phương thức danh sách giúp dễ dàng sử dụng danh sách như một ngăn xếp, trong đó phần tử cuối cùng được thêm vào là phần tử đầu tiên được lấy ra (đầu cuối vào trước, ra trước Để thêm một mục vào đầu ngăn xếp, hãy sử dụng append (). Để lấy một mục từ đầu ngăn xếp, hãy sử dụng pop () mà không có chỉ mục rõ ràng. "
Uri

110
"Đẩy" không có nghĩa là thêm vào phía trước. mọi việc thực hiện một ngăn xếp đã được viết bởi một người lành mạnh "đẩy" lên trên cùng (cuối) của ngăn xếp, chứ không phải dưới cùng (bắt đầu) của ngăn xếp
Kip

4
hiệu chỉnh: mỗi * thực hiện dựa trên mảng . việc thực hiện danh sách liên kết sẽ đẩy lên đầu.
Kip

16
javascript pushthêm vào cuối.
Kobi

2
Không, có trong list.popngữ nghĩa tài khoản , list.appendđẩy các yếu tố vào danh sách, khi được xem như một ngăn xếp.
fortran

10

Bởi vì nó gắn một yếu tố vào danh sách? Đẩy thường được sử dụng khi đề cập đến ngăn xếp.


7
Một danh sách có thể là một ngăn xếp mặc dù. :-)
Jason Baker

@JasonBaker Bạn có thể triển khai ngăn xếp bằng danh sách, nhưng đó không có nghĩa là danh sách == stack. Bạn cũng có thể thực hiện một ngăn xếp bằng cách sử dụng hàng đợi, nếu bạn thực sự muốn. (Nó sẽ không hiệu quả khủng khiếp, nhưng điều đó là có thể!)
Mark E. Haase

Sự nhầm lẫn thực sự xuất phát từ thực tế là một ngăn xếp không có "bắt đầu" hoặc "kết thúc" như một danh sách, mà là "trên cùng" và "dưới cùng". Thêm vào ngăn xếp ngụ ý đặt một phần tử lên trên cùng và "đẩy" xuống. "Đẩy" ở phía trước không có ý nghĩa (ít nhất là không về mặt ngôn ngữ). Và để làm cho mọi thứ trở nên khó hiểu hơn, C ++ sử dụng "push_front" và "push_back".
JesperE

9

Bởi vì "nối" theo trực giác có nghĩa là "thêm vào cuối danh sách". Nếu nó được gọi là "đẩy", thì sẽ không rõ liệu chúng ta có thêm công cụ ở phần đuôi hay ở đầu danh sách hay không.


12
Điều này không có ý nghĩa vì có một pophoạt động. Vì pushpopthường là các hoạt động xếp chồng và đi cùng nhau, nên chúng sẽ hoạt động trên cùng một danh sách.
jamesdlin

7

Không phải là một câu trả lời chính thức bằng bất kỳ phương tiện nào (chỉ là phỏng đoán dựa trên việc sử dụng ngôn ngữ), nhưng Python cho phép bạn sử dụng các danh sách dưới dạng ngăn xếp (ví dụ, phần 5.1.1 của hướng dẫn ). Tuy nhiên, danh sách trước hết vẫn là danh sách, do đó, các thao tác phổ biến cho cả hai sử dụng thuật ngữ danh sách (nghĩa là nối thêm) thay vì điều khoản ngăn xếp (nghĩa là đẩy). Vì một hoạt động pop không phổ biến trong các danh sách (mặc dù 'removeLast' có thể đã được sử dụng), nên chúng đã xác định một pop () nhưng không phải là đẩy ().


3

Ok, ý kiến ​​cá nhân ở đây, nhưng Nối và Chuẩn bị ngụ ý các vị trí chính xác trong một bộ.

Push và Pop thực sự là những khái niệm có thể được áp dụng cho một trong hai tập hợp ... Chỉ cần bạn nhất quán ... Vì một số lý do, với tôi, Push () có vẻ như nên áp dụng cho mặt trước của một tập hợp bộ...


3
Vì bạn đã đưa nó lên, nếu các mảng có hàm .append (), thì tại sao không có hàm tương ứng.prepend ()? Tôi có thể học cách sử dụng .insert (0, val) để trả trước, nhưng sau đó tôi cảm thấy xấu hổ vì thiếu hàm .delete (pos, val) tương ứng. ref: docs.python.org/2/library/array.html
MarkHu

3

FYI, thật khó để tạo ra một danh sách có phương pháp thúc đẩy:

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

Một ngăn xếp là một kiểu dữ liệu hơi trừu tượng. Ý tưởng "đẩy" và "bật" phần lớn độc lập với cách thức thực hiện ngăn xếp. Ví dụ: về mặt lý thuyết bạn có thể triển khai một ngăn xếp như thế này (mặc dù tôi không biết tại sao bạn lại như vậy):

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

... và tôi đã không sử dụng các danh sách được liên kết để thực hiện một ngăn xếp.


1

Đẩy là một hành vi ngăn xếp được xác định ; nếu bạn đẩy A lên ngăn xếp (B, C, D) bạn sẽ nhận được (A, B, C, D).

Nếu bạn đã sử dụng nối python, tập dữ liệu kết quả sẽ trông như (B, C, D, A)

Chỉnh sửa: Wow, thánh sư.

Tôi sẽ giả định rằng nó sẽ rõ ràng từ ví dụ của tôi phần nào trong danh sách là phần trên cùng và phần nào là phần dưới cùng. Giả sử rằng hầu hết chúng ta ở đây đọc từ trái sang phải, yếu tố đầu tiên của bất kỳ danh sách nào sẽ luôn ở bên trái.


1
Điều đó không đúng, pop loại bỏ khỏi cuối danh sách, không phải từ phía trước.
fortran

4
đọc trang bạn liên kết đến đẩy được định nghĩa là đẩy lên trên cùng của ngăn xếp. kết thúc nào là "đỉnh" phụ thuộc vào việc thực hiện. trong ngăn xếp dựa trên mảng, đẩy sẽ đẩy vào cuối mảng. trong ngăn xếp dựa trên danh sách liên kết, đẩy sẽ đẩy về đầu.
Kip

0

Có lẽ vì phiên bản gốc của Python ( C Python) được viết bằng C, không phải C ++.

Ý tưởng rằng một danh sách được hình thành bằng cách đẩy mọi thứ vào mặt sau của một cái gì đó có lẽ không nổi tiếng như ý nghĩ về việc nối thêm chúng.


Phần thứ hai là một câu trả lời tốt. Nhưng điều đó có liên quan gì đến việc được triển khai trong C / C ++?
Jason Baker

@Jason: Trong STL của C ++, push_back () là cách bạn thêm vào danh sách. Tôi đã cố gắng truyền đạt ý tưởng meta rằng ý tưởng rằng các danh sách được hình thành bằng cách đẩy có lẽ sẽ xuất hiện nhiều hơn nếu bạn làm việc trong C ++. Có ý nghĩa gì không?
thư giãn

Nếu bạn có một loại danh sách được triển khai dưới dạng một mảng liền kề (một vectơ trong C ++, một danh sách trong Python, một mảng trong Perl) thì sẽ có nghĩa là "đẩy" đặt phần tử mới vào cuối. Bạn sẽ lưu ý rằng perl 4 được cho là "đẩy" và "pop" là các hàm trên các mảng giống hệt như append / pop và C ++ của Push_back / pop_back và trước khi STL chính thức được đề xuất cho C ++. Vì vậy, nó không có gì để làm với STL của C ++ tạo ra một sự hiểu biết mới về mọi thứ.
Andrew Dalke

Một trong những điều tôi nhớ khi học Python từ nền Perl là khả năng sử dụng các thao tác đẩy (), pop (), shift () và unshift () tích hợp để thêm / xóa các phần tử vào / từ hai đầu của cùng một mảng . Mặc dù tôi có thể dễ dàng bọc danh sách Python trong lớp "Stackish" hoặc lớp "Queueish", nhưng nó không dễ dàng (hoặc hiệu quả) để thực hiện cả hai cùng một lúc.
Peter

-2

Push và Pop có ý nghĩa về mặt ẩn dụ của một chồng đĩa hoặc khay trong quán ăn tự chọn hoặc tiệc buffet, cụ thể là những người trong loại chủ sở hữu có một lò xo bên dưới để tấm trên cùng là (ít nhiều ... về lý thuyết) ở cùng một nơi cho dù có bao nhiêu tấm bên dưới nó.

Nếu bạn loại bỏ một khay, trọng lượng của lò xo sẽ ​​ít hơn một chút và ngăn xếp "bật" lên một chút, nếu bạn đặt tấm trở lại, nó sẽ "đẩy" chồng xuống. Vì vậy, nếu bạn nghĩ về danh sách như một ngăn xếp và yếu tố cuối cùng là trên cùng, thì bạn không nên nhầm lẫn nhiều.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.