Kho python
“Cấu trúc” có nghĩa là các quyết định bạn đưa ra liên quan đến cách dự án của bạn đáp ứng tốt nhất mục tiêu của nó. Chúng ta cần xem xét cách tận dụng tốt nhất các tính năng của Python để tạo mã rõ ràng, hiệu quả. Về mặt thực tế, “cấu trúc” có nghĩa là tạo mã sạch có logic và các phần phụ thuộc rõ ràng cũng như cách các tệp và thư mục được tổ chức trong hệ thống tệp Show Những chức năng nào nên đi vào những mô-đun nào? Trong phần này, chúng ta xem xét kỹ hơn các mô-đun của Python và các hệ thống nhập vì chúng là các yếu tố trung tâm để thực thi cấu trúc trong dự án của bạn. Sau đó, chúng tôi thảo luận về các quan điểm khác nhau về cách xây dựng mã có thể được mở rộng và kiểm tra một cách đáng tin cậy Cấu trúc của Kho lưu trữNó quan trọngGiống như Kiểu mã, Thiết kế API và Tự động hóa là điều cần thiết cho một chu kỳ phát triển lành mạnh. Cấu trúc kho lưu trữ là một phần quan trọng trong kiến trúc dự án của bạn Khi một người dùng hoặc cộng tác viên tiềm năng truy cập vào trang của kho lưu trữ của bạn, họ sẽ thấy một số điều
Chỉ khi họ cuộn xuống dưới màn hình đầu tiên thì người dùng mới thấy README của dự án của bạn Nếu repo của bạn là một đống tệp khổng lồ hoặc một mớ hỗn độn các thư mục, họ có thể tìm ở nơi khác trước khi đọc tài liệu đẹp đẽ của bạn
Tất nhiên, ấn tượng đầu tiên không phải là tất cả. Bạn và đồng nghiệp của mình sẽ dành vô số thời gian làm việc với kho lưu trữ này, cuối cùng sẽ trở nên quen thuộc với mọi ngóc ngách. Bố cục là quan trọng Kho lưu trữ mẫutl;dr. Đây là những gì Kenneth Reitz đề xuất vào năm 2013 Kho lưu trữ này có sẵn trên GitHub README.rst LICENSE setup.py requirements.txt sample/__init__.py sample/core.py sample/helpers.py docs/conf.py docs/index.rst tests/test_basic.py tests/test_advanced.py Hãy đi vào một số chi tiết cụ thể Mô-đun thực tếĐịa điểm./sample.py9 hoặc ./test_sample.py0Mục đíchMã quan tâm Gói mô-đun của bạn là trọng tâm cốt lõi của kho lưu trữ. Nó không nên được giấu đi ./sample/ Nếu mô-đun của bạn chỉ bao gồm một tệp duy nhất, bạn có thể đặt nó trực tiếp vào thư mục gốc của kho lưu trữ của mình ./sample.py Thư viện của bạn không thuộc thư mục con src hoặc python mơ hồ Giấy phépĐịa điểm./test_sample.py1Mục đích Xây dựng luật Đây được cho là phần quan trọng nhất trong kho lưu trữ của bạn, ngoài bản thân mã nguồn. Toàn bộ văn bản giấy phép và khiếu nại bản quyền phải tồn tại trong tệp này Nếu bạn không chắc mình nên sử dụng giấy phép nào cho dự án của mình, hãy xem chọnalicense. com Tất nhiên, bạn cũng có thể tự do xuất bản mã mà không cần giấy phép, nhưng điều này sẽ ngăn nhiều người có khả năng sử dụng hoặc đóng góp cho mã của bạn Cài đặt. pyĐịa điểm./test_sample.py2Mục đích Quản lý gói hàng và phân phối Nếu gói mô-đun của bạn nằm ở thư mục gốc của kho lưu trữ, thì rõ ràng gói này cũng phải ở thư mục gốc Tệp yêu cầuLocation./test_sample.py3PurposeDevelopment dependencies A nên được đặt ở thư mục gốc của kho lưu trữ. Nó nên chỉ định các phụ thuộc cần thiết để đóng góp cho dự án. thử nghiệm, xây dựng và tạo tài liệu Nếu dự án của bạn không có phụ thuộc phát triển hoặc nếu bạn muốn thiết lập môi trường phát triển thông qua ./test_sample.py4, tệp này có thể không cần thiết Tài liệuLocation./test_sample.py5PurposePackage reference documentation Có rất ít lý do để điều này tồn tại ở nơi khác Bộ kiểm traĐể được tư vấn về cách viết bài kiểm tra của bạn, hãy xem Kiểm tra mã của bạn . Địa điểm./test_sample.py6 hoặc ./test_sample.py7Mục đíchTích hợp gói và kiểm tra đơn vị Khi mới bắt đầu, một bộ thử nghiệm nhỏ thường sẽ tồn tại trong một tệp duy nhất ./test_sample.py Khi bộ thử nghiệm phát triển, bạn có thể di chuyển các thử nghiệm của mình vào một thư mục, như vậy tests/test_basic.py tests/test_advanced.py Rõ ràng, các mô-đun thử nghiệm này phải nhập mô-đun đã đóng gói của bạn để kiểm tra nó. Bạn có thể làm điều này một vài cách
Tôi đánh giá cao cái sau. Yêu cầu nhà phát triển chạy ./test_sample.py8 để kiểm tra cơ sở mã thay đổi tích cực cũng yêu cầu họ phải thiết lập môi trường biệt lập cho từng phiên bản của cơ sở mã Để cung cấp ngữ cảnh nhập cho các bài kiểm tra riêng lẻ, hãy tạo tệp ./test_sample.py9 import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample Sau đó, trong các mô-đun thử nghiệm riêng lẻ, hãy nhập mô-đun như vậy from .context import sample Điều này sẽ luôn hoạt động như mong đợi, bất kể phương pháp cài đặt Một số người sẽ khẳng định rằng bạn nên phân phối các bài kiểm tra của mình trong chính mô-đun của mình – tôi không đồng ý. Nó thường làm tăng độ phức tạp cho người dùng của bạn; MakefileLocationtests/test_basic.py tests/test_advanced.py0PurposeGeneric management tasks Nếu bạn xem hầu hết các dự án của tôi hoặc bất kỳ dự án Pocoo nào, bạn sẽ nhận thấy một Makefile nằm xung quanh. Tại sao? Makefile mẫu init: pip install -r requirements.txt test: py.test tests .PHONY: init test Các tập lệnh quản lý chung khác (e. g. tests/test_basic.py tests/test_advanced.py1 hoặc tests/test_basic.py tests/test_advanced.py2) cũng thuộc thư mục gốc của kho lưu trữ Về ứng dụng DjangoTôi đã nhận thấy một xu hướng mới trong các ứng dụng Django kể từ khi phát hành Django 1. 4. Nhiều nhà phát triển đang cấu trúc kho lưu trữ của họ kém do các mẫu ứng dụng đi kèm mới Làm sao? $ django-admin.py startproject samplesite Cấu trúc kho lưu trữ kết quả trông như thế này README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py Đừng làm điều này Các đường dẫn lặp đi lặp lại gây nhầm lẫn cho cả công cụ và nhà phát triển của bạn. Việc lồng nhau không cần thiết không giúp được gì cho bất kỳ ai (trừ khi họ hoài cổ về các kho lưu trữ SVN nguyên khối) Hãy làm điều đó đúng cách ./sample/0 Lưu ý “ tests/test_basic.py tests/test_advanced.py3” Cấu trúc kết quả ./sample/1 Cấu trúc mã là chìa khóaNhờ cách nhập và mô-đun được xử lý trong Python, việc cấu trúc một dự án Python tương đối dễ dàng. Dễ dàng ở đây có nghĩa là bạn không có nhiều ràng buộc và mô hình nhập mô-đun dễ nắm bắt. Do đó, bạn chỉ còn lại nhiệm vụ kiến trúc thuần túy là tạo ra các phần khác nhau của dự án và các tương tác của chúng. Cấu trúc dễ dàng của một dự án có nghĩa là nó cũng dễ dàng thực hiện nó một cách kém cỏi. Một số dấu hiệu của một dự án có cấu trúc kém bao gồm
mô-đunCác mô-đun Python là một trong những lớp trừu tượng chính có sẵn và có lẽ là lớp tự nhiên nhất. Các lớp trừu tượng cho phép tách mã thành các phần chứa dữ liệu và chức năng liên quan Ví dụ: một lớp của dự án có thể xử lý giao tiếp với hành động của người dùng, trong khi lớp khác sẽ xử lý thao tác dữ liệu ở mức độ thấp. Cách tự nhiên nhất để tách hai lớp này là tập hợp lại tất cả các chức năng giao tiếp trong một tệp và tất cả các hoạt động cấp thấp trong một tệp khác. Trong trường hợp này, tệp giao diện cần nhập tệp cấp thấp. Điều này được thực hiện với các câu lệnh tests/test_basic.py tests/test_advanced.py9 và import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample0 Ngay khi bạn sử dụng câu lệnh nhập, bạn sử dụng các mô-đun. Đây có thể là các mô-đun tích hợp sẵn như os và sys, mô-đun bên thứ ba mà bạn đã cài đặt trong môi trường của mình hoặc mô-đun nội bộ của dự án của bạn Để phù hợp với hướng dẫn về phong cách, hãy đặt tên mô-đun ngắn, viết thường và đảm bảo tránh sử dụng các ký hiệu đặc biệt như dấu chấm (. ) hoặc dấu chấm hỏi (?). Tên tệp như import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample1 là tên bạn nên tránh. Đặt tên theo cách này sẽ cản trở cách Python tìm kiếm các mô-đun trong trường hợp của tôi. thư rác. py Python hy vọng sẽ tìm thấy tệp import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample2 trong thư mục có tên import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample3, điều này không đúng. Có một cách sử dụng ký hiệu dấu chấm trong tài liệu Python Nếu muốn, bạn có thể đặt tên cho mô-đun của mình là import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample4, nhưng ngay cả dấu gạch dưới, người bạn đáng tin cậy của chúng ta, cũng không nên xuất hiện thường xuyên trong tên mô-đun. Tuy nhiên, việc sử dụng các ký tự khác (dấu cách hoặc dấu gạch ngang) trong tên mô-đun sẽ ngăn quá trình nhập (- là toán tử trừ). Cố gắng giữ tên mô-đun ngắn để không cần phải tách các từ. Và, trên hết, không có không gian tên với dấu gạch dưới; ./sample/2 Ngoài một số hạn chế đặt tên, không có gì đặc biệt cần thiết để tệp Python trở thành một mô-đun. Nhưng bạn cần hiểu cơ chế nhập để sử dụng đúng khái niệm này và tránh một số vấn đề Cụ thể, câu lệnh import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample5 sẽ tìm tệp thích hợp, đó là import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6 trong cùng thư mục với người gọi, nếu nó tồn tại. Nếu nó không được tìm thấy, trình thông dịch Python sẽ tìm kiếm import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6 trong “đường dẫn” theo cách đệ quy và đưa ra một ngoại lệ ImportError khi không tìm thấy nó Khi tìm thấy import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6, trình thông dịch Python sẽ thực thi mô-đun trong một phạm vi biệt lập. Mọi câu lệnh cấp cao nhất trong import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6 sẽ được thực hiện, bao gồm cả các lần nhập khác nếu có. Định nghĩa chức năng và lớp được lưu trữ trong từ điển của mô-đun Sau đó, các biến, hàm và lớp của mô-đun sẽ có sẵn cho người gọi thông qua không gian tên của mô-đun, một khái niệm trung tâm trong lập trình đặc biệt hữu ích và mạnh mẽ trong Python Trong nhiều ngôn ngữ, một lệnh from .context import sample0 được bộ tiền xử lý sử dụng để lấy tất cả mã được tìm thấy trong tệp và 'sao chép' mã đó vào mã của người gọi. Nó khác với Python. mã đi kèm được tách biệt trong một không gian tên mô-đun, điều đó có nghĩa là bạn thường không phải lo lắng rằng mã đi kèm có thể có tác dụng không mong muốn, e. g. ghi đè lên một chức năng hiện có cùng tên Có thể mô phỏng hành vi tiêu chuẩn hơn bằng cách sử dụng cú pháp đặc biệt của câu lệnh nhập. from .context import sample1. Điều này thường được coi là thực hành xấu. Sử dụng from .context import sample2 làm cho mã khó đọc hơn và làm cho các phần phụ thuộc ít bị ngăn cách hơn Sử dụng from .context import sample3 là một cách để xác định chức năng bạn muốn nhập và đặt nó vào không gian tên cục bộ. Mặc dù ít gây hại hơn nhiều so với from .context import sample2 vì nó hiển thị rõ ràng những gì được nhập trong không gian tên cục bộ, nhưng ưu điểm duy nhất của nó so với import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample5 đơn giản hơn là nó sẽ tiết kiệm được một chút thời gian gõ Rất tệ ./sample/3 Tốt hơn ./sample/4 Tốt nhất ./sample/5 Như đã đề cập trong phần này, khả năng đọc là một trong những tính năng chính của Python. Khả năng đọc có nghĩa là tránh văn bản soạn sẵn vô dụng và lộn xộn; . Nhưng sự ngắn gọn và tối nghĩa là giới hạn mà sự ngắn gọn nên dừng lại. Có thể biết ngay lập tức một lớp hoặc chức năng đến từ đâu, như trong thành ngữ from .context import sample6, giúp cải thiện đáng kể khả năng đọc và hiểu mã trong tất cả trừ các dự án tệp đơn giản nhất góiPython cung cấp một hệ thống đóng gói rất đơn giản, nó chỉ đơn giản là một phần mở rộng của cơ chế mô-đun cho một thư mục Bất kỳ thư mục nào có tệp from .context import sample7 đều được coi là gói Python. Các mô-đun khác nhau trong gói được nhập theo cách tương tự như các mô-đun đơn giản, nhưng với một hành vi đặc biệt đối với tệp from .context import sample7, được sử dụng để thu thập tất cả các định nghĩa trên toàn gói Tệp import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6 trong thư mục init: pip install -r requirements.txt test: py.test tests .PHONY: init test0 được nhập với câu lệnh init: pip install -r requirements.txt test: py.test tests .PHONY: init test1. Câu lệnh này sẽ tìm tệp from .context import sample7 trong init: pip install -r requirements.txt test: py.test tests .PHONY: init test3 và thực hiện tất cả các câu lệnh cấp cao nhất của nó. Sau đó, nó sẽ tìm một tệp có tên init: pip install -r requirements.txt test: py.test tests .PHONY: init test4 và thực hiện tất cả các câu lệnh cấp cao nhất của nó. Sau các thao tác này, bất kỳ biến, hàm hoặc lớp nào được xác định trong import os import sys sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) import sample6 đều có sẵn trong gói. không gian tên modu Một vấn đề thường thấy là thêm quá nhiều mã vào tệp from .context import sample7. Khi độ phức tạp của dự án tăng lên, có thể có các gói con và gói con trong cấu trúc thư mục sâu. Trong trường hợp này, việc nhập một mặt hàng từ gói con phụ sẽ yêu cầu thực thi tất cả các tệp from .context import sample7 đã gặp khi duyệt qua cây Để trống tệp from .context import sample7 được coi là thông lệ bình thường và thậm chí là tốt, nếu các mô-đun và gói con của gói không cần chia sẻ bất kỳ mã nào Cuối cùng, có sẵn một cú pháp thuận tiện để nhập các gói được lồng sâu. init: pip install -r requirements.txt test: py.test tests .PHONY: init test9. Điều này cho phép bạn sử dụng mod thay cho sự lặp lại dài dòng của $ django-admin.py startproject samplesite0 Lập trình hướng đối tượngPython đôi khi được mô tả là ngôn ngữ lập trình hướng đối tượng. Điều này có thể gây hiểu nhầm và cần làm rõ thêm Trong Python, mọi thứ đều là một đối tượng và có thể được xử lý như vậy. Đây là ý nghĩa khi chúng ta nói, ví dụ, các hàm là đối tượng hạng nhất. Hàm, lớp, chuỗi và thậm chí cả kiểu là các đối tượng trong Python. giống như bất kỳ đối tượng nào, chúng có một loại, chúng có thể được truyền dưới dạng đối số hàm và chúng có thể có các phương thức và thuộc tính. Theo cách hiểu này, Python có thể được coi là một ngôn ngữ hướng đối tượng Tuy nhiên, không giống như Java, Python không áp đặt lập trình hướng đối tượng làm mô hình lập trình chính. Hoàn toàn khả thi đối với một dự án Python không hướng đối tượng, tôi. e. không sử dụng hoặc sử dụng rất ít định nghĩa lớp, kế thừa lớp hoặc bất kỳ cơ chế nào khác dành riêng cho ngôn ngữ lập trình hướng đối tượng Ngoài ra, như đã thấy trong phần này, cách Python xử lý các mô-đun và không gian tên cung cấp cho nhà phát triển một cách tự nhiên để đảm bảo việc đóng gói và phân tách các lớp trừu tượng, cả hai đều là những lý do phổ biến nhất để sử dụng hướng đối tượng. Do đó, các lập trình viên Python có nhiều quyền hạn hơn để không sử dụng hướng đối tượng, khi nó không được yêu cầu bởi mô hình kinh doanh Có một số lý do để tránh hướng đối tượng không cần thiết. Việc xác định các lớp tùy chỉnh rất hữu ích khi chúng ta muốn gắn một số trạng thái và một số chức năng lại với nhau. Vấn đề, như đã chỉ ra trong các cuộc thảo luận về lập trình chức năng, xuất phát từ phần "trạng thái" của phương trình Trong một số kiến trúc, điển hình là các ứng dụng web, nhiều phiên bản của các quy trình Python được sinh ra như một phản hồi cho các yêu cầu bên ngoài xảy ra đồng thời. Trong trường hợp này, việc giữ một số trạng thái trong các đối tượng được khởi tạo, có nghĩa là giữ một số thông tin tĩnh về thế giới, dễ xảy ra các vấn đề tương tranh hoặc điều kiện chủng tộc. Đôi khi, giữa việc khởi tạo trạng thái của một đối tượng (thường được thực hiện với phương thức $ django-admin.py startproject samplesite1) và việc sử dụng thực tế trạng thái của đối tượng thông qua một trong các phương thức của nó, thế giới có thể đã thay đổi và trạng thái được giữ lại có thể đã lỗi thời. Ví dụ: một yêu cầu có thể tải một mục trong bộ nhớ và đánh dấu nó là đã đọc bởi người dùng. Nếu một yêu cầu khác yêu cầu xóa mục này cùng lúc, thì việc xóa có thể thực sự xảy ra sau khi quá trình đầu tiên tải mục đó và sau đó chúng tôi phải đánh dấu đối tượng đã xóa là đã đọc Vấn đề này và các vấn đề khác đã dẫn đến ý tưởng rằng sử dụng các hàm không trạng thái là một mô hình lập trình tốt hơn Một cách khác để nói điều tương tự là đề xuất sử dụng các hàm và thủ tục với càng ít ngữ cảnh ngầm và tác dụng phụ càng tốt. Bối cảnh ẩn của hàm được tạo thành từ bất kỳ biến toàn cục hoặc mục nào trong lớp lưu trữ được truy cập từ bên trong hàm. Tác dụng phụ là những thay đổi mà một hàm tạo ra đối với ngữ cảnh ẩn của nó. Nếu một chức năng lưu hoặc xóa dữ liệu trong một biến toàn cục hoặc trong lớp lưu trữ lâu dài, thì nó được cho là có tác dụng phụ Việc cô lập cẩn thận các chức năng có ngữ cảnh và tác dụng phụ khỏi các chức năng có logic (được gọi là các chức năng thuần túy) mang lại những lợi ích sau
Tóm lại, các hàm thuần túy là các khối xây dựng hiệu quả hơn các lớp và đối tượng đối với một số kiến trúc vì chúng không có ngữ cảnh hoặc tác dụng phụ Rõ ràng, hướng đối tượng là hữu ích và thậm chí cần thiết trong nhiều trường hợp, ví dụ như khi phát triển các ứng dụng hoặc trò chơi đồ họa trên máy tính để bàn, trong đó những thứ được thao tác (cửa sổ, nút, hình đại diện, phương tiện) có thời gian tồn tại tương đối lâu trong máy tính. người trang tríNgôn ngữ Python cung cấp một cú pháp đơn giản nhưng mạnh mẽ được gọi là 'decorators'. Trình trang trí là một hàm hoặc một lớp bao bọc (hoặc trang trí) một hàm hoặc một phương thức. Hàm hoặc phương thức 'được trang trí' sẽ thay thế hàm hoặc phương thức 'không được trang trí' ban đầu. Bởi vì các hàm là đối tượng hạng nhất trong Python, điều này có thể được thực hiện 'thủ công', nhưng sử dụng cú pháp @decorator sẽ rõ ràng hơn và do đó được ưu tiên hơn ./sample/6 Cơ chế này rất hữu ích để phân tách các mối quan tâm và tránh logic không liên quan bên ngoài 'làm ô nhiễm' logic cốt lõi của hàm hoặc phương thức. Một ví dụ điển hình về một phần chức năng được xử lý tốt hơn với trang trí là hoặc bộ nhớ đệm. bạn muốn lưu trữ kết quả của một hàm đắt tiền trong một bảng và sử dụng chúng trực tiếp thay vì tính toán lại chúng khi chúng đã được tính toán. Đây rõ ràng không phải là một phần của logic chức năng Trình quản lý bối cảnhTrình quản lý bối cảnh là một đối tượng Python cung cấp thêm thông tin theo ngữ cảnh cho một hành động. Thông tin bổ sung này có dạng chạy một hàm có thể gọi được khi bắt đầu ngữ cảnh bằng cách sử dụng câu lệnh $ django-admin.py startproject samplesite2, cũng như chạy một hàm có thể gọi được khi hoàn thành tất cả mã bên trong khối $ django-admin.py startproject samplesite2. Ví dụ nổi tiếng nhất về việc sử dụng trình quản lý ngữ cảnh được hiển thị ở đây, mở trên một tệp ./sample/7 Bất kỳ ai quen thuộc với mẫu này đều biết rằng việc gọi $ django-admin.py startproject samplesite4 theo kiểu này đảm bảo rằng phương thức $ django-admin.py startproject samplesite6 của $ django-admin.py startproject samplesite5 sẽ được gọi vào một thời điểm nào đó. Điều này làm giảm tải nhận thức của nhà phát triển và làm cho mã dễ đọc hơn Có hai cách dễ dàng để tự thực hiện chức năng này. sử dụng một lớp hoặc sử dụng một trình tạo. Hãy tự triển khai các chức năng trên, bắt đầu với cách tiếp cận lớp ./sample/8 Đây chỉ là một đối tượng Python thông thường với hai phương thức bổ sung được sử dụng bởi câu lệnh $ django-admin.py startproject samplesite2. Đầu tiên, CustomOpen được khởi tạo và sau đó phương thức $ django-admin.py startproject samplesite8 của nó được gọi và bất kỳ giá trị trả về nào của $ django-admin.py startproject samplesite8 đều được gán cho $ django-admin.py startproject samplesite5 trong phần README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py1 của câu lệnh. Khi nội dung của khối $ django-admin.py startproject samplesite2 được thực thi xong, phương thức README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py3 sau đó được gọi Và bây giờ, cách tiếp cận trình tạo bằng ngữ cảnh riêng của Python ./sample/9 Điều này hoạt động theo cách chính xác giống như ví dụ về lớp ở trên, mặc dù nó ngắn gọn hơn. Hàm README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py4 thực thi cho đến khi gặp câu lệnh README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py5. Sau đó, nó trao lại quyền kiểm soát cho câu lệnh $ django-admin.py startproject samplesite2, câu lệnh này gán bất kỳ thứ gì đã được ________5'ed cho f trong phần ____23_______1. Mệnh đề README.rst samplesite/manage.py samplesite/samplesite/settings.py samplesite/samplesite/wsgi.py samplesite/samplesite/sampleapp/models.py9 đảm bảo rằng ./sample/00 được gọi cho dù có ngoại lệ bên trong $ django-admin.py startproject samplesite2 hay không Vì hai cách tiếp cận có vẻ giống nhau, chúng ta nên tuân theo Thiền của Python để quyết định khi nào nên sử dụng cách nào. Cách tiếp cận lớp có thể tốt hơn nếu có một lượng logic đáng kể để đóng gói. Cách tiếp cận chức năng có thể tốt hơn cho các tình huống mà chúng ta đang xử lý một hành động đơn giản gõ độngPython được gõ động, có nghĩa là các biến không có kiểu cố định. Trên thực tế, trong Python, các biến rất khác so với các biến trong nhiều ngôn ngữ khác, cụ thể là các ngôn ngữ được nhập tĩnh. Các biến không phải là một phân đoạn của bộ nhớ máy tính nơi một số giá trị được ghi, chúng là 'thẻ' hoặc 'tên' trỏ đến các đối tượng. Do đó, biến 'a' có thể được đặt thành giá trị 1, sau đó là giá trị 'a string', thành hàm Kiểu gõ động của Python thường được coi là một điểm yếu và thực sự nó có thể dẫn đến sự phức tạp và mã khó gỡ lỗi. Một cái gì đó có tên 'a' có thể được đặt thành nhiều thứ khác nhau và nhà phát triển hoặc người bảo trì cần theo dõi tên này trong mã để đảm bảo rằng nó không được đặt thành một đối tượng hoàn toàn không liên quan Một số hướng dẫn giúp tránh vấn đề này
Xấu ./sample.py0 Tốt ./sample.py1 Sử dụng các hàm hoặc phương thức ngắn giúp giảm nguy cơ sử dụng cùng tên cho hai thứ không liên quan Tốt hơn là sử dụng các tên khác nhau ngay cả đối với những thứ có liên quan, khi chúng có một loại khác Xấu ./sample.py2 Không có hiệu quả đạt được khi sử dụng lại tên. các bài tập sẽ phải tạo các đối tượng mới. Tuy nhiên, khi độ phức tạp tăng lên và mỗi phép gán được phân tách bằng các dòng mã khác, bao gồm các nhánh và vòng lặp 'nếu', thì việc xác định loại biến đã cho trở nên khó khăn hơn. Một số phương pháp mã hóa, chẳng hạn như lập trình chức năng, khuyến nghị không bao giờ gán lại một biến. Trong Java, điều này được thực hiện với từ khóa cuối cùng. Python không có từ khóa cuối cùng và dù sao nó cũng đi ngược lại triết lý của nó. Tuy nhiên, có thể là một kỷ luật tốt để tránh gán cho một biến nhiều lần và nó giúp nắm bắt được khái niệm về các loại có thể thay đổi và không thể thay đổi Các loại có thể thay đổi và không thay đổiPython có hai loại tích hợp hoặc do người dùng xác định Các loại có thể thay đổi là những loại cho phép sửa đổi nội dung tại chỗ. Các biến điển hình là danh sách và từ điển. Tất cả các danh sách đều có các phương thức biến đổi, như ./sample/02 hoặc ./sample/03 và có thể được sửa đổi tại chỗ. Điều tương tự cũng xảy ra với từ điển Các loại bất biến không cung cấp phương pháp thay đổi nội dung của chúng. Chẳng hạn, biến x được đặt thành số nguyên 6 không có phương thức “tăng”. Nếu bạn muốn tính x + 1, bạn phải tạo một số nguyên khác và đặt tên cho nó ./sample.py3 Một hậu quả của sự khác biệt trong hành vi này là các loại có thể thay đổi không "ổn định" và do đó không thể được sử dụng làm khóa từ điển Sử dụng các loại có thể thay đổi đúng cách cho những thứ có thể thay đổi về bản chất và các loại không thể thay đổi cho những thứ có bản chất cố định giúp làm rõ mục đích của mã Ví dụ: tương đương bất biến của danh sách là bộ dữ liệu, được tạo bằng ./sample/04. Bộ dữ liệu này là một cặp không thể thay đổi tại chỗ và có thể được sử dụng làm khóa cho từ điển Một điểm đặc biệt của Python có thể khiến người mới bắt đầu ngạc nhiên là các chuỗi không thay đổi. Điều này có nghĩa là khi xây dựng một chuỗi từ các phần của nó, việc nối thêm từng phần vào chuỗi sẽ không hiệu quả vì toàn bộ chuỗi được sao chép trên mỗi phần nối thêm. Thay vào đó, sẽ hiệu quả hơn nhiều nếu tích lũy các phần trong một danh sách, có thể thay đổi được và sau đó dán ( ./sample/05) các phần lại với nhau khi cần chuỗi đầy đủ. Hiểu danh sách thường là cách nhanh nhất và thành ngữ nhất để làm điều này Xấu ./sample.py4 Tốt hơn ./sample.py5 Tốt nhất ./sample.py6 Một điều cuối cùng cần đề cập về chuỗi là sử dụng ./sample/06 không phải lúc nào cũng tốt nhất. Trong trường hợp bạn đang tạo một chuỗi mới từ một số chuỗi được xác định trước, sử dụng toán tử cộng thực sự nhanh hơn. Nhưng trong những trường hợp như trên hoặc trong trường hợp bạn đang thêm vào một chuỗi hiện có, sử dụng ./sample/06 sẽ là phương pháp ưa thích của bạn ./sample.py7 Ghi chú Bạn cũng có thể sử dụng toán tử định dạng để nối một số chuỗi xác định trước bên cạnh và ./sample/09. Tuy nhiên, PEP 3101 không khuyến khích việc sử dụng toán tử ./sample/10 để ủng hộ phương pháp |