Skip to main content

Bài 15 - Python Namespace And Scope

I. Giới thiệu

Namespace (không gian tên) và Scope (phạm vi) là hai khái niệm cốt lõi trong Python giúp quản lý việc truy cập biến, hàm, và lớp trong chương trình. Hiểu rõ chúng giúp tránh lỗi và viết mã hiệu quả hơn.

II. Namespace (Không gian tên)

1. Định nghĩa

  • Namespace là hệ thống đặt tên duy nhất cho các đối tượng (biến, hàm, lớp) trong Python.
  • Mỗi namespace là một ánh xạ từ tênđối tượng (như một từ điển).
  • Namespace được tạo tại thời điểm runtime.

2. Phân loại Namespace

Có 3 loại chính:

  • Built-in Namespace:
    Chứa các hàm và biến sẵn có của Python (vd: print(), len()).
    Tồn tại từ khi trình thông dịch khởi động.
  • Global Namespace:
    Chứa các tên được định nghĩa ở cấp module (file .py).
    Tồn tại đến khi chương trình kết thúc.
  • Local Namespace:
    Chứa các tên trong hàm hoặc lớp.
    Tồn tại khi hàm/lớp được gọi và hủy khi kết thúc.

3. Ví dụ

# Built-in namespace: print, len, list, ...
# Global namespace: global_var, outer_func
global_var = 10  # Global namespace
def outer_func():
   outer_var = 20  # Local namespace của outer_func
   
   def inner_func():
       inner_var = 30  # Local namespace của inner_func
       print(inner_var)
   
   inner_func()
outer_func()

III. Scope (Phạm vi)

1. Định nghĩa

  • Scope là vùng mã nơi một namespace có thể được truy cập trực tiếp.
  • Quyết định khả năng "nhìn thấy" của một biến tại vị trí trong code.

2. Quy tắc LEGB

Python tìm kiếm tên theo thứ tự:

  1. L (Local): Trong hàm/lớp hiện tại.
  2. E (Enclosing): Trong hàm bao ngoài (nếu có).
  3. G (Global): Ở cấp module.
  4. B (Built-in): Trong namespace built-in.

3. Các loại Scope

  • Local Scope: Biến trong hàm hiện tại.
  • Enclosing Scope: Biến trong hàm bao ngoài (closure).
  • Global Scope: Biến ở cấp module.
  • Built-in Scope: Biến built-in.

IV. Ví dụ minh họa

1. Cơ bản

x = 10  # Global scope
def foo():
   y = 20  # Local scope
   print(x)  # Tìm thấy x trong global scope
foo()
print(y)  # Lỗi! y không tồn tại trong global scope

2. Enclosing Scope

def outer():
   z = 30  # Enclosing scope
   
   def inner():
       print(z)  # Truy cập z từ enclosing scope
   
   inner()
outer()

3. Global vs Local

counter = 0  # Global
def increment():
   global counter  # Khai báo sử dụng global variable
   counter += 1
increment()
print(counter)  # 1

4. LEGB Rule

name = "Global"  # Global
def outer():
   name = "Enclosing"  # Enclosing
   
   def inner():
       name = "Local"  # Local
       print(name)  # Ưu tiên Local → Output: "Local"
   
   inner()
outer()

V. Lưu ý quan trọng

  1. global keyword:
    Cho phép sửa đổi biến toàn cục trong hàm.

    total = 0
    def update():
       global total
       total = 100
  2. nonlocal keyword:
    Truy cập biến trong enclosing scope (không phải global).

    def outer():
       count = 0
       
       def inner():
           nonlocal count
           count = 10  # Sửa biến của outer()
  3. Biến chỉ đọc trong nested scope:
    Python cho phép đọc biến từ enclosing scope, nhưng nếu gán, nó sẽ tạo biến mới ở local scope (trừ khi dùng nonlocal/global).
  4. Namespace động:
    Có thể kiểm tra namespace bằng:
    • locals(): Trả về dictionary của local namespace.
    • globals(): Trả về dictionary của global namespace.

VI. Bài tập thực hành

Kiểm tra LEGB:
Dự đoán output của đoạn mã sau:

x = 5
def func1():
   x = 10
   def func2():
       print(x)
   func2()
func1()  # Output?

Giải thích:
Hàm func2 tìm x theo LEGB:

  • Local (func2): ❌
  • Enclosing (func1): ✅ x=10 → Output: 10

Tổng kết

Khái niệmMô tả
NamespaceHệ thống quản lý tên → đối tượng (Built-in/Global/Local)
ScopeVùng mã nơi namespace được truy cập trực tiếp (LEGB)
globalChỉ định sử dụng biến toàn cục trong hàm
nonlocalChỉ định sử dụng biến từ enclosing scope (closure)

Hiểu rõ Namespace và Scope giúp tránh lỗi logic về biến, quản lý bộ nhớ hiệu quả và thiết kế chương trình rõ ràng!