Hướng dẫn how are python projects organized? - các dự án python được tổ chức như thế nào?

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.


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à ...

  • Theo dõi mọi thay đổi bạn thực hiện,
  • Tìm ra chính xác khi bạn phá vỡ một cái gì đó,
  • Có thể xem các phiên bản cũ của mã của bạn,
  • Sao lưu mã của bạn và
  • Hợp tác với người khác.

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:

  • import re
    
    6: Một mô tả về dự án của bạn và các mục tiêu của nó.
  • import re
    
    7: Giấy phép dự án của bạn, nếu đó là nguồn mở. (Xem OpenSource.org để biết thêm thông tin về việc chọn một.)
  • import re
    
    8: Một tệp đặc biệt cho Git biết các tệp và thư mục nào sẽ bỏ qua. (Nếu bạn đang sử dụng VCS khác, tệp này có một tên khác. Hãy tìm nó.)
  • Một thư mục với tên của dự án của bạn.

Đú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

import re
9.

Pep 8 và đặt tên

Phong 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" ... ...

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.

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

  • Làm điều này:
    # smart_door.py
    def close():
        print("Ahhhhhhhhhhhh.")
    
    def open():
        print("Thank you for making a simple door very happy.")
    
    0
  • Không phải thế này:
    # smart_door.py
    def close():
        print("Ahhhhhhhhhhhh.")
    
    def open():
        print("Thank you for making a simple door very happy.")
    
    1

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 (

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
2) nào cũng là một mô -đun và một loạt các mô -đun trong thư mục là một gói.

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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,

import re
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
import re
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,

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, để có ý tưởng về cách chúng ta cấu trúc công cụ ...

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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à

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, với bốn gói phụ:
import smart_door
smart_door.open()
smart_door.close()
1,
import smart_door
smart_door.open()
smart_door.close()
2,
import smart_door
smart_door.open()
smart_door.close()
3 và
import smart_door
smart_door.open()
smart_door.close()
4. Tôi cũng có thư mục
import smart_door
smart_door.open()
smart_door.close()
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).
import smart_door
smart_door.open()
smart_door.close()
5 không phải là một gói, vì nó không chứa
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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:

import smart_door
smart_door.open()
smart_door.close()
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
import smart_door
smart_door.open()
smart_door.close()
9. Chúng ta sẽ nói về những gì diễn ra trong đó
import smart_door
smart_door.open()
smart_door.close()
8 một chút.

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

import re
5. Ví dụ...

import re

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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à

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, với bốn gói phụ:
import smart_door
smart_door.open()
smart_door.close()
1,
import smart_door
smart_door.open()
smart_door.close()
2,
import smart_door
smart_door.open()
smart_door.close()
3 và
import smart_door
smart_door.open()
smart_door.close()
4. Tôi cũng có thư mục
import smart_door
smart_door.open()
smart_door.close()
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).
import smart_door
smart_door.open()
smart_door.close()
5 không phải là một gói, vì nó không chứa
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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:

import smart_door
smart_door.open()
smart_door.close()
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
import smart_door
smart_door.open()
smart_door.close()
9. Chúng ta sẽ nói về những gì diễn ra trong đó
import smart_door
smart_door.open()
smart_door.close()
8 một chút.
File "weird.py", line 1, in
import re
File "re.py", line 122, in
import enum
ModuleNotFoundError: No module named 'enum'

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

import re
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ụ,

from smart_door import open
open()
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
from smart_door import open
open()
4. Điều đó không có nghĩa là chúng có sẵn cho tệp chúng tôi đã nhập
from smart_door import open
open()
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)
from smart_door import open
open()
6 đã bị xóa trên môi trường của bạn và bạn đã chạy
from smart_door import open
open()
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'

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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à

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, với bốn gói phụ:
import smart_door
smart_door.open()
smart_door.close()
1,
import smart_door
smart_door.open()
smart_door.close()
2,
import smart_door
smart_door.open()
smart_door.close()
3 và
import smart_door
smart_door.open()
smart_door.close()
4. Tôi cũng có thư mục
import smart_door
smart_door.open()
smart_door.close()
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).
import smart_door
smart_door.open()
smart_door.close()
5 không phải là một gói, vì nó không chứa
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
3.

import smart_door
smart_door.open()
smart_door.close()

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
9 để làm cho sơ đồ nhỏ đó ở trên.)namespace of
from smart_door import open, close
open()
close()
6 and
from smart_door import *
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à

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, với bốn gói phụ:
import smart_door
smart_door.open()
smart_door.close()
1,
import smart_door
smart_door.open()
smart_door.close()
2,
import smart_door
smart_door.open()
smart_door.close()
3 và
import smart_door
smart_door.open()
smart_door.close()
4. Tôi cũng có thư mục
import smart_door
smart_door.open()
smart_door.close()
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).
import smart_door
smart_door.open()
smart_door.close()
5 không phải là một gói, vì nó không chứa
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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:

import smart_door
smart_door.open()
smart_door.close()
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
import smart_door
smart_door.open()
smart_door.close()
9. Chúng ta sẽ nói về những gì diễn ra trong đó
import smart_door
smart_door.open()
smart_door.close()
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:

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

import re
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.

from smart_door import open
open()

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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
9 để làm cho sơ đồ nhỏ đó ở trên.)

from smart_door import open, close
open()
close()

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

from smart_door import *
5, và sau đó chỉ cần sử dụng
from smart_door import *
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
from smart_door import *
7 và nói
from smart_door import *
8.

Hệ thống

import re
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 ...

from smart_door import *

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

from smart_door import *
from gzip import *
open()

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à,

from smart_door import *
from gzip import *
open()
0 sẽ là hàm được gọi, vì đó là phiên bản cuối cùng của
from smart_door import open, close
open()
close()
6 đã được nhập và do đó được xác định trong mã của chúng tôi.
from smart_door import *
from gzip import *
open()
2 đã bị che mờ - chúng tôi không thể gọi nó là
from smart_door import open, close
open()
close()
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
from smart_door import open, close
open()
close()
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 ...

Rõ ràng là tốt hơn tiềm ẩn.

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

from smart_door import *
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 ...

Căn hộ tốt hơn so với lồng nhau.

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ạn

Cấ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

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8 của tôi ...

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore

Nhập chế độ FullScreenen EXIT Mode FullScreen

Trong mô -đun

from smart_door import *
from gzip import *
open()
6 của tôi, được xác định bởi
from smart_door import *
from gzip import *
open()
7, tôi muốn sử dụng lớp
from smart_door import *
from gzip import *
open()
8 của mình. Lớp đó được định nghĩa trong
from smart_door import *
from gzip import *
open()
9. Làm thế nào để tôi nhận được nó?

Bởi vì tôi đã xác định

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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
omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
1, tôi nói ...

from omission.common.game_enums import GameMode

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,

# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8 và bước xuống gói
import smart_door
smart_door.open()
smart_door.close()
1, nơi nó tìm kiếm
omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
4.absolute import. It starts at the top-level package,
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8, and walks down into the
import smart_door
smart_door.open()
smart_door.close()
1 package, where it looks for
omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
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ư

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
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
import smart_door
smart_door.open()
smart_door.close()
2 (trong đó
omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
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...

import re
0

Nhập chế độ FullScreenen EXIT Mode FullScreen

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
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à
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8. Vì vậy, nhập khẩu bước trở lại một cấp, bước xuống
import smart_door
smart_door.open()
smart_door.close()
1 và tìm thấy
omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
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

from omission.common.game_enums import GameMode
2, tôi có dòng này:

import re
1

Nhậ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

from omission.common.game_enums import GameMode
3, phải không?

Sai! Nó thực sự sẽ thất bại trong việc định vị

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
1. Điều này là do chúng tôi đang chạy gói cấp cao nhất
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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ế:

import re
2

Nhập chế độ FullScreenen EXIT Mode FullScreen

Trong trường hợp đó,

from omission.common.game_enums import GameMode
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.

omission-git
├── LICENSE.md
├── omission
│   ├── app.py
│   ├── common
│   │   ├── classproperty.py
│   │   ├── constants.py
│   │   ├── game_enums.py
│   │   └── __init__.py
│   ├── data
│   │   ├── data_loader.py
│   │   ├── game_round_settings.py
│   │   ├── __init__.py
│   │   ├── scoreboard.py
│   │   └── settings.py
│   ├── game
│   │   ├── content_loader.py
│   │   ├── game_item.py
│   │   ├── game_round.py
│   │   ├── __init__.py
│   │   └── timer.py
│   ├── __init__.py
│   ├── __main__.py
│   ├── resources
│   └── tests
│       ├── __init__.py
│       ├── test_game_item.py
│       ├── test_game_round_settings.py
│       ├── test_scoreboard.py
│       ├── test_settings.py
│       ├── test_test.py
│       └── test_timer.py
├── pylintrc
├── README.md
└── .gitignore
8 có nghĩa là "trở lại một cấp" và
from omission.common.game_enums import GameMode
6 có nghĩa là "vị trí hiện tại". Tất nhiên, Python tiến thêm một bước:
from omission.common.game_enums import GameMode
9 có nghĩa là "trở lại hai cấp độ",
import re
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() 8

Bạn có nhớ khi tôi đề cập đến việc tạo

import smart_door
smart_door.open()
smart_door.close()
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
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
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
import smart_door
smart_door.open()
smart_door.close()
9.

Đây là nội dung của tệp đó:

import re
3

Nhập chế độ FullScreenen EXIT Mode FullScreen

Đúng, đó thực sự là nó! Tôi đang nhập mô-đun của mình

import re
05 từ gói cấp cao nhất
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8.

Hãy nhớ rằng, tôi cũng có thể đã nói

import re
07 thay thế. Ngoài ra, nếu tôi muốn nói
import re
08 thay vì
import re
09, tôi có thể đã thực hiện
import re
10 hoặc
import re
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.boilerplate - code that must be used pretty universally with little to no modification - but this is one of those rare bits.

import re
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
import re
16 ở đầu
from omission.common.game_enums import GameMode
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

import re
18, mô -đun đó được gán giá trị đặc biệt là
import re
15: "Chính".main".

Do đó,

import re
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 ...

import re
4

Nhập chế độ FullScreenen EXIT Mode FullScreen

Đúng, đó thực sự là nó! Tôi đang nhập mô-đun của mình

import re
05 từ gói cấp cao nhất
# smart_door.py
def close():
    print("Ahhhhhhhhhhhh.")

def open():
    print("Thank you for making a simple door very happy.")
8.

Hãy nhớ rằng, tôi cũng có thể đã nói

import re
07 thay thế. Ngoài ra, nếu tôi muốn nói
import re
08 thay vì
import re
09, tôi có thể đã thực hiện
import re
10 hoặc
import re
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.

import re
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
import re
16 ở đầu
from omission.common.game_enums import GameMode
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

    import re
    
    18, mô -đun đó được gán giá trị đặc biệt là
    import re
    
    15: "Chính".

  • Do đó,

    import re
    
    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.module.

  • 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 ...packages. Each package must contain a special

    # smart_door.py
    def close():
        print("Ahhhhhhhhhhhh.")
    
    def open():
        print("Thank you for making a simple door very happy.")
    
    3 file.

  • ... Sau đó tôi có thể thực thi mô -đun đó trực tiếp qua

    import re
    
    22 và kết quả giống như
    import smart_door
    smart_door.open()
    smart_door.close()
    
    9. Bây giờ
    import smart_door
    smart_door.open()
    smart_door.close()
    
    8 đang bị bỏ qua hoàn toàn và ____115 của
    import re
    
    26 là
    import re
    
    27.

  • Trong khi đó, nếu tôi chỉ chạy

    import smart_door
    smart_door.open()
    smart_door.close()
    
    9, mã đặc biệt đó trong
    import re
    
    12 bị bỏ qua, vì
    import re
    
    15 của nó hiện là
    import re
    
    31 một lần nữa.
    use
    import re
    
    34 in an import statement. Before you entertain a possible exception, the Zen of Python points out "Special cases aren't special enough to break the rules."

  • Xem cách hoạt động của nó?

  • Gói lên

Hãy xem xét.

  • Mỗi dự án nên sử dụng VCS, chẳng hạn như Git. Có rất nhiều lựa chọn để lựa chọn.
  • Mỗi tệp mã Python (
    # smart_door.py
    def close():
        print("Ahhhhhhhhhhhh.")
    
    def open():
        print("Thank you for making a simple door very happy.")
    
    2) là một mô -đun.
  • Tổ chức các mô -đun của bạn thành các gói. Mỗi gói phải chứa một tệp
    # smart_door.py
    def close():
        print("Ahhhhhhhhhhhh.")
    
    def open():
        print("Thank you for making a simple door very happy.")
    
    3 đặc biệt.
  • Dự án của bạn thường bao gồm một gói cấp cao nhất, thường chứa các gói phụ. Gói cấp cao nhất đó thường chia sẻ tên của dự án của bạn và tồn tại dưới dạng thư mục trong gốc của kho lưu trữ dự án của bạn.
  • Không bao giờ sử dụng
    import re
    
    34 trong một tuyên bố nhập khẩu. Trước khi bạn giải trí một ngoại lệ có thể, Zen of Python chỉ ra "các trường hợp đặc biệt không đủ đặc biệt để phá vỡ các quy tắc".

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ố ..