Câu trả lời:
Điều này không liên quan gì đến Python; biến toàn cục không tốt trong bất kỳ ngôn ngữ lập trình nào.
Tuy nhiên, về mặt khái niệm các hằng số toàn cục không giống như các biến toàn cục ; hằng số toàn cục hoàn toàn vô hại. Trong Python, sự khác biệt giữa cả hai hoàn toàn theo quy ước: CONSTANTS_ARE_CAPITALIZED
và globals_are_not
.
Lý do các biến toàn cục không tốt là do chúng cho phép các hàm có các tác dụng phụ ẩn (không rõ ràng, đáng ngạc nhiên, khó phát hiện, khó chẩn đoán), dẫn đến sự gia tăng độ phức tạp, có khả năng dẫn đến mã Spaghetti .
Tuy nhiên, việc sử dụng thuần thục trạng thái toàn cục là có thể chấp nhận được (cũng như trạng thái cục bộ và khả năng thay đổi) ngay cả trong lập trình chức năng, để tối ưu hóa thuật toán, giảm độ phức tạp, lưu vào bộ nhớ đệm và ghi nhớ hoặc tính thực tế của các cấu trúc cổng có nguồn gốc chủ yếu là cơ sở mã bắt buộc.
Nói chung, câu hỏi của bạn có thể được trả lời theo nhiều cách, vì vậy cách tốt nhất của bạn là chỉ cần google "tại sao các biến toàn cục là xấu". Vài ví dụ:
Nếu bạn muốn đi sâu hơn và tìm hiểu lý do tại sao lại gây ra các tác dụng phụ và nhiều điều thú vị khác, bạn nên học Lập trình chức năng:
Vâng, về lý thuyết , các khối cầu (và "trạng thái" nói chung) là xấu. Trong thực tế, nếu bạn nhìn vào thư mục các gói của python, bạn sẽ thấy rằng hầu hết các mô-đun ở đó bắt đầu với một loạt các khai báo toàn cục. Rõ ràng, mọi người không có vấn đề gì với chúng.
Đặc biệt đối với python, khả năng hiển thị của hình cầu bị giới hạn trong một mô-đun, do đó không có hình cầu "thực sự" nào ảnh hưởng đến toàn bộ chương trình - điều đó làm cho chúng ít gây hại hơn. Một điểm khác: không có const
, vì vậy khi bạn cần một hằng số, bạn phải sử dụng một toàn cục.
Trong thực tế của tôi, nếu tôi tình cờ sửa đổi một toàn cục trong một hàm, tôi luôn khai báo nó với global
, ngay cả khi về mặt kỹ thuật không cần điều đó, như trong:
cache = {}
def foo(args):
global cache
cache[args] = ...
Điều này làm cho các thao tác của quả cầu dễ dàng theo dõi hơn.
Ý kiến cá nhân về chủ đề này là việc có các biến toàn cục được sử dụng trong một hàm logic có nghĩa là một số mã khác có thể thay đổi logic và kết quả đầu ra mong đợi của hàm đó, điều này sẽ làm cho việc gỡ lỗi rất khó khăn (đặc biệt là trong các dự án lớn) và sẽ khiến việc kiểm tra khó hơn cũng.
Hơn nữa, nếu bạn cho rằng những người khác đang đọc mã của bạn (cộng đồng nguồn mở, đồng nghiệp, v.v.) thì họ sẽ gặp khó khăn khi cố gắng hiểu biến toàn cục đang được đặt ở đâu, đã được thay đổi ở đâu và điều gì sẽ xảy ra từ biến toàn cục này. đến một hàm riêng biệt mà chức năng của nó có thể được xác định bằng cách đọc chính định nghĩa hàm.
Tôi tin rằng một mã sạch và (gần như) không có lỗi phải có các chức năng càng thuần càng tốt (xem các chức năng thuần túy ). Một hàm thuần túy là một hàm có các điều kiện sau:
Việc có các biến toàn cục đang vi phạm ít nhất một trong những điều trên nếu không phải cả hai đều là mã bên ngoài có thể gây ra kết quả không mong muốn.
Một định nghĩa rõ ràng khác về hàm thuần túy: "Hàm thuần túy là hàm nhận tất cả các đầu vào của nó làm đối số rõ ràng và tạo ra tất cả các đầu ra của nó dưới dạng kết quả rõ ràng ." [1] . Việc có các biến toàn cục vi phạm ý tưởng về các hàm thuần túy vì một đầu vào và có thể một trong các đầu ra (biến toàn cục) không được đưa ra hoặc trả về một cách rõ ràng.
Hơn nữa, nếu bạn xem xét thử nghiệm đơn vị và nguyên tắc ĐẦU TIÊN ( thử nghiệm F ast, thử nghiệm độc lập I , R epeatable, S elf-Validating và T imely) có thể sẽ vi phạm nguyên tắc kiểm tra độc lập (có nghĩa là kiểm tra không phụ thuộc trên nhau).
Có một biến toàn cục (không phải luôn luôn) nhưng trong hầu hết các trường hợp (ít nhất là những gì tôi đã thấy cho đến nay) là để chuẩn bị và chuyển kết quả cho các hàm khác. Điều này cũng vi phạm nguyên tắc này. Nếu biến toàn cục đã được sử dụng theo cách đó (tức là biến toàn cục được sử dụng trong hàm X phải được đặt trong hàm Y trước) thì có nghĩa là để kiểm tra đơn vị hàm X, bạn phải chạy thử / chạy hàm Y trước.
Mặt khác và như những người khác đã đề cập, nếu biến toàn cục được sử dụng như một biến "hằng số" có thể tốt hơn một chút vì ngôn ngữ không hỗ trợ hằng số. Tuy nhiên, tôi luôn thích làm việc với các lớp và có "hằng số" như một thành viên của lớp và hoàn toàn không sử dụng biến toàn cục. Nếu bạn có mã mà hai lớp khác nhau yêu cầu để chia sẻ một biến toàn cục thì bạn có thể cần phải cấu trúc lại giải pháp của mình và làm cho các lớp của bạn độc lập.
Tôi không tin rằng không nên sử dụng hình cầu. Nhưng nếu chúng được sử dụng, các tác giả nên xem xét một số nguyên tắc (có lẽ những nguyên tắc đã đề cập ở trên và các nguyên tắc kỹ thuật phần mềm và thực tiễn tốt khác) để có mã sạch hơn và gần như không có lỗi.
Chúng rất cần thiết, màn hình là một ví dụ điển hình. Tuy nhiên, trong một môi trường đa luồng hoặc có nhiều nhà phát triển tham gia, trong thực tế câu hỏi thường đặt ra: ai đã (sai) đặt ra hoặc xóa nó? Tùy thuộc vào kiến trúc, phân tích có thể tốn kém và được yêu cầu thường xuyên. Mặc dù việc đọc var toàn cục có thể được nhưng việc ghi vào nó phải được kiểm soát, ví dụ như bởi một luồng đơn hoặc lớp luồng an toàn. Do đó, các tín đồ toàn cầu nảy sinh nỗi sợ hãi về chi phí phát triển cao có thể gây ra bởi những hậu quả mà bản thân chúng bị coi là xấu xa. Do đó, nói chung, bạn nên giữ cho số lượng vars toàn cầu ở mức thấp.
eval
,import *
, nối chuỗi , biếnid
, bóng tối thuộc tính )