Phạm vi của biến – Python Variables Scope
Việc khai báo và sử dụng biến là một trong những vấn đề rất cơ bản nhưng hay gặp phải lỗi trong quá trình phát triển. Hôm nay chúng ta sẽ cùng nhau tìm hiểu về phạm vi của biến trong Python.
Python có 3 phạm vi (scope) của biến:
- Local scope
- Global scope
- Enclosing scope
Nội dung của bài
Local scope (Biến cục bộ)
Một biến được khai báo bên trong một hàm (xem bài hàm trong Python) thì phạm vi của biến là local scope. Biến được sử dụng trong nội tại hàm, và tồn tài khi hàm thực thi.
def myfunc():
x = 100 # local scope x
print(x)
myfunc() # prints 100
Biến cục bộ được giải phóng khỏi bộ nhớ khi kết thúc lời gọi hàm.
Global scope (Biến toàn cục)
Biến toàn cục được khai báo bên ngoài tất cả các hàm, trong file code. Phạm vi của biến toàn cục là trong tòa bộ file code.
x = 100 # global scope x
def myfunc():
print(x) # giá trị của x là 100 bên trong hàm myfunc
myfunc()
print(x) # giá trị của x là 100 bên ngoài hàm myfunc
Nếu trong hàm chúng ta khai báo biến cục bộ trùng tên với biến toàn cục thì hệ thống sẽ sử dụng biến cụ bộ.
x = 100 # global scope x
def myfunc():
x= 200 # local scope x
print(x) # giá trị của x là 200 bên trong hàm myfunc
myfunc()
print(x) # giá trị của x là 100 bên ngoài hàm myfunc
Khi muốn thay đổi giá trị của biến toàn cục bên trong lời gọi hàm, chúng ta sử dụng từ khóa global trước biến:
x = 100 # global scope x
def myfunc():
global x
x = 200
print(x) # giá trị của x là 200 bên trong hàm myfunc
myfunc()
print(x) # giá trị của x là 200 bên ngoài hàm myfunc
Enclosing Scope
Enclosing function là hàm mà bên trong nó chứa một hàm khác (nested functions).
Khi chúng ta khai báo một biến bên trong Enclosing function thì biến này không có hiêu lực bên trong hàm nested functions.
# enclosing function
def f1():
x = 42
# nested function
def f2():
x = 0
print(x) # x có giá trị 0
f2()
print(x) # x vẫn có giá trị 42
f1()
Biến x không thay đổi giá trị sau lời gọi hàm f2(), vì bản chất hệ thống sẽ khởi tạo bộ nhớ mới cho biến x bên trong hàm f2(). Muốn thay đội giá trị trong quá trình xử lý logic của hàm 2 chúng ta sử dụng từ khóa nonlocal trước biến x:
# enclosing function
def f1():
x = 42
# nested function
def f2():
nonlocal x
x = 0
print(x) # x is now 0
f2()
print(x) # x có giá trị mới là 0
f1()
Biến x lúc này đã ánh xạ đến biến x bên ngoài hàm f2(), và khi chúng ta thay đổi giá trị của x thì giá trị của x bên ngoài hàm f2() cũng được cập nhật.
Scoping Rule – LEGB Rule
Khi một biến được tham chiếu ( được sử dụng trong một logic nào đó) Python sẽ tuân theo LEGB rule với 4 phạm vi của biến theo mức độ:
L phạm vi là biến cụ bộ – Local Scope.
E tiếp theo là biến cục bộ trong các enclosing function and lambdas – (Enclosing Scope).
G Tiếp theo là biến toàn cục – Global scope.
B Cuối cùng là biến có sẵn trong Python – Built-in.
Kết luận
Hiểu rõ về phạm vi của biến giúp chúng ta xây dựng chương trình tối ưu và tránh gặp phải những lỗi cơ bản.