Khai báo biến trong vòng lặp python

Trong chương 18, “Hàm Python”, chúng ta đã học được rằng một hàm chỉ nên sử dụng các biến đã được xác định trong khối của hàm hoặc được truyền rõ ràng dưới dạng tham số (Quy tắc 1). Quy tắc này hoạt động chặt chẽ với định nghĩa của chúng tôi về một biến trong Python, như một cái tên đề cập đến một số dữ liệu

Đây là một khái niệm mạnh mẽ, cho phép chúng ta truyền tham số cho hàm và nhận giá trị trả về. Trong Python, một phần dữ liệu có thể được tham chiếu bởi nhiều biến. Các biến tham số là tên mới cho cùng một dữ liệu. Chúng ta có thể khám phá khái niệm này bằng một ví dụ đơn giản

Khai báo biến trong vòng lặp python

Trong mẫu mã này, chúng tôi đã tạo một danh sách duy nhất, nhưng chúng tôi đang liên kết hai tên biến với nó, numsnumsb. Khi chúng tôi sửa đổi danh sách thông qua một tên, thay đổi được phản ánh qua tên kia (chúng tôi chỉ có thể thay đổi dữ liệu vì danh sách có thể thay đổi, nhưng ngay cả dữ liệu không thay đổi cũng có thể được gọi bằng nhiều tên)

Điều tương tự cũng xảy ra khi chúng ta sử dụng một tham số trong một hàm. Hãy xem lại hàm gc_content(), sử dụng hàm base_composition() mà chúng ta đã viết (nhưng bỏ qua ở đây cho rõ ràng). Trong danh sách này, tất cả các tên biến thuộc về hàm được đánh dấu bằng màu đỏ, trong khi các tên biến “toàn cầu” khác được đánh dấu bằng màu tím và được gạch chân bằng đường đứt nét. Theo Quy tắc 1, chúng ta sẽ không thấy bất kỳ biến màu tím/gạch chân nào trong định nghĩa hàm

Khai báo biến trong vòng lặp python
Khai báo biến trong vòng lặp python

Bên ngoài hàm, chuỗi dữ liệu "ACCCTAGACTG" được gán cho biến seq3, nhưng bên trong hàm, nó được gán cho biến seq. Bên trong hàm, giá trị dữ liệu 0.54 được tham chiếu bởi biến gc và bên ngoài nó được tham chiếu bởi seq3_gc

Chúng tôi biết rằng chúng tôi có thể truy cập biến seq3 từ bên trong hàm, ngay cả khi chúng tôi không nên. Nhưng còn chiều ngược lại thì sao?

Khai báo biến trong vòng lặp python

Trên thực tế, chúng ta không thể. Dòng numsb2 ở trên, ngay cả sau khi tính toán seq3_gc, sẽ tạo ra một numsb4. Lỗi này xảy ra do các biến có phạm vi và phạm vi của biến gc bị giới hạn, từ thời điểm nó được xác định cho đến khi kết thúc khối chức năng mà nó được xác định (tất cả các biến được đánh dấu màu đỏ đều có đặc điểm này). Các biến có phạm vi giới hạn được gọi là biến cục bộ. Phạm vi của một biến là bối cảnh trong đó có thể được sử dụng. Nó định nghĩa “biến tồn tại bao lâu” hoặc “biến tồn tại ở đâu. ” Một biến có phạm vi giới hạn, như trong quá trình thực thi một hàm, được gọi là biến cục bộ

Sau khi lệnh gọi hàm kết thúc, hình ảnh sẽ giống như vậy

Khai báo biến trong vòng lặp python

Cuối cùng, bộ thu gom rác sẽ nhận thấy rằng không có biến nào tham chiếu đến dữ liệu numsb6, numsb7 và numsb8 và nó sẽ xóa những biến đó khỏi RAM để nhường chỗ cho dữ liệu mới

Bởi vì phạm vi nói về các biến, nó ít liên quan đến dữ liệu mà một biến đề cập đến—ngoại trừ việc nói rằng dữ liệu được thu thập rác khi không có biến nào đề cập đến dữ liệu đó trong bất kỳ phạm vi hiện tại nào. Tuy nhiên, vì biến gc không nằm trong phạm vi sau khi chức năng kết thúc, nên chúng tôi không thể sử dụng nó bên ngoài khối chức năng

Một trong những tính năng đặc biệt thú vị và mạnh mẽ của các biến cục bộ là chúng tồn tại độc lập với bất kỳ biến nào khác có thể tồn tại cùng tên vào thời điểm đó (đôi khi chúng được cho là “che khuất” các biến khác có cùng tên). Hãy xem xét đoạn mã sau

Khai báo biến trong vòng lặp python

Bạn nghĩ dòng cuối cùng, numsb2, sẽ in gì? . Mặc dù hàm gc_content() định nghĩa biến gc của chính nó, nhưng vì biến này là cục bộ nên nó không “đè” lên biến gc bên ngoài. Tóm tắt

  • Các biến được xác định trong một hàm (và các tham số cho một hàm) là cục bộ của lệnh gọi hàm
  • Các biến cục bộ này “bóng tối” bất kỳ biến nào khác có thể tồn tại trong quá trình thực thi hàm
  • Khi lời gọi hàm kết thúc, các biến cục bộ sẽ bị quên

Một trong những bài học quan trọng về phạm vi là biết khi nào nó có thể dẫn đến rắc rối. Điều này dễ thấy nhất nếu chúng ta so sánh cách phạm vi hoạt động với một ngôn ngữ khác, trong trường hợp này là C++. Trong C++, các biến được khai báo với kiểu của chúng và các biến được khai báo trong khối câu lệnh if (hoặc bất kỳ khối nào khác) cũng là cục bộ của khối đó. Điều này có nghĩa là chúng vượt ra ngoài phạm vi khi khối kết thúc. Nếu chúng ta thử và sử dụng chúng bên ngoài khối mà chúng được khai báo, sẽ xảy ra lỗi

Mặt khác, trong Python, các biến được khai báo trong câu lệnh if, khối vòng lặp for và khối vòng lặp while không phải là biến cục bộ và nằm trong phạm vi bên ngoài khối. Do đó, chúng tôi nói rằng C ++ có phạm vi "cấp khối", trong khi Python chỉ sử dụng phạm vi "cấp chức năng". Các dấu ngoặc trong hình bên dưới minh họa phạm vi cho một số biến trong mã C++ và Python tương đương. Vì C++ sử dụng phạm vi cấp khối và gc_content()5 và gc_content()6 được khai báo bên trong các khối, chúng tôi không thể truy cập nội dung của chúng bên ngoài các khối đó

Khai báo biến trong vòng lặp python

Điều này có vẻ như là một lợi thế cho Python, nhưng trong trường hợp này, chúng tôi nghĩ rằng C ++ có thể đúng. Xét cho cùng, nếu chúng ta cần các biến gc_content()6 và gc_content()8 có thể truy cập được sau các khối if trong ví dụ C++, chúng ta có thể khai báo chúng cùng với gc_content()5. Chúng tôi thậm chí có thể đã cung cấp cho chúng một giá trị mặc định để giữ bằng cách sử dụng các khai báo như base_composition()0 và base_composition()1; . Điều này sẽ đặc biệt hữu ích nếu giá trị của gc_content()5 không được đặt thành 5 như ở đây, mà phụ thuộc vào dữ liệu đầu vào

Mặt khác, trong Python, mã như thế này có thể gây ra sự cố. Nếu biến gc_content()5 phụ thuộc vào dữ liệu đầu vào, thì các biến gc_content()6 và gc_content()8 có thể không bao giờ được đặt, dẫn đến một biến base_composition()7 cuối cùng khi chúng được truy cập sau đó. Chúng tôi chắc chắn không nên coi bất kỳ chương trình nào đôi khi tạo ra lỗi, tùy thuộc vào dữ liệu đầu vào, là rất tốt

Có lẽ cách tốt nhất để giải quyết loại vấn đề này là giả sử rằng Python sử dụng phạm vi cấp độ khối, khai báo các biến trong khối/cấp độ rộng nhất mà chúng sẽ được sử dụng. base_composition()8 là một giá trị mặc định tốt mà sau này chúng ta có thể kiểm tra nếu chúng ta muốn thực thi mã sau này một cách có điều kiện trên cơ sở liệu các biến có thực sự được đặt thành thứ gì đó hữu ích hay không

Khai báo biến trong vòng lặp python

Mã này sẽ không bị lỗi, bất kể giá trị của gc_content()5 là bao nhiêu. Việc đặt các giá trị ban đầu cho các biến này thành base_composition()8 trước các khối if cũng cung cấp lời nhắc và gợi ý trực quan rằng các biến này dự định sẽ được sử dụng bên ngoài các khối if lồng nhau và chúng ta nên kiểm tra nội dung của chúng trước khi sử dụng chúng sau này.

Do đó, C ++ và các ngôn ngữ có phạm vi cấp khối khác khuyến khích các biến "tồn tại trong thời gian ngắn", đây là một câu thần chú lập trình tốt. Chỉ xác định các biến khi cần thiết và sử dụng chúng trong thời gian ngắn nhất có thể giúp tạo ra mã rõ ràng hơn, mô-đun hơn và thậm chí hiệu quả hơn (vì các biến tồn tại trong thời gian ngắn cho phép trình thu gom rác dọn sạch nhiều dữ liệu hơn). Theo một cách nào đó, việc phá vỡ Quy tắc 1 của các hàm là một kiểu lạm dụng phạm vi biến tương tự

Khai báo biến trong vòng lặp python

Các lập trình viên mới bắt đầu thường thấy dễ dàng hơn để tránh các quy ước này bằng cách đặt một số lượng lớn các biến gần đầu chương trình, sau đó truy cập và đặt chúng ở các điểm khác nhau trong suốt chương trình. Điều này đôi khi được gọi một cách thông tục là “mã spaghetti”, bởi vì các kết nối khoảng cách xa được tạo giữa các vùng mã khác nhau giống như mì spaghetti. Tuy nhiên, hiếm khi chiến lược này được đền đáp

Như đã thảo luận trong chương 25, “Thuật toán và cấu trúc dữ liệu”, các biến cục bộ và các khái niệm tương tự cho phép chúng ta giải quyết các vấn đề phức tạp theo những cách hấp dẫn và tao nhã

Chúng ta có thể định nghĩa một biến trong for

Trong mỗi bước lặp, một biến vòng lặp được đặt thành một giá trị trong một chuỗi hoặc bộ sưu tập dữ liệu khác . Loại vòng lặp for này được biết đến trong hầu hết các shell Unix và Linux và nó là loại vòng lặp được triển khai trong Python.

Bạn có thể khai báo biến trong vòng lặp không?

Việc xác định một biến trong vòng lặp không phải là vấn đề . Trên thực tế, đó là một cách làm tốt, vì số nhận dạng nên được giới hạn trong phạm vi nhỏ nhất có thể. Điều tồi tệ là gán một biến trong một vòng lặp nếu bạn cũng có thể chỉ định nó một lần trước khi vòng lặp chạy.

Tôi nên khai báo biến trong vòng lặp hay bên ngoài?

Nếu biến được khai báo bên ngoài vòng lặp, thì nó có phạm vi toàn cầu vì nó có thể được sử dụng xuyên suốt hàm và cả bên trong vòng lặp . Nếu biến được khai báo bên trong vòng lặp thì phạm vi chỉ có giá trị bên trong vòng lặp và nếu sử dụng bên ngoài vòng lặp sẽ báo lỗi.

Điều gì xảy ra với các biến được khai báo trong vòng lặp?

Nếu một biến được khai báo bên trong một vòng lặp, JavaScript sẽ cấp phát bộ nhớ mới cho biến đó trong mỗi lần lặp lại , ngay cả khi các cấp phát cũ hơn vẫn sẽ sử dụng . Mặc dù điều này có thể được chấp nhận đối với các biến của kiểu dữ liệu vô hướng, nhưng nó có thể phân bổ nhiều bộ nhớ cho các biến SCFile hoặc các mảng hoặc đối tượng lớn.