Trong Chương trước, chúng ta đã thảo luận về Danh sách Python, đối tượng
4
4 tương tự như Danh sách như thế nào và cách chúng ta có thể đặt các đối tượng vào một 4
4, xem xét phần bù của chúng và 4
7 đối với 4
4 trong MusicXML hoặc dưới dạng văn bản. Chúng tôi kết thúc bằng cách đặt một 4
4 bên trong một 4
4 khác, đây có vẻ là một thủ thuật hay cho đến khi chúng tôi phát hiện ra rằng chúng tôi không thể lấy được các phần tử bên trong 4
4 bên trongTrong chương này, chúng ta sẽ nghiên cứu cách khai thác sức mạnh của
listB[3]2 lồng nhau. Chúng ta sẽ bắt đầu thảo luận về danh sách đệ quy [vì
listB[3]2 hoạt động rất giống danh sách]. Những người có một số lập trình có thể sẽ muốn bỏ qua phần sau
danh sách danh sách
Danh sách [tương tự như Mảng trong các ngôn ngữ khác] có thể chứa tất cả những thứ khác bên trong chúng, bao gồm cả các danh sách khác. Vì vậy, hãy bắt đầu bằng cách tạo hai danh sách
listA = [10, 20, 30] listB = [1, 2, 3, listA]
Bây giờ khi chúng ta nhìn vào danh sách, chúng ta sẽ thấy danh sách đó nằm trong danh sách đó
listB
[1, 2, 3, [10, 20, 30]]
Lưu ý rằng khi chúng ta nhìn vào độ dài [
listB[3]4] của danh sách B, nó cho thấy có 4 phần tử chứ không phải 6
len[listB]
4
Đó là bởi vì phần tử thứ tư của listB [mà bạn sẽ nhớ lại, được gọi là
listB[3]5 chứ không phải
listB[3]6] bản thân nó là một danh sách, listA
listB[3]
[10, 20, 30]
listB[3] is listA
True
Vì vậy, nếu chúng ta muốn lấy phần tử thứ ba của listA, có một cách dễ dàng để thực hiện
listA[2]
listB
0Nhưng chúng ta cũng có thể nghĩ rằng
listB[3]7 cũng là phần tử thứ ba của phần tử thứ tư của listB. Vì vậy, chúng ta có thể viết điều này thay vì
listB
1listB
0Ồ, và vì mỗi phần tử này là phần tử cuối cùng trong danh sách tương ứng của chúng, thay vào đó chúng ta có thể viết
listB
3listB
0có nghĩa là "lấy phần tử cuối cùng của phần tử cuối cùng của danh sách"
Nhưng điều gì sẽ xảy ra nếu chúng ta chỉ muốn biết mọi số được lưu trữ ở bất kỳ đâu trong listB, ngay cả khi số đó nằm trong chính danh sách đó?
listB
5listB
6Thay vào đó, chúng ta phải kiểm tra xem mỗi “số” trong
listB[3]8 thực sự là một số hay một danh sách. Và nếu đó là một danh sách, chúng ta nên tìm từng số trong đó và in ra. Đây là một bộ lệnh phức tạp hơn một chút để làm điều đó
listB
7listB
8Điều đó đã làm nó. Làm thế nào nó hoạt động? . Sau đó, ở dòng tiếp theo
[10, 20, 30]0 kiểm tra xem thứ đó có phải là một danh sách không. Nếu đó là
[10, 20, 30]1 thì chúng ta sẽ đến một vòng lặp bên trong, nơi chúng ta xem xét “thứ” [trong trường hợp này là
[10, 20, 30]2, nhưng chương trình không biết điều đó] và lấy “số” từ đó. Nhưng nếu "thứ" không phải là một danh sách, thì đó là nơi mà ____18_______3 xuất hiện, đó là thứ chúng tôi chạy nếu chúng tôi không có một danh sách, nó chỉ nói, in số
[Trong trường hợp này, chúng tôi giả định rằng chỉ có hai loại sự vật trong
listB[3]8, các con số và các danh sách khác. ] Gặp lỗi nhớ đừng quên đoạn kết “. ” hoặc thụt lề dòng tiếp theo
Hàm và đệ quy
Nhưng điều gì sẽ xảy ra nếu chúng ta làm điều này
listB
9Bây giờ vì listB chứa listA, chúng tôi kết thúc với một danh sách trong danh sách trong danh sách
[1, 2, 3, [10, 20, 30]]0
[1, 2, 3, [10, 20, 30]]1
Nếu chúng tôi muốn in tất cả các số trong listC, chúng tôi có thể viết một tập hợp các lệnh xấu xí như thế này [Tôi sẽ hiểu nếu bạn không thực sự muốn nhập số này và chỉ muốn tin tôi rằng nó hoạt động]
[1, 2, 3, [10, 20, 30]]2
[1, 2, 3, [10, 20, 30]]3
chà. Nếu đây là cách duy nhất để làm điều đó, tôi sẽ không trách bạn nếu bạn quyết định rằng lập trình không đáng để bạn phải đau đầu. Đặc biệt là vì bạn có thể đã đoán rằng chúng tôi có thể tạo ra.
[10, 20, 30]5 và nhận một lớp danh sách khác. May mắn thay, có một chút phép thuật lập trình gọi là “đệ quy” mà chúng ta có thể sử dụng để đi vào trọng tâm của vấn đề. Lưu ý rằng trong mã tôi vừa viết, có một vài dòng về cơ bản giống [với một vài từ được thay đổi] như các phần khác của mã. Với mã hóa đệ quy, chúng tôi sẽ tìm cách lưu các dòng đó để sử dụng lại chúng. Nhập sáu dòng này
[1, 2, 3, [10, 20, 30]]4
Những gì chúng tôi đã làm là tạo một chức năng mới gọi là ''flatPrint'' để tiếp cận danh sách các danh sách và in bất kỳ thứ gì có trong đó
Bây giờ cố gắng
[1, 2, 3, [10, 20, 30]]5
[1, 2, 3, [10, 20, 30]]3
nó hoạt động. Nhưng bằng cách nào?
Câu lệnh
[10, 20, 30]6 nói rằng chúng ta sẽ ''xác định'' một chức năng mới. Sau từ
[10, 20, 30]6 là tên của hàm – thứ mà chúng ta có thể gọi nó để sử dụng sau này. [Chúng tôi gọi quá trình lấy các cấu trúc lồng nhau và biến chúng thành thứ gì đó tuyến tính là “làm phẳng” chúng, giống như nghiền nát một hộp các tông. Vì đây là một máy làm phẳng cũng in những gì bên trong nó, nên
[10, 20, 30]8 là một cái tên hay cho nó. Lưu ý rằng giống như với các biến, trường hợp quan trọng trong Python, do đó,
[10, 20, 30]8 không giống như
listB[3] is listA0 hoặc
listB[3] is listA1 hoặc
listB[3] is listA2. ]
Sau “flatPrint”, trong ngoặc đơn là tên biến
listB[3] is listA3. Lưu ý rằng chúng tôi chưa sử dụng tên
listB[3] is listA3 – nó không tồn tại. Ý nghĩa của
listB[3] is listA3 ở đây là bất cứ khi nào chúng ta sử dụng hàm
[10, 20, 30]8, bất kể tên của danh sách là gì, thì trong vòng
[10, 20, 30]8 nó sẽ được gọi là
listB[3] is listA3. Vì vậy, bạn có thể nói
listB[3] is listA9, như chúng ta vừa làm, và trong hàm
[10, 20, 30]8,
True
1 sẽ được gọi là listB[3] is listA3
Đây là một chức năng đơn giản hơn sẽ giải thích điều đó tốt hơn.
True
3 nhận một số và in ra hình vuông của nó[1, 2, 3, [10, 20, 30]]7
Bây giờ chúng ta có thể thử
[1, 2, 3, [10, 20, 30]]8
[1, 2, 3, [10, 20, 30]]9
len[listB]0
len[listB]1
len[listB]2
len[listB]3
Lưu ý hai điều trong trường hợp cuối cùng. Đầu tiên số pi không chính xác là 3. 14 – tất cả chúng ta đều biết điều đó; . Thứ hai, chúng tôi đã đưa biến
True
4 vào hàm True
3. Nhưng trong hàm True
3 chúng ta không viết. True
7; . [Nhân tiện, thay vì viết listA[2]0 chúng ta có thể viết
listA[2]1 vì ‘’ ** ‘’ là cách Python biểu thị số mũ]
Khi kết thúc một chức năng, bạn có thể
listA[2]2 một thứ gì đó hoặc
listA[2]3 một giá trị, giá trị này có thể được sử dụng cho bất kỳ thứ gì khác. Đây là
listA[2]4 hoạt động rất giống với
True
3, nhưng nó chia số thành khối và thay vì in ra, nó sẽ trả về số đólen[listB]4
Bởi vì chúng tôi không in
True
9, chúng tôi có thể gán giá trị của cubeMe cho một biến kháclen[listB]5
len[listB]6
len[listB]7
len[listB]8
Lưu ý rằng nếu
listA[2]7 và
listA[2]8 thì chúng ta có thể thay thế
listA[2]9 cho
listB
00 và viếtlen[listB]9
len[listB]8
Do đó, sử dụng
listA[2]3 thay vì
listA[2]2 sẽ hiệu quả hơn, vì vậy sau khi kết thúc với
[10, 20, 30]8, chúng ta chủ yếu sẽ viết các hàm
listA[2]3 chứ không phải hàm
listA[2]2
Vì vậy, quay lại
[10, 20, 30]8, mà bạn sẽ nhớ là [Tôi đang thêm lại số dòng nhận xét để tôi có thể tham khảo]
4
1Hãy nhìn vào nó từng dòng một
Dòng 1, như chúng ta đã nói, định nghĩa hàm có tên là
[10, 20, 30]8 cần một danh sách mà chúng ta sẽ gọi là
listB[3] is listA3
Dòng 2, nói “đối với mỗi thứ trong danh sách của tôi, hãy lấy nó và gọi nó là
listB
09. ” Khi chúng ta hoàn thành với listB
09, chương trình sẽ quay lại dòng 2 để thực hiện việc tiếp theoDòng 3, kiểm tra xem
listB
09 có phải là danh sách không. Nếu vậy, chúng tôi làm dòng 4. Nếu không chúng ta nhảy đến dòng 5Dòng 4. Đây là nơi phép màu xảy ra. Bây giờ chúng ta biết rằng
listB
09 là một danh sách. Vậy làm thế nào để chúng tôi in một danh sách [có thể có các danh sách khác bên trong nó]? . Về bản chất, [10, 20, 30]8 sử dụng khả năng phân biệt rõ ràng giữa danh sách và số để in bất kỳ danh sách nội bộ nào. Chúng ta gọi các hàm sử dụng [“gọi”] chính các hàm đệ quy và quá trình sử dụng các hàm đệ quy được gọi là đệ quy. Đó là một công cụ mạnh mẽ và chúng tôi sẽ sử dụng rất nhiều trong music21
Dòng 5, là nơi chúng ta nhảy từ dòng 3 nếu
listB
09 không phải là danh sách, vì vậy Python sẽ thực thi dòng 6Dòng 6, chỉ cần in
listB
09, mà bây giờ chúng ta biết là một sốMột lời cảnh báo. không giống như một số ngôn ngữ lập trình [Java, C, v.v. ], Python không bao giờ kiểm tra xem những gì bạn chuyển đến
[10, 20, 30]8 có thực sự là một danh sách không. Vì vậy, bạn có thể thử làm điều gì đó như
listB
18 nhưng vì listB[3]7 không phải là một danh sách nên bạn sẽ gặp lỗi
4
2 4
3Để biết thêm thông tin về cấu trúc dữ liệu [danh sách, danh sách của danh sách và những thứ chúng tôi chưa hiểu, tôi khuyên bạn nên xem hướng dẫn Python của Google, đặc biệt là lớp 2]
Gói [lại
Trong chương này, chúng ta đã xem xét cách chúng ta có thể nhìn vào bên trong danh sách của danh sách, điều này sẽ rất quan trọng khi chúng ta xem xét cách làm việc với
listB[3]2 của
listB[3]2 trong âm nhạc21, để xem xét
listB
22 trong phạm vi listB
23 trong phạm vi listB
24. Chúng tôi cũng đã học cách xác định một hàm và viết các hàm đệ quy để thực hiện công việc hiệu quả chỉ trong một vài dòng mã. Trong chương tiếp theo, chúng ta áp dụng tất cả những điều này vào âm nhạc với