Hướng dẫn global scope trong python

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

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.

Hướng dẫn global scope trong python
Scoping Rule – LEGB Rule

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.

Bài viết được sự cho phép của tác giả Nguyễn Chí Thức

Trong bài Python này bạn sẽ học về biến toàn cục (global), biến cục bộ (local), biến nonlocal trong Python và trường hợp sử dụng các biến này.

Trong ngôn ngữ lập trình Python, một biến được khai báo bên ngoài hàm hoặc trong phạm vi toàn cục được gọi là biến toàn cục hay biến global. Biến toàn cục có thể được truy cập từ bên trong hoặc bên ngoài hàm.

Hướng dẫn global scope trong python

Tuyển dụng lập trình python

Hãy xem ví dụ về cách tạo biến toàn cục trong Python.

x = "Biến toàn cục" #khai báo biến x
#Gọi x từ trong hàm vidu()
def vidu():
    print("x trong hàm vidu() :", x)

vidu()
#Gọi x ngoài hàm vidu()
print("x ngoài hàm vidu():", x)

Trong ví dụ trên, ta khai báo biến x là biến toàn cục, và định nghĩa hàm vidu() để in biến x. Cuối cùng ta gọi hàm vidu() để in giá trị của biến x. Chạy code trên ta sẽ được kết quả là:

x trong hàm vidu(): Biến toàn cục
x ngoài hàm vidu(): Biến toàn cục

Chuyện gì sẽ xảy ra nếu bạn thay đổi giá trị của x trong hàm?

x = 2 
def vidu():
   x=x*2    
   print(x)

vidu()

Nếu chạy code này bạn sẽ nhận được thông báo lỗi:

UnboundLocalError: local variable 'x' referenced before assignment

Lỗi này xuất hiện là do Python xử lý x như một biến cục bộ và x không được định nghĩa trong vidu().

Để thay đổi biến toàn cục trong một hàm bạn sẽ phải sử dụng từ khóa global. Chúng tôi sẽ nói kỹ hơn trong bài về từ khóa global.

Biến cục bộ trong Python

Biến được khai báo bên trong một hàm hoặc trong phạm vi cục bộ được gọi là biến cục bộ hay biến local.

def vidu():
 y = "Biến cục bộ"
vidu()
print(y)

Khi chạy code trên bạn sẽ nhận được thông báo lỗi:

NameError: name 'y' is not defined

Lỗi này xuất hiện là do chúng ta đã cố truy cập vào biến cục bộ y trong phạm vi toàn cục, nhưng y chỉ làm việc trong hàm vidu() hoặc phạm vi cục bộ.

Thông thường, để tạo một biến cục bộ, chúng ta sẽ khai báo nó trong một hàm như ví dụ dưới đây:

def vidu():
 y = "Biến cục bộ"
 print(y)
vidu()

Chạy code trên ta sẽ được kết quả

Biến cục bộ

Chúng ta quay trở lại xem xét vấn đề trước đó, lúc x là một biến toàn cục và chúng ta muốn thay đổi x trong vidu().

Biến cục bộ và biến toàn cục

Ở đây, chúng ta sẽ học cách dùng biến cục bộ và toàn cục trong cùng một code.

x = 2

def vidu():
 global x
 y = "Biến cục bộ"
 x = x * 2
 print(x)
 print(y)
#Viết bởi uCode.vn 
vidu()

Chạy code trên ta sẽ có đầu ra:

4
Biến cục bộ

Trong code trên, chúng ta khai báo x là biến toàn cục và y là biến cục bộ trong vidu() và dùng toán tử * để thay đổi biến toàn cục và in cả giá trị của x và y. Sau khi gọi hàm vidu() giá trị của x sẽ thành 4 vì được nhân đôi.

Ví dụ sử dụng biến toàn cục và cục bộ trùng tên:

x = 5

def vidu():
 x = 10
 print("Biến x cục bộ:", x)

vidu()
print("Biến x toàn cục:", x)

Sau khi chạy code trên ta có đầu ra:

Biến x cục bộ: 10
Biến x toàn cục: 5

Trong code trên, chúng ta sử dụng cùng tên x cho cả biến cục bộ và biến toàn cục. Khi in cùng biến x chúng ta nhận được hai kết quả khác nhau vì biến được khai báo ở cả hai phạm vi, cục bộ (bên trong hàm vidu()) và toàn cục (bên ngoài hàm vidu()).

Khi chúng ta in biến trong hàm vidu() nó sẽ xuất ra Biến x cục bộ: 10, đây được gọi là phạm vi cục bộ của biến. Tương tự khi ta in biến bên ngoài hàm vidu() sẽ cho ra Biến x toàn cục: 5, đây là phạm vi toàn cục của biến.

Biến nonlocal trong Python

Từ nonlocal này mình không biết dịch sang tiếng Việt sao cho chuẩn. Trong Python, biến nonlocal được sử dụng trong hàm lồng nhau nơi mà phạm vi cục bộ không được định nghĩa. Nói dễ hiểu thì biến nonlocal không phải biến local, không phải biến global, bạn khai báo một biến là nonlocal khi muốn sử dụng nó ở phạm vi rộng hơn local, nhưng chưa đến mức global.

Để khai báo biến nonlocal ta cần dùng đến từ khóa nonlocal.

Ví dụ:

def ham_ngoai():
    x = "Biến cục bộ"
 
    def ham_trong():
       nonlocal x
       x = "Biến nonlocal"
       print("Bên trong:", x)
 
    ham_trong()
    print("Bên ngoài:", x)

hamngoai()

Chạy code trên bạn sẽ có đầu ra:

Bên trong: Biến nonlocal
Bên ngoài: Biến nonlocal

Trong code trên có một hàm lồng là ham_trong(), ta dùng từ khóa nonlocal để tạo biến nonlocal. Hàm ham_trong() được định nghĩa trong phạm vi của ham_ngoai().

Lưu ý: Nếu chúng ta thay đổi giá trị của biến nonlocal, sự thay đổi sẽ xuất hiện trong biến cục bộ.

Bài viết gốc được đăng tải tại ucode.vn

Có thể bạn quan tâm:

  • Giới thiệu IDE phổ biến trong lập trình Python
  • 43 kho lưu trữ Github JS phổ biến nhất 2019 –  Bạn đã biết hết chưa?
  • Sử dụng biến trong CSS toàn tập

Xem thêm các việc làm công nghệ thông tin hấp dẫn tại TopDev