Giống như các bài báo? Mua sách! Dead Simple Python của Jason C. McDonald có sẵn từ No Starch Press.Dead Simple Python by Jason C. McDonald is available from No Starch Press. Show
Phần tồi tệ nhất của hướng dẫn luôn luôn là sự đơn giản của họ, phải không? Hiếm khi bạn sẽ tìm thấy một cái có nhiều hơn một tệp, hiếm khi hơn nhiều với nhiều thư mục. Tôi đã thấy rằng cấu trúc một dự án Python là một trong những thành phần thường bị bỏ qua nhất của việc dạy ngôn ngữ. Tồi tệ hơn, nhiều nhà phát triển hiểu sai, vấp phải một mớ hỗn độn của những sai lầm phổ biến cho đến khi họ đến một thứ gì đó ít nhất là hoạt động.structuring a Python project is one of the most often overlooked components of teaching the language. Worse, many developers get it wrong, stumbling through a jumble of common mistakes until they arrive at something that at least works. Đây là tin tốt: Bạn không cần phải là một trong số họ! Trong phần này của loạt phim Python đơn giản chết, chúng tôi sẽ khám phá các câu lệnh, mô -đun, gói, và cách ghép mọi thứ lại với nhau mà không xé tóc. Thậm chí chúng ta sẽ chạm vào VCS, PEP và Zen of Python. Thắt dây an toàn! Thiết lập kho lưu trữTrước khi chúng tôi đi sâu vào cấu trúc dự án thực tế, hãy giải quyết cách thức điều này phù hợp với hệ thống kiểm soát phiên bản của chúng tôi [VCS] ... bắt đầu với thực tế bạn cần một VCS! Một vài lý do là ...
Bạn đã có rất nhiều tùy chọn có sẵn cho bạn. Git là rõ ràng nhất, đặc biệt nếu bạn không biết nên sử dụng những gì khác. Bạn có thể lưu trữ kho Git của mình miễn phí trên GitHub, Gitlab, Bitbucket hoặc Gitote, trong số những người khác. Nếu bạn muốn một cái gì đó khác ngoài Git, có hàng tá các lựa chọn khác, bao gồm Mercurial, Bazaar, Subversion (mặc dù nếu bạn sử dụng cái cuối cùng đó, có lẽ bạn sẽ được coi là một con khủng long của bạn bè.)Git is the most obvious, especially if you don't know what else to use. You can host your Git repository for free on GitHub, GitLab, Bitbucket, or Gitote, among others. If you want something other than Git, there's dozens of other options, including Mercurial, Bazaar, Subversion (although if you use that last one, you'll probably be considered something of a dinosaur by your peers.) Tôi sẽ lặng lẽ giả định rằng bạn đang sử dụng Git cho phần còn lại của hướng dẫn này, vì đó là những gì tôi sử dụng độc quyền. Khi bạn đã tạo kho lưu trữ của mình và sao chép một bản sao cục bộ vào máy tính của bạn, bạn có thể bắt đầu thiết lập dự án của mình. Tối thiểu, bạn sẽ cần phải tạo như sau:
Đúng vậy ... Các tệp mã Python của chúng tôi thực sự thuộc về một thư mục con riêng biệt! Điều này rất quan trọng, vì thư mục gốc của kho lưu trữ của chúng tôi sẽ trở nên lộn xộn với các tệp xây dựng, tập lệnh đóng gói, môi trường ảo và tất cả các cách khác không thực sự là một phần của mã nguồn.our Python code files actually belong in a separate subdirectory! This is very important, as our repository's root directory is going to get mighty cluttered with build files, packaging scripts, virtual environments, and all manner of other things that aren't actually part of the source code. Chỉ vì lợi ích của ví dụ, chúng tôi sẽ gọi dự án hư cấu của chúng tôi 9.Pep 8 và đặt tênPhong cách Python được điều chỉnh phần lớn bởi một tập hợp các tài liệu được gọi là đề xuất tăng cường Python, viết tắt PEP. Tất nhiên, không phải tất cả các PEP đều được thông qua - đó là lý do tại sao chúng được gọi là "đề xuất" - nhưng một số là. Bạn có thể duyệt chỉ số PEP chính trên trang web Python chính thức. Chỉ số này được chính thức gọi là PEP 0.Python Enhancement Proposals, abbreviated PEP. Not all PEPs are actually adopted, of course - that's why they're called "Proposals" - but some are. You can browse the master PEP index on the official Python website. This index is formally referred to as PEP 0. Ngay bây giờ, chúng tôi chủ yếu quan tâm đến PEP 8, lần đầu tiên được tác giả bởi người tạo ngôn ngữ Python Guido Van Rossum trở lại vào năm 2001. Đây là tài liệu chính thức phác thảo phong cách mã hóa mà tất cả các nhà phát triển Python thường nên tuân theo. Giữ nó dưới gối của bạn! Tìm hiểu nó, làm theo nó, khuyến khích người khác làm như vậy.PEP 8, first authored by the Python language creator Guido van Rossum back in 2001. It is the document which officially outlines the coding style all Python developers should generally follow. Keep it under your pillow! Learn it, follow it, encourage others to do the same. . Ngay bây giờ, chúng tôi chủ yếu quan tâm đến phần có tên "Gói và tên mô -đun" ... ...
Chúng ta sẽ nhận được chính xác các mô -đun và gói trong một khoảnh khắc, nhưng bây giờ, hãy hiểu rằng các mô -đun được đặt tên bởi tên tệp và các gói được đặt tên theo tên thư mục của chúng.modules are named by filenames, and packages are named by their directory name. Nói cách khác, tên tệp nên là chữ thường, với dấu gạch dưới nếu điều đó cải thiện khả năng đọc. Tương tự, tên thư mục phải là tất cả các chữ thường, mà không nhấn mạnh nếu có thể tránh được. Để đặt theo cách khác ...filenames should be all lowercase, with underscores if that improves readability. Similarly, directory names should be all lowercase, without underscores if at all avoidable. To put that another way...
Tôi biết, tôi biết, cách dài để tạo ra một điểm, nhưng ít nhất tôi đã đặt một chút pep trong bước của bạn. (Xin chào? Đây có phải là thứ trên không?) Gói và mô -đunĐiều này sẽ cảm thấy chống vi khuẩn, nhưng đây là những định nghĩa được hứa hẹn: Bất kỳ tệp Python ( Chà ... gần như. Có một điều khác bạn phải làm cho một thư mục để biến nó thành một gói và đó là để một tệp có tên 3 vào nó. Bạn thực sự không phải đặt bất cứ thứ gì vào tập tin đó. Nó chỉ cần ở đó.Có những thứ thú vị khác bạn có thể làm với 3, nhưng nó nằm ngoài phạm vi của hướng dẫn này, vì vậy hãy đọc các tài liệu để tìm hiểu thêm.Nếu bạn quên 3 trong gói của mình, nó sẽ làm điều gì đó kỳ quặc hơn là chỉ thất bại, bởi vì điều đó làm cho nó trở thành một gói không gian tên ngầm. Có một số điều tiện lợi bạn có thể làm với loại gói đặc biệt đó, nhưng tôi không đi vào đó ở đây. Như thường lệ, bạn có thể tìm hiểu thêm bằng cách đọc tài liệu: PEP 420: Gói không gian tên ngầm.implicit namespace package. There's some nifty things you can do with that special type of package, but I'm not going into that here. As usual, you can learn more by reading the documentation: PEP 420: Implicit Namespace Packages.Vì vậy, nếu chúng ta nhìn vào cấu trúc dự án của mình, 9 thực sự là một gói và nó có thể chứa các gói khác. Do đó, chúng tôi có thể gọi 9 Gói cấp cao nhất của chúng tôi và tất cả các gói bên dưới các thanh toán con của nó. Điều này sẽ thực sự quan trọng một khi chúng ta nhập khẩu công cụ.Chúng ta hãy xem một ảnh chụp nhanh các dự án trong thế giới thực của tôi, 8, để có ý tưởng về cách chúng ta cấu trúc công cụ ...
Nhập chế độ FullScreenen EXIT Mode FullScreen (Trong trường hợp bạn đang tự hỏi, tôi đã sử dụng chương trình UNIX 9 để làm cho sơ đồ nhỏ đó ở trên.)Bạn sẽ thấy rằng tôi có một gói cấp cao nhất được gọi là 8, với bốn gói phụ: 1, 2, 3 và 4. Tôi cũng có thư mục 5, nhưng chỉ chứa âm thanh trò chơi, hình ảnh, v.v. (bỏ qua ở đây cho sự ngắn gọn). 5 không phải là một gói, vì nó không chứa 3.Tôi cũng có một tệp đặc biệt khác trong gói cấp cao nhất của mình: 8. Đây là tệp được chạy khi chúng tôi thực hiện trực tiếp gói cấp cao nhất của chúng tôi thông qua 9. Chúng ta sẽ nói về những gì diễn ra trong đó 8 một chút.Nhập hoạt động như thế nàoNếu bạn đã viết bất kỳ mã Python có ý nghĩa nào trước đây, bạn gần như chắc chắn đã quen thuộc với câu lệnh 5. Ví dụ...
Nhập chế độ FullScreenen EXIT Mode FullScreen (Trong trường hợp bạn đang tự hỏi, tôi đã sử dụng chương trình UNIX 9 để làm cho sơ đồ nhỏ đó ở trên.)Bạn sẽ thấy rằng tôi có một gói cấp cao nhất được gọi là 8, với bốn gói phụ: 1, 2, 3 và 4. Tôi cũng có thư mục 5, nhưng chỉ chứa âm thanh trò chơi, hình ảnh, v.v. (bỏ qua ở đây cho sự ngắn gọn). 5 không phải là một gói, vì nó không chứa 3.
Nhập hoạt động như thế nào Nếu bạn đã viết bất kỳ mã Python có ý nghĩa nào trước đây, bạn gần như chắc chắn đã quen thuộc với câu lệnh 5. Ví dụ...Thật hữu ích khi biết rằng, khi chúng tôi nhập một mô -đun, chúng tôi thực sự đang chạy nó. Điều này có nghĩa là bất kỳ câu lệnh import re 5 nào trong mô -đun cũng đang được chạy.Ví dụ, 3 có một số báo cáo nhập khẩu của riêng mình, được thực hiện khi chúng ta nói 4. Điều đó không có nghĩa là chúng có sẵn cho tệp chúng tôi đã nhập 5 từ, nhưng điều đó có nghĩa là các tệp đó phải tồn tại. Nếu (vì một số lý do không thể xảy ra) 6 đã bị xóa trên môi trường của bạn và bạn đã chạy 4, nó sẽ thất bại với một lỗi ...Traceback (cuộc gọi gần đây nhất cuối cùng): Tệp "WEIRD.PY", LINE 1, trong tệp nhập RE "Re.py", dòng 122, trong nhập enum modulenotfounderror: Không có mô -đun có tên 'enum'
Nhập chế độ FullScreenen EXIT Mode FullScreen (Trong trường hợp bạn đang tự hỏi, tôi đã sử dụng chương trình UNIX 9 để làm cho sơ đồ nhỏ đó ở trên.)Bạn sẽ thấy rằng tôi có một gói cấp cao nhất được gọi là 8, với bốn gói phụ: 1, 2, 3 và 4. Tôi cũng có thư mục 5, nhưng chỉ chứa âm thanh trò chơi, hình ảnh, v.v. (bỏ qua ở đây cho sự ngắn gọn). 5 không phải là một gói, vì nó không chứa 3.
Nhập chế độ FullScreenen EXIT Mode FullScreen (Trong trường hợp bạn đang tự hỏi, tôi đã sử dụng chương trình UNIX 9 để làm cho sơ đồ nhỏ đó ở trên.)namespace of 6 and 0. Python developers really like namespaces, because they make it obvious where functions and whatnot are coming from.Bạn sẽ thấy rằng tôi có một gói cấp cao nhất được gọi là 8, với bốn gói phụ: 1, 2, 3 và 4. Tôi cũng có thư mục 5, nhưng chỉ chứa âm thanh trò chơi, hình ảnh, v.v. (bỏ qua ở đây cho sự ngắn gọn). 5 không phải là một gói, vì nó không chứa 3.Tôi cũng có một tệp đặc biệt khác trong gói cấp cao nhất của mình: 8. Đây là tệp được chạy khi chúng tôi thực hiện trực tiếp gói cấp cao nhất của chúng tôi thông qua 9. Chúng ta sẽ nói về những gì diễn ra trong đó 8 một chút.Zen of Python, also known as PEP 20, defines the philosophy behind the Python language. The last line has a statement that addresses this:
Nếu bạn đã viết bất kỳ mã Python có ý nghĩa nào trước đây, bạn gần như chắc chắn đã quen thuộc với câu lệnh 5. Ví dụ...Thật hữu ích khi biết rằng, khi chúng tôi nhập một mô -đun, chúng tôi thực sự đang chạy nó. Điều này có nghĩa là bất kỳ câu lệnh 5 nào trong mô -đun cũng đang được chạy.
Nhập chế độ FullScreenen EXIT Mode FullScreen (Trong trường hợp bạn đang tự hỏi, tôi đã sử dụng chương trình UNIX 9 để làm cho sơ đồ nhỏ đó ở trên.)
Nhập chế độ FullScreenen EXIT Mode FullScreen Trong cơn ác mộng đóng gói lồng nhau khủng khiếp đó trước đó, giờ đây chúng ta có thể nói 5, và sau đó chỉ cần sử dụng 6 trực tiếp. Ngoài ra, nếu chúng ta muốn một chút không gian tên, chúng ta có thể nói 7 và nói 8.Hệ thống 5 rất linh hoạt như thế.Tuy nhiên, không lâu, có lẽ bạn sẽ thấy mình nói "nhưng tôi có hàng trăm chức năng trong mô -đun của mình và tôi muốn sử dụng tất cả!" Đây là điểm mà nhiều nhà phát triển đi ra khỏi đường ray, bằng cách làm điều này ...
Nhập chế độ FullScreenen EXIT Mode FullScreen Điều này rất, rất xấu! Nói một cách đơn giản, nó nhập mọi thứ trong mô -đun trực tiếp và đó là một vấn đề. Hãy tưởng tượng mã sau ... Simply put, it imports everything in the module directly, and that's a problem. Imagine the following code...
Nhập chế độ FullScreenen EXIT Mode FullScreen Bạn cho rằng điều gì sẽ xảy ra? Câu trả lời là, 0 sẽ là hàm được gọi, vì đó là phiên bản cuối cùng của 6 đã được nhập và do đó được xác định trong mã của chúng tôi. 2 đã bị che mờ - chúng tôi không thể gọi nó là 6, điều đó có nghĩa là chúng tôi thực sự không thể gọi nó.shadowed - we can't call it as 6, which means we effectively can't call it at all.Tất nhiên, vì chúng ta thường không biết, hoặc ít nhất là không nhớ, mọi hàm, lớp và biến trong mỗi mô -đun được nhập, chúng ta có thể dễ dàng kết thúc với rất nhiều mớ hỗn độn. Zen of Python cũng đề cập đến kịch bản này ...
Bạn không bao giờ phải đoán nơi một chức năng hoặc biến đến từ đâu. Ở đâu đó trong tệp nên là mã rõ ràng cho chúng ta biết nó đến từ đâu. Hai kịch bản đầu tiên chứng minh điều đó. Tôi cũng nên đề cập rằng kịch bản 1 trước đó là điều mà các nhà phát triển Python không muốn xem. Cũng từ Zen of Python ...
Một số gói của các gói là ổn, nhưng khi dự án của bạn bắt đầu trông giống như một bộ búp bê Matryoshka phức tạp, bạn đã làm điều gì đó sai. Tổ chức các mô -đun của bạn thành các gói, nhưng giữ cho nó đơn giản hợp lý. Nhập khẩu trong dự án của bạnCấu trúc tệp dự án mà chúng tôi đã tạo trước đó sắp trở nên rất tiện dụng. Nhớ lại dự án 8 của tôi ...
Nhập chế độ FullScreenen EXIT Mode FullScreen Trong mô -đun 6 của tôi, được xác định bởi 7, tôi muốn sử dụng lớp 8 của mình. Lớp đó được định nghĩa trong 9. Làm thế nào để tôi nhận được nó?Bởi vì tôi đã xác định 8 là một gói và tổ chức các mô -đun của tôi thành các gói con, nó thực sự khá dễ dàng. Trong 1, tôi nói ...
Nhập chế độ FullScreenen EXIT Mode FullScreen Điều này được gọi là nhập khẩu tuyệt đối. Nó bắt đầu ở gói cấp cao nhất, 8 và bước xuống gói 1, nơi nó tìm kiếm 4.absolute import. It starts at the top-level package, 8, and walks down into the 1 package, where it looks for 4.Một số nhà phát triển đến với tôi với các báo cáo nhập khẩu giống như 5 và tự hỏi tại sao nó không hoạt động. Nói một cách đơn giản, gói 2 (trong đó 1 sống) không có kiến thức về các gói anh chị em của nó.Nó, tuy nhiên, biết về cha mẹ của nó. Bởi vì điều này, Python có một thứ gọi là nhập khẩu tương đối cho phép chúng ta làm điều tương tự như thế này thay vào đó ...relative imports that lets us do the same thing like this instead... 0Nhập chế độ FullScreenen EXIT Mode FullScreen 8 có nghĩa là "Gói cha mẹ trực tiếp của gói này", trong trường hợp này là 8. Vì vậy, nhập khẩu bước trở lại một cấp, bước xuống 1 và tìm thấy 4.Có rất nhiều cuộc tranh luận về việc sử dụng nhập khẩu tuyệt đối hay tương đối. Cá nhân, tôi thích sử dụng nhập khẩu tuyệt đối bất cứ khi nào có thể, bởi vì nó làm cho mã dễ đọc hơn rất nhiều. Bạn có thể tạo nên tâm trí của riêng bạn, tuy nhiên. Phần quan trọng duy nhất là kết quả là rõ ràng - không nên có bí ẩn nào đến từ đâu. (Tiếp tục đọc: Real Python - Tuyệt đối với nhập khẩu tương đối Có một gotcha ẩn nấp khác ở đây! Trong 2, tôi có dòng này: 1Nhập chế độ FullScreenen EXIT Mode FullScreen Chắc chắn, vì cả hai mô -đun này đều nằm trong cùng một gói, chúng ta sẽ có thể nói 3, phải không?Sai! Nó thực sự sẽ thất bại trong việc định vị 1. Điều này là do chúng tôi đang chạy gói cấp cao nhất 8, có nghĩa là đường dẫn tìm kiếm (nơi Python tìm kiếm các mô-đun và theo thứ tự nào) hoạt động khác nhau.search path (where Python looks for modules, and in what order) works differently.
Tuy nhiên, chúng tôi có thể sử dụng nhập khẩu tương đối thay thế: 2Nhập chế độ FullScreenen EXIT Mode FullScreen Trong trường hợp đó, 6 duy nhất có nghĩa là "gói này".Nếu bạn quen thuộc với hệ thống tệp Unix điển hình, điều này sẽ bắt đầu có ý nghĩa. 8 có nghĩa là "trở lại một cấp" và 6 có nghĩa là "vị trí hiện tại". Tất nhiên, Python tiến thêm một bước: 9 có nghĩa là "trở lại hai cấp độ", 00 là "ba cấp độ", v.v.
Tuy nhiên, hãy nhớ rằng những "cấp độ" đó không chỉ là các thư mục đơn giản, ở đây. Chúng là các gói. Nếu bạn có hai gói riêng biệt trong một thư mục đơn giản không phải là gói, bạn không thể sử dụng nhập khẩu tương đối để nhảy từ cái này sang thư mục khác. Bạn sẽ phải làm việc với đường dẫn tìm kiếm Python cho điều đó và điều đó nằm ngoài phạm vi của hướng dẫn này. (Xem các tài liệu ở cuối bài viết này.) import smart_door smart_door.open() smart_door.close() 8Bạn có nhớ khi tôi đề cập đến việc tạo 8 trong gói cấp cao nhất của chúng tôi không? Đó là một tệp đặc biệt được thực thi khi chúng tôi chạy gói trực tiếp với Python. Gói 8 của tôi có thể được chạy từ gốc của kho lưu trữ của tôi với 9.Đây là nội dung của tệp đó: 3Nhập chế độ FullScreenen EXIT Mode FullScreen Đúng, đó thực sự là nó! Tôi đang nhập mô-đun của mình 05 từ gói cấp cao nhất 8.Hãy nhớ rằng, tôi cũng có thể đã nói 07 thay thế. Ngoài ra, nếu tôi muốn nói 08 thay vì 09, tôi có thể đã thực hiện 10 hoặc 11. Cuối cùng, nó không tạo ra nhiều sự khác biệt kỹ thuật về cách tôi thực hiện nhập khẩu đó, miễn là mã có thể đọc được.. Phần gây nhầm lẫn hầu hết mọi người lúc đầu là toàn bộ tuyên bố 14. Python không có nhiều nồi hơi - mã phải được sử dụng khá phổ biến với rất ít hoặc không có sửa đổi - nhưng đây là một trong những bit hiếm.boilerplate - code that must be used pretty universally with little to no modification - but this is one of those rare bits. 15 là một thuộc tính chuỗi đặc biệt của mỗi mô -đun Python. Nếu tôi dán dòng 16 ở đầu 2, khi mô -đun đó được nhập (và do đó chạy), chúng ta sẽ thấy "OSMISS.DATA.SETINGS" được in ra.Khi một mô -đun được chạy trực tiếp qua 18, mô -đun đó được gán giá trị đặc biệt là 15: "Chính".main".Do đó, 20 thực sự đang kiểm tra xem mô -đun có được thực thi làm mô -đun chính không. Nếu có, nó chạy mã theo điều kiện.Bạn có thể thấy điều này trong hành động một cách khác. Nếu tôi thêm phần sau vào cuối ____ 112 ... 4Nhập chế độ FullScreenen EXIT Mode FullScreen Đúng, đó thực sự là nó! Tôi đang nhập mô-đun của mình 05 từ gói cấp cao nhất 8.Hãy nhớ rằng, tôi cũng có thể đã nói 07 thay thế. Ngoài ra, nếu tôi muốn nói 08 thay vì 09, tôi có thể đã thực hiện 10 hoặc 11. Cuối cùng, nó không tạo ra nhiều sự khác biệt kỹ thuật về cách tôi thực hiện nhập khẩu đó, miễn là mã có thể đọc được.. Phần gây nhầm lẫn hầu hết mọi người lúc đầu là toàn bộ tuyên bố import re 14. Python không có nhiều nồi hơi - mã phải được sử dụng khá phổ biến với rất ít hoặc không có sửa đổi - nhưng đây là một trong những bit hiếm. 15 là một thuộc tính chuỗi đặc biệt của mỗi mô -đun Python. Nếu tôi dán dòng 16 ở đầu 2, khi mô -đun đó được nhập (và do đó chạy), chúng ta sẽ thấy "OSMISS.DATA.SETINGS" được in ra.
Hãy xem xét.
Sử dụng nhập khẩu tuyệt đối hoặc tương đối để chỉ các mô -đun khác trong dự án của bạn. Chương trình Python được cấu trúc như thế nào?Các thuộc tính và nhập khẩu: Chương trình Python cấu trúc bao gồm ba tệp như: a.py, B.Py và C.Py. Mô hình tệp a.py được chọn cho tệp cấp cao. Nó được biết đến như một tệp văn bản đơn giản của các câu lệnh. Và nó có thể được thực hiện từ dưới lên trên khi nó được ra mắt.consists of three files such as : a.py,b.py and c.py. The file model a.py is chosen for high level file . it is known as a simple text file of statements. And it can be executed from bottom to top when it is launched.
Cách tốt nhất để tổ chức mã Python là gì?Các mô -đun là các tập tin với các tập tin.Tiện ích mở rộng PY có chứa mã Python.Họ giúp tổ chức các chức năng, lớp hoặc bất kỳ khối mã nào liên quan trong cùng một tệp.Nó được coi là một thông lệ tốt nhất để chia các khối mã Python lớn thành các mô -đun chứa tới 300 dòng mã400400.split the large Python code blocks into modules containing up to 300–400 lines of code.
Các dự án Python được đặt tên như thế nào?PEP8 định nghĩa một tiêu chuẩn cho cách đặt tên cho các gói và mô-đun: các mô-đun nên có tên ngắn, toàn bộ.Dấu gạch dưới có thể được sử dụng trong tên mô -đun nếu nó cải thiện khả năng đọc.Các gói Python cũng nên có tên ngắn, toàn bộ, mặc dù việc sử dụng dấu gạch dưới không được khuyến khích.Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.
Các loại dự án trong Python là gì?Ý tưởng dự án Python: Cấp độ mới bắt đầu.. Tạo một trình tạo mã..... Xây dựng một máy tính đếm ngược..... Viết một phương thức sắp xếp..... Xây dựng một bài kiểm tra tương tác..... Tic-tac-toe theo văn bản..... Tạo một bộ chuyển đổi nhiệt độ/đo lường..... Xây dựng một ứng dụng quầy..... Xây dựng một trò chơi đoán số .. |