Hướng dẫn what is self head in python? - tự đứng đầu trong python là gì?

18.1. Tài liệu tham khảo được nhúng

Chúng tôi đã thấy các ví dụ về các thuộc tính đề cập đến các đối tượng khác, mà chúng tôi gọi là các tài liệu tham khảo nhúng. Một cấu trúc dữ liệu phổ biến, danh sách được liên kết, tận dụng tính năng này.embedded references. A common data structure, the linked list, takes advantage of this feature.

Các danh sách được liên kết được tạo thành từ các nút, trong đó mỗi nút chứa một tham chiếu đến nút tiếp theo trong danh sách. Ngoài ra, mỗi nút chứa một đơn vị dữ liệu được gọi là hàng hóa.nodes, where each node contains a reference to the next node in the list. In addition, each node contains a unit of data called the cargo.

Một danh sách được liên kết được coi là một cấu trúc dữ liệu đệ quy vì nó có một định nghĩa đệ quy.recursive data structure because it has a recursive definition.

Một danh sách được liên kết là:

  1. danh sách trống, được đại diện bởi không có, hoặcNone, or
  2. Một nút chứa một đối tượng hàng hóa và tham chiếu đến một danh sách được liên kết.

Cấu trúc dữ liệu đệ quy cho vay theo các phương pháp đệ quy.

18.2. Lớp nútNode class¶

Như thường lệ khi viết một lớp mới, chúng tôi sẽ bắt đầu với các phương thức khởi tạo và __str__ để chúng tôi có thể kiểm tra cơ chế cơ bản của việc tạo và hiển thị loại mới:__str__ methods so that we can test the basic mechanism of creating and displaying the new type:

class Node:
    def __init__(self, cargo=None, next=None):
        self.cargo = cargo
        self.next  = next

    def __str__(self):
        return str(self.cargo)

Như thường lệ, các tham số cho phương thức khởi tạo là tùy chọn. Theo mặc định, cả hàng hóa và liên kết, tiếp theo, được đặt thành không có.next, are set to None.

Biểu diễn chuỗi của một nút chỉ là biểu diễn chuỗi của hàng hóa. Vì bất kỳ giá trị nào cũng có thể được chuyển đến hàm STR, chúng tôi có thể lưu trữ bất kỳ giá trị nào trong danh sách.str function, we can store any value in a list.

Để kiểm tra việc triển khai cho đến nay, chúng tôi có thể tạo một nút và in nó:Node and print it:

>>> node = Node("test")
>>> print node
test

Để làm cho nó thú vị, chúng tôi cần một danh sách với nhiều hơn một nút:

>>> node1 = Node(1)
>>> node2 = Node(2)
>>> node3 = Node(3)

Mã này tạo ra ba nút, nhưng chúng tôi không có danh sách vì các nút không được liên kết. Sơ đồ trạng thái trông như thế này:linked. The state diagram looks like this:

Để liên kết các nút, chúng ta phải tạo nút thứ nhất tham khảo nút thứ hai và nút thứ hai tham khảo thứ ba:

>>> node1.next = node2
>>> node2.next = node3

Tham chiếu của nút thứ ba là không có, điều này chỉ ra rằng đó là kết thúc của danh sách. Bây giờ sơ đồ trạng thái trông như thế này:None, which indicates that it is the end of the list. Now the state diagram looks like this:

Bây giờ bạn đã biết cách tạo các nút và liên kết chúng vào danh sách. Điều có thể ít rõ ràng hơn vào thời điểm này là tại sao.

18.3. Danh sách là Bộ sưu tập

Danh sách này rất hữu ích vì chúng cung cấp một cách để lắp ráp nhiều đối tượng vào một thực thể duy nhất, đôi khi được gọi là một bộ sưu tập. Trong ví dụ, nút đầu tiên của danh sách đóng vai trò là tham chiếu đến toàn bộ danh sách.collection. In the example, the first node of the list serves as a reference to the entire list.

Để truyền danh sách dưới dạng tham số, chúng tôi chỉ phải chuyển tham chiếu đến nút đầu tiên. Ví dụ: hàm print_list lấy một nút duy nhất làm đối số. Bắt đầu với đầu của danh sách, nó in từng nút cho đến khi kết thúc:print_list takes a single node as an argument. Starting with the head of the list, it prints each node until it gets to the end:

def print_list(node):
    while node:
        print node,
        node = node.next
    print

Để gọi phương thức này, chúng tôi chuyển tham chiếu đến nút đầu tiên:

>>> print_list(node1)
1 2 3

Bên trong print_list Chúng tôi có một tham chiếu đến nút đầu tiên của danh sách, nhưng không có biến nào đề cập đến các nút khác. Chúng ta phải sử dụng giá trị tiếp theo từ mỗi nút để đến nút tiếp theo.print_list we have a reference to the first node of the list, but there is no variable that refers to the other nodes. We have to use the next value from each node to get to the next node.

Để đi qua một danh sách được liên kết, người ta thường sử dụng một biến vòng như nút để chỉ từng nút liên tiếp.node to refer to each of the nodes in succession.

Sơ đồ này hiển thị giá trị của danh sách và các giá trị mà nút thực hiện:list and the values that node takes on:

18.4. Danh sách và đệ quy

Đó là điều tự nhiên để thể hiện nhiều hoạt động danh sách bằng các phương pháp đệ quy. Ví dụ: sau đây là thuật toán đệ quy để in danh sách ngược:

  1. Tách danh sách thành hai phần: nút đầu tiên (được gọi là đầu); và phần còn lại (được gọi là đuôi).
  2. In đuôi về phía sau.
  3. In đầu.

Tất nhiên, bước 2, cuộc gọi đệ quy, giả định rằng chúng ta có cách in danh sách lạc hậu. Nhưng nếu chúng ta cho rằng cuộc gọi đệ quy hoạt động - bước nhảy vọt của đức tin - thì chúng ta có thể thuyết phục bản thân rằng thuật toán này hoạt động.

Tất cả những gì chúng ta cần là một trường hợp cơ sở và một cách chứng minh rằng đối với bất kỳ danh sách nào, cuối cùng chúng ta sẽ đến trường hợp cơ sở. Với định nghĩa đệ quy của một danh sách, một trường hợp cơ sở tự nhiên là danh sách trống, được biểu thị bằng không có:None:

def print_backward(list):
    if list == None: return
    head = list
    tail = list.next
    print_backward(tail)
    print head,

Dòng đầu tiên xử lý trường hợp cơ sở bằng cách không làm gì cả. Hai dòng tiếp theo chia danh sách thành đầu và đuôi. Hai dòng cuối cùng in danh sách. Dấu phẩy ở cuối dòng cuối cùng khiến Python không in một dòng mới sau mỗi nút.head and tail. The last two lines print the list. The comma at the end of the last line keeps Python from printing a newline after each node.

Chúng tôi gọi phương thức này khi chúng tôi gọi print_list:print_list:

>>> print_backward(node1)
3 2 1

Kết quả là một danh sách lạc hậu.

Bạn có thể tự hỏi tại sao print_list và print_backward là các hàm và không phải là phương thức trong lớp nút. Lý do là chúng tôi muốn sử dụng không có gì để đại diện cho danh sách trống và việc gọi một phương thức không hợp pháp là không hợp pháp. Giới hạn này làm cho việc viết danh sách-thao tác mã theo kiểu hướng đối tượng sạch sẽ.print_list and print_backward are functions and not methods in the Node class. The reason is that we want to use None to represent the empty list and it is not legal to invoke a method on None. This limitation makes it awkward to write list – manipulating code in a clean object-oriented style.

Chúng ta có thể chứng minh rằng print_backward sẽ luôn chấm dứt không? Nói cách khác, nó sẽ luôn luôn đạt đến trường hợp cơ sở? Trong thực tế, câu trả lời là không. Một số danh sách sẽ làm cho phương pháp này sụp đổ.print_backward will always terminate? In other words, will it always reach the base case? In fact, the answer is no. Some lists will make this method crash.

18,5. Danh sách vô hạn

Không có gì để ngăn một nút nhắc lại vào một nút trước đó trong danh sách, bao gồm cả chính nó. Ví dụ, hình này hiển thị một danh sách với hai nút, một trong số đó đề cập đến chính nó:

Nếu chúng ta gọi print_list trong danh sách này, nó sẽ lặp lại mãi mãi. Nếu chúng ta gọi print_backward, nó sẽ tái phát vô hạn. Loại hành vi này làm cho danh sách vô hạn khó làm việc.print_list on this list, it will loop forever. If we invoke print_backward, it will recurse infinitely. This sort of behavior makes infinite lists difficult to work with.

Tuy nhiên, đôi khi chúng hữu ích. Ví dụ: chúng tôi có thể đại diện cho một số dưới dạng danh sách các chữ số và sử dụng danh sách vô hạn để thể hiện một phần lặp lại.

Bất kể, có vấn đề là chúng ta không thể chứng minh rằng in_list và print_backward chấm dứt. Điều tốt nhất chúng ta có thể làm là tuyên bố giả thuyết, nếu danh sách không có vòng lặp, thì các phương pháp này sẽ chấm dứt. Loại yêu cầu này được gọi là điều kiện tiên quyết. Nó áp đặt một ràng buộc đối với một trong các tham số và mô tả hành vi của phương thức nếu ràng buộc được thỏa mãn. Bạn sẽ sớm thấy nhiều ví dụ hơn.print_list and print_backward terminate. The best we can do is the hypothetical statement, If the list contains no loops, then these methods will terminate. This sort of claim is called a precondition. It imposes a constraint on one of the parameters and describes the behavior of the method if the constraint is satisfied. You will see more examples soon.

18.6. Định lý mơ hồ cơ bản

Một phần của print_backward có thể đã nhướng mày:print_backward might have raised an eyebrow:

head = list
tail = list.next

Sau khi gán đầu tiên, đầu và danh sách có cùng loại và cùng một giá trị. Vậy tại sao chúng ta lại tạo ra một biến mới?head and list have the same type and the same value. So why did we create a new variable?

Lý do là hai biến đóng vai trò khác nhau. Chúng tôi nghĩ về Head như một tham chiếu đến một nút duy nhất và chúng tôi nghĩ về danh sách như một tham chiếu đến nút đầu tiên của danh sách. Những vai trò này không phải là một phần của chương trình; Họ đang ở trong tâm trí của các lập trình viên.head as a reference to a single node, and we think of list as a reference to the first node of a list. These roles are not part of the program; they are in the mind of the programmer.

Nói chung, chúng ta có thể nói bằng cách xem xét một chương trình vai trò của một biến. Sự mơ hồ này có thể hữu ích, nhưng nó cũng có thể làm cho các chương trình khó đọc. Chúng tôi thường sử dụng các tên biến như nút và danh sách để ghi lại cách chúng tôi dự định sử dụng một biến và đôi khi tạo các biến bổ sung để phân loại.node and list to document how we intend to use a variable and sometimes create additional variables to disambiguate.

Chúng ta có thể đã viết print_backward mà không có đầu và đuôi, điều này làm cho nó ngắn gọn hơn nhưng có thể ít rõ ràng hơn:print_backward without head and tail, which makes it more concise but possibly less clear:

def print_backward(list) :
    if list == None : return
    print_backward(list.next)
    print list,

Nhìn vào hai cuộc gọi chức năng, chúng ta phải nhớ rằng print_backward coi đối số của nó là một bộ sưu tập và in coi đối số của nó là một đối tượng duy nhất.print_backward treats its argument as a collection and print treats its argument as a single object.

Định lý mơ hồ cơ bản mô tả sự mơ hồ vốn có trong một tham chiếu đến một nút: một biến đề cập đến một nút có thể coi nút là một đối tượng hoặc là đầu tiên trong danh sách các nút.fundamental ambiguity theorem describes the ambiguity that is inherent in a reference to a node: A variable that refers to a node might treat the node as a single object or as the first in a list of nodes.

18.7. Sửa đổi danh sách

Có hai cách để sửa đổi một danh sách được liên kết. Rõ ràng, chúng ta có thể thay đổi hàng hóa của một trong các nút, nhưng các hoạt động thú vị hơn là các hoạt động thêm, xóa hoặc sắp xếp lại các nút.

Ví dụ, hãy để Viết một phương thức xóa nút thứ hai trong danh sách và trả về một tham chiếu đến nút bị xóa:

>>> node = Node("test")
>>> print node
test
0

Một lần nữa, chúng tôi đang sử dụng các biến tạm thời để làm cho mã dễ đọc hơn. Đây là cách sử dụng phương pháp này:

>>> node = Node("test")
>>> print node
test
1

Biểu đồ trạng thái này cho thấy hiệu quả của hoạt động:

Điều gì xảy ra nếu bạn gọi phương pháp này và vượt qua danh sách chỉ có một yếu tố (một singleton)? Điều gì xảy ra nếu bạn vượt qua danh sách trống như một đối số? Có một điều kiện tiên quyết cho phương pháp này? Nếu vậy, hãy sửa chữa phương pháp để xử lý vi phạm điều kiện tiên quyết một cách hợp lý.singleton)? What happens if you pass the empty list as an argument? Is there a precondition for this method? If so, fix the method to handle a violation of the precondition in a reasonable way.

18.8. Người bao bọc và người trợ giúp

Nó thường hữu ích để chia một hoạt động danh sách thành hai phương thức. Ví dụ: để in một danh sách ngược trong định dạng danh sách thông thường [3,2,1], chúng ta có thể sử dụng phương thức print_backward để in 3,2, nhưng chúng ta cần một phương thức riêng để in dấu ngoặc và nút đầu tiên. Hãy gọi nó là print_backward_nicely:[3, 2, 1] we can use the print_backward method to print 3, 2, but we need a separate method to print the brackets and the first node. Let’s call it print_backward_nicely:

>>> node = Node("test")
>>> print node
test
2

Một lần nữa, bạn nên kiểm tra các phương pháp như thế này để xem liệu chúng có làm việc với các trường hợp đặc biệt như danh sách trống hoặc singleton không.

Khi chúng tôi sử dụng phương pháp này ở nơi khác trong chương trình, chúng tôi sẽ gọi trực tiếp print_backward_nicely và nó sẽ thay mặt chúng tôi gọi print_backward. Theo nghĩa đó, print_backward_nicely hoạt động như một trình bao bọc và nó sử dụng print_backward làm người trợ giúp.print_backward_nicely directly, and it invokes print_backward on our behalf. In that sense, print_backward_nicely acts as a wrapper, and it uses print_backward as a helper.

18.9. Lớp LinkedListLinkedList class¶

Có một số vấn đề tinh tế với cách chúng tôi đã thực hiện danh sách. Trong một sự đảo ngược của nguyên nhân và kết quả, chúng tôi sẽ đề xuất một triển khai thay thế trước và sau đó giải thích những vấn đề mà nó giải quyết.

Đầu tiên, chúng tôi sẽ tạo một lớp mới có tên LinkedList. Các thuộc tính của nó là một số nguyên chứa độ dài của danh sách và tham chiếu đến nút đầu tiên. Các đối tượng LinkedList đóng vai trò là tay cầm để thao tác danh sách các đối tượng nút:LinkedList. Its attributes are an integer that contains the length of the list and a reference to the first node. LinkedList objects serve as handles for manipulating lists of Node objects:

>>> node = Node("test")
>>> print node
test
3

Một điều tốt đẹp về lớp LinkedList là nó cung cấp một nơi tự nhiên để đặt các chức năng trình bao bọc như print_backward_nicely, mà chúng ta có thể tạo ra một phương thức của lớp LinkedList:LinkedList class is that it provides a natural place to put wrapper functions like print_backward_nicely, which we can make a method of the LinkedList class:

>>> node = Node("test")
>>> print node
test
4

Chỉ để làm cho mọi thứ trở nên khó hiểu, chúng tôi đổi tên print_backward_nicely. Bây giờ có hai phương thức có tên print_backward: một trong lớp nút (người trợ giúp); và một trong lớp LinkedList (trình bao bọc). Khi trình bao bọc gọi self.head.print_backward, nó sẽ gọi người trợ giúp, vì self.head là một đối tượng nút.print_backward_nicely. Now there are two methods named print_backward: one in the Node class (the helper); and one in the LinkedList class (the wrapper). When the wrapper invokes self.head.print_backward, it is invoking the helper, because self.head is a Node object.

Một lợi ích khác của lớp LinkedList là nó giúp thêm hoặc xóa phần tử đầu tiên của danh sách. Ví dụ, AddFirst là một phương pháp cho danh sách liên kết; Nó lấy một mục hàng hóa làm đối số và đặt nó ở đầu danh sách:LinkedList class is that it makes it easier to add or remove the first element of a list. For example, addFirst is a method for LinkedLists; it takes an item of cargo as an argument and puts it at the beginning of the list:

>>> node = Node("test")
>>> print node
test
5

Như thường lệ, bạn nên kiểm tra mã như thế này để xem nó có xử lý các trường hợp đặc biệt không. Ví dụ, điều gì xảy ra nếu danh sách ban đầu trống?

18.10. Bất biến trong

Một số danh sách được hình thành tốt; Những người khác thì không. Ví dụ: nếu một danh sách chứa một vòng lặp, nó sẽ khiến nhiều phương pháp của chúng tôi bị sập, vì vậy chúng tôi có thể muốn yêu cầu danh sách đó không có vòng lặp. Một yêu cầu khác là giá trị độ dài trong đối tượng LinkedList phải bằng với số lượng nút thực tế trong danh sách.length value in the LinkedList object should be equal to the actual number of nodes in the list.

Các yêu cầu như thế này được gọi là bất biến bởi vì, lý tưởng nhất, chúng nên đúng với mọi đối tượng mọi lúc. Chỉ định bất biến cho các đối tượng là một thực tiễn lập trình hữu ích vì nó giúp dễ dàng chứng minh tính chính xác của mã, kiểm tra tính toàn vẹn của cấu trúc dữ liệu và phát hiện lỗi.invariants because, ideally, they should be true of every object all the time. Specifying invariants for objects is a useful programming practice because it makes it easier to prove the correctness of code, check the integrity of data structures, and detect errors.

Một điều đôi khi khó hiểu về bất biến là có những lúc chúng bị vi phạm. Ví dụ, ở giữa AddFirst, sau khi chúng tôi đã thêm nút nhưng trước khi chúng tôi có độ dài tăng lên, bất biến đã bị vi phạm. Loại vi phạm này là chấp nhận được; Trên thực tế, thường không thể sửa đổi một đối tượng mà không vi phạm bất biến trong ít nhất một chút. Thông thường, chúng tôi yêu cầu mọi phương pháp vi phạm bất biến phải khôi phục bất biến.addFirst, after we have added the node but before we have incremented length, the invariant is violated. This kind of violation is acceptable; in fact, it is often impossible to modify an object without violating an invariant for at least a little while. Normally, we require that every method that violates an invariant must restore the invariant.

Nếu có bất kỳ đoạn mã đáng kể nào trong đó bất biến bị vi phạm, điều quan trọng là các ý kiến ​​phải làm rõ điều đó, để không có hoạt động nào được thực hiện mà phụ thuộc vào bất biến.

18.11. Bảng chú giải¶

Tham chiếu tham chiếu được nhúng được lưu trữ trong một thuộc tính của một đối tượng. Cấu trúc dữ liệu lista được liên kết Mục của dữ liệu có trong một tham chiếu nhúng Node.linkan được sử dụng để liên kết một đối tượng với một đối tượng khác. Là đầu tiên trong danh sách các nút.Singletona được liên kết danh sách với một phương thức Node.WrapPera hoạt động như một người trung gian giữa người gọi và phương thức trợ giúp, thường làm cho phương thức dễ dàng hoặc ít dễ bị lỗi để gọi phương thức được gọi trực tiếp bởi người gọi nhưng được sử dụng bởi một phương thức khác để thực hiện một phần của hoạt động. Khẳng định không đúng fied).

18.12. Bài tập

  1. Theo quy ước, các danh sách thường được in trong ngoặc với dấu phẩy giữa các yếu tố, như trong [1,2,3]. Sửa đổi print_list để nó tạo ra đầu ra ở định dạng này.[1, 2, 3]. Modify print_list so that it generates output in this format.

Một python listnode là gì?

Một phần tử danh sách duy nhất được gọi là một nút.Các nút không giống như các mảng được lưu trữ tuần tự trong bộ nhớ.Thay vào đó, nó có khả năng tìm thấy chúng ở các phân đoạn bộ nhớ khác nhau mà bạn có thể tìm thấy bằng cách theo các con trỏ từ nút này sang nút khác. is called a node. The nodes are not like arrays which are stored sequentially in memory. Instead, it is likely to find them at different memory segments, which you can find by following the pointers from one node to the next.

ListNode tùy chọn trong Python là gì?

Đó là cho phép các giá trị có thể không có.Ví dụ: đây là tất cả các danh sách: (3 -> 1 -> Không) Ví dụ: # Sử dụng tùy chọn [] cho các giá trị không thể là x: tùy chọn [str] = some_function ()to allow for values that can be None. For example: These are all listnodes: (3 -> 1 -> None) Example: # Use Optional[] for values that could be None x: Optional[str] = some_function()

Đầu trong danh sách được liên kết là gì?

Điểm nhập vào một danh sách được liên kết được gọi là người đứng đầu danh sách.Cần lưu ý rằng đầu không phải là một nút riêng biệt, mà là tham chiếu đến nút đầu tiên.Nếu danh sách trống thì đầu là một tham chiếu null.Một danh sách được liên kết là một cấu trúc dữ liệu động. is called the head of the list. It should be noted that head is not a separate node, but the reference to the first node. If the list is empty then the head is a null reference. A linked list is a dynamic data structure.

Danh sách được liên kết trong Python là gì?

Một danh sách được liên kết là một chuỗi các yếu tố dữ liệu, được kết nối với nhau thông qua các liên kết.Mỗi phần tử dữ liệu chứa một kết nối với phần tử dữ liệu khác dưới dạng con trỏ.a sequence of data elements, which are connected together via links. Each data element contains a connection to another data element in form of a pointer.