Hướng dẫn is it bad to use a global variable in python? - sử dụng biến toàn cục trong python có tệ không?

Một ý kiến ​​cá nhân về chủ đề là việc có các biến toàn cầu đang được sử dụng trong logic hàm có nghĩa là một số mã khác có thể thay đổi logic và đầu ra dự kiến ​​của hàm đó sẽ khiến việc gỡ lỗi rất khó (đặc biệt là trong các dự án lớn) và sẽ làm cho thử nghiệm khó khăn hơn cũng.

Hơn nữa, nếu bạn xem xét người khác đọc mã của bạn (cộng đồng nguồn mở, đồng nghiệp, v.v.), họ sẽ gặp khó khăn khi cố gắng hiểu biến toàn cầu đang được thiết lập, nơi đã được thay đổi và những gì mong đợi từ biến toàn cầu này trái ngược đối với một hàm bị cô lập mà chức năng của nó có thể được xác định bằng cách đọc định nghĩa hàm.

(Có lẽ) vi phạm định nghĩa chức năng thuần túy

Tôi tin rằng một mã không có lỗi và (gần) sẽ có các chức năng tinh khiết nhất có thể (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:

  1. Hàm luôn đánh giá cùng một giá trị kết quả với cùng một giá trị đối số. Giá trị kết quả chức năng không thể phụ thuộc vào bất kỳ thông tin hoặc trạng thái ẩn nào có thể thay đổi trong khi tiến hành thực hiện chương trình hoặc giữa các lần thực hiện khác nhau của chương trình, cũng không thể phụ thuộc vào bất kỳ đầu vào bên ngoài nào từ các thiết bị I/O (thường là xem bên dưới).always evaluates the same result value given the same argument value(s). The function result value cannot depend on any hidden information or state that may change while program execution proceeds or between different executions of the program, nor can it depend on any external input from I/O devices (usually—see below).
  2. Đánh giá kết quả không gây ra bất kỳ tác dụng phụ hoặc đầu ra nào có thể quan sát được, chẳng hạn như đột biến của các đối tượng có thể thay đổi hoặc đầu ra cho các thiết bị I/O.does not cause any semantically observable side effect or output, such as mutation of mutable objects or output to I/O devices.

Có các biến toàn cầu đang vi phạm ít nhất một trong những điều ở trên nếu không phải là một mã bên ngoài có thể gây ra kết quả bất ngờ.

Một định nghĩa rõ ràng khác về các chức năng thuần túy: "Chức năng thuần túy là một hàm lấy 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ó làm kết quả rõ ràng." [1]. Có các biến toàn cầu vi phạm ý tưởng về các hàm thuần túy vì đầu vào và có thể một trong các đầu ra (biến toàn cầu) không được cung cấp rõ ràng hoặc trả về.all of its inputs as explicit arguments and produces all of its outputs as explicit results." [1]. Having global variables violates the idea of pure functions since an input and maybe one of the outputs (the global variable) is not explicitly being given or returned.

(Có lẽ) Vi phạm kiểm tra đơn vị F.I.R.S.T Nguyên tắc

Hơn nữa, nếu bạn xem xét kiểm tra đơn vị và nguyên tắc F.I.R.S.T (kiểm tra nhanh, kiểm tra độc lập, lặp lại, tự đánh giá và kịp thời) có thể sẽ vi phạm nguyên tắc kiểm tra độc lập (có nghĩa là các bài kiểm tra không phụ thuộc vào nhau).Fast tests, Independent tests, Repeatable, Self-Validating and Timely) will probably violate the Independent tests principle (which means that tests don't depend on each other).

Có một biến toàn cầu (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 chức năng khác. Điều này vi phạm nguyên tắc này là tốt. Nếu biến toàn cầu đã được sử dụng theo cách đó (tức là biến toàn cầu được sử dụng trong hàm X phải được đặt trong hàm y trước tiên), điều đó có nghĩa là đối với chức năng kiểm tra đơn vị x, bạn phải chạy chức năng kiểm tra/chạy y trước.

Quả cầu là hằng số

Mặt khác và như những người khác đã đề cập, nếu biến toàn cầu được sử dụng làm biến "không đổi" 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ố" với tư cách là thành viên lớp và hoàn toàn không sử dụng biến toàn cầu. Nếu bạn có một mã mà hai lớp khác nhau yêu cầu để chia sẻ một biến toàn cầu thì có lẽ bạn cần phải tái cấu trúc 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 Globals không nên được sử dụng. 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ác nguyên tắc được đề cập ở trên và các nguyên tắc kỹ thuật phần mềm khác và thực tiễn tốt) cho một mã sạch hơn và gần như không có lỗi.

Trước hết, hãy để tôi giải thích rằng tôi hiểu lạm dụng chúng sẽ cắn vào mông bạn và cắn mạnh. Tuy nhiên, ý kiến ​​cộng đồng dường như là bất kỳ việc sử dụng các biến toàn cầu là một điều xấu và tôi đang gặp khó khăn trong việc hiểu được sự ghét bỏ.

Ví dụ, như một bài kiểm tra các kỹ năng lập trình khá mới của tôi, tôi đã làm việc trong một loại trò chơi Battleship của một người chơi. Tất cả đều dựa trên văn bản như tôi chưa học đồ họa, vì vậy bảng của tôi là một mảng các mảng đầy thời gian. Bằng cách sử dụng phương pháp ' '.join(), nó trông tương đối đẹp.

Tuy nhiên, tôi đã xác định board trong main() nhưng sau đó cần nó trong makeShip(), phải lấy bảng, sau đó chỉnh sửa bảng để nó được cập nhật với thông tin của con tàu mới này. Bây giờ, tôi đã làm điều này một thời gian trước, trước khi tôi học được tất cả sự ghét bỏ chống lại các biến toàn cầu. Vì vậy, tôi đã tự nghĩ, "Chà, tôi không thể sử dụng một biến cục bộ trong một chức năng khác, vì vậy hãy để Google 'từ khóa biến toàn cầu Python Python' và xem điều gì sẽ xảy ra."

Bây giờ, tôi chỉ có thể làm:

def makeShip(board, shipLength)
    {calculate where to place ship so it doesn't overlap other ships}
    {place ship on board}
    return board

def main()
    {in the middle of code}
    board = makeShip(board, shipLength)

Điều này là đủ dễ dàng, nhưng điều gì sẽ xảy ra nếu makeShip() yêu cầu nhiều biến để tính toán có bao nhiêu tàu để đặt và ở đâu? Tôi thực sự không muốn chuyển 5 biến cho mọi chức năng ảnh hưởng đến bảng, chỉ vì vậy main()makeShip() có thể "nói chuyện" với nhau, sau đó tôi sẽ kết thúc với makeShip(board, hiddenBoard, shipLength, shipPos, shipNumber, etc). Tôi không thể tạo chúng tại địa phương trong Chúng được tính từ độ khó và kích thước bảng mà người chơi chọn trong

def makeShip(shipLength)
    {place ship on board}

def main()
    {code}
    makeShip(shipLength)
1

Vì vậy, điều gì tồi tệ khi chỉ đơn giản là làm cho board toàn cầu và làm

def makeShip(shipLength)
    {place ship on board}

def main()
    {code}
    makeShip(shipLength)

Ý tôi là, mọi thứ trong chừng mực, phải không? Hay có một sự thay thế khác mà tôi thậm chí không nghĩ/học được?

Tôi cho rằng đó là một trong những điều không ảnh hưởng đến một chương trình nhỏ, một tập tin như thế này, nhưng trở thành một vấn đề lớn khi bạn có hàng tá tệp được làm việc bởi những người khác nhau.

Chỉnh sửa: Từ ngữ và chính tả khác nhau.

Có tệ khi sử dụng các biến toàn cầu không?

Sử dụng các biến toàn cầu gây ra sự kết hợp rất chặt chẽ của mã.Sử dụng các biến toàn cầu gây ô nhiễm không gian tên.Điều này có thể dẫn đến việc chỉ định lại một giá trị toàn cầu không cần thiết.Kiểm tra trong các chương trình sử dụng các biến toàn cầu có thể là một nỗi đau lớn vì rất khó để tách chúng ra khi thử nghiệm.causes very tight coupling of code. Using global variables causes namespace pollution. This may lead to unnecessarily reassigning a global value. Testing in programs using global variables can be a huge pain as it is difficult to decouple them when testing.

Tại sao các biến toàn cầu nên tránh trong Python?

Họ làm cho việc suy luận khó khăn hơn về cách chương trình của bạn hoạt động, vì bất cứ điều gì trong mã của bạn đều có thể thay đổi biến đó.Chúng làm cho việc kiểm tra mã của bạn khó khăn hơn, vì mỗi hàm bây giờ không chỉ phụ thuộc vào các đối số bạn vượt qua mà còn một hoặc nhiều biến toàn cầu.. They make it more difficult to test your code, since each function now depends not only on the arguments you pass it but also one or more global variables.