Phạm vi trong python

Không gian tên là hệ thống có một tên duy nhất cho mỗi đối tượng trong Python. Một đối tượng có thể là một biến hoặc một phương thức. Bản thân Python duy trì một không gian tên dưới dạng từ điển (dictionary) trong Python. Vui lòng xem xét một ví dụ về tệp hệ thống cấu trúc trong thư mục của máy tính

Như chúng ta đã biết, có thể có nhiều thư mục có một tệp cùng tên bên trong mỗi thư mục. Nhưng người ta có thể trỏ tới tệp đó chỉ bằng một đường dẫn tuyệt đối cho tệp

Ví dụ thực tế, vai trò của một không gian tên giống như họ tên của cái gì đó. Có thể không tìm thấy tên “Cafedev” nào trong lớp nếu có rất nhiều tên “Cafedev”, nhưng khi bạn yêu cầu cụ thể về “Cafedev Share” hoặc “Cafedev iOS” (với tên cụ thể của họ), thì lúc này

Trên các dòng mã, trình thông dịch Python hiểu biến chính hoặc phương thức nào đang được cố gắng chỉ đến trong mã, tùy thuộc vào không gian tên. Vì vậy, việc phân nhỏ các từ (tên) sẽ cung cấp thêm thông tin. With Name of it (có nghĩa là tên, định danh duy nhất) + Space (liên quan đến phạm vi). Ở đây, một tên có thể là của bất kỳ phương thức hoặc biến nào trong Python và không gian phụ thuộc vào vị trí mà người ta đang cố gắng truy cập vào một biến hoặc một phương thức

2. Các loại không gian tên

Khi trình thông dịch Python chạy độc lập mà không có mô-đun, phương thức và lớp do người dùng định nghĩa, v. v thì một số hàm như print(), id() luôn xuất hiện, chúng được khai triển trong các namespace. Khi người dùng tạo một mô-đun, một không gian tên toàn cục sẽ được khởi động, việc tạo các hàm cục bộ sau đó sẽ tạo ra một vùng tên cục bộ. Không gian tên tích hợp sẵn bao gồm không gian tên toàn cục bộ và không gian tên toàn cục bộ bao gồm các không gian tên cục bộ

Phạm vi trong python

3. Thời gian tồn tại của một không gian tên

Thời gian tồn tại của một không gian tên phụ thuộc vào phạm vi của các đối tượng, nếu phạm vi của một đối tượng kết thúc, thời gian tồn tại của không gian tên đó cũng kết thúc. Do đó, không thể truy cập các đối tượng bên trong không gian tên từ một không gian tên bên ngoài

Ví dụ


# var1 is in the global namespace  
var1 = 5
def some_func(): 
  
    # var2 is in the local namespace  
    var2 = 6
    def some_inner_func(): 
  
        # var3 is in the nested local  
        # namespace 
        var3 = 7

Như có thể xuất hiện trong hình bên dưới, một đối tượng tên có thể cùng xuất hiện trong nhiều không gian tên vì sự phân tách giữa các không gian tên của chúng

Phạm vi trong python

Như có thể xuất hiện trong hình bên dưới, một đối tượng tên có thể cùng xuất hiện trong nhiều không gian tên vì sự phân tách giữa các không gian tên của chúng

Nhưng trong một số trường hợp, người ta chỉ quan tâm đến việc cập nhật hoặc xử lý biến toàn cục, chẳng hạn như trong ví dụ sau, người ta đánh dấu nó rõ ràng biến toàn cục và cập nhật xử lý hoặc xử lý chúng


# Python program processing 
# global variable 
  
count = 5
def some_method(): 
    global count 
    count = count + 1
    print(count) 
some_method() 

Kết quả

6

4. Phạm vi của các đối tượng trong Python

Phạm vi đề cập đến mã vùng mà từ đối tượng đó trong Python có thể truy cập được. Do đó, người ta không thể truy cập bất kỳ đối tượng cụ thể nào từ bất kỳ nơi nào trong mã, việc truy cập phải được cho phép theo phạm vi của đối tượng

Hãy lấy một ví dụ để hiểu sự giống nhau chi tiết hơn

Ví dụ 1


# Python program showing 
# a scope of object 
  
def some_func(): 
    print("Inside some_func") 
    def some_inner_func(): 
        var = 10
        print("Inside inner function, value of var:",var) 
    some_inner_func() 
    print("Try printing var from outer function: ",var) 
some_func() 

Kết quả

Inside some_func
Inside inner function, value of var: 10

Traceback (most recent call last):
  File "/home/1eb47bb3eac2fa36d6bfe5d349dfcb84.py", line 8, in 
    some_func()
  File "/home/1eb47bb3eac2fa36d6bfe5d349dfcb84.py", line 7, in some_func
    print("Try printing var from outer function: ",var)
NameError: name 'var' is not defined

Trọn bộ tự học Python từ cơ bản tăng cao tại đây nha

Nếu thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa

Khi mình ngồi học và dịch bài "Lớp Trăn" cho sê-ri "Khám Phá Đại Bản Doanh Trăn", mình đụng hai bạn này, và các bạn thật là vật và khó nhai. Thế là mình search và viết bài này để hiểu rõ hơn về hai bạn ấy, hi vọng bạn đọc thêm để hiểu về Python nhé

Không gian tên là gì?

No namespace(namespace) is a notgian Chứa các tên =))

Thật vậy, tên là các danh sách, và không gian là cấu trúc hay các tổ chức, hay hiểu đơn giản nó là một vùng nào đó

Không gian tên trong Python giống như bảng phân công theo dõi công việc của một nhóm người vậy đó. Bảng phân tích thì theo dõi tên người, còn tên không gian trong Python thì theo dõi tên các đối tượng

Thế đối tượng trong Python là gì nhỉ?

Có thể bạn đã biết, mọi thứ trong Python đều là đối tượng. Khi mình viết chương trình Python, chúng ta định nghĩa các lớp và mô-đun; . Tất cả bọn họ đều là đối tượng của cả họ

Không gian tên trong Python thì theo dõi tên các đối tượng, giả sử các giới hạn như khả năng thực thi của đối tượng và các hàm chức năng. Dưới đây là một số điểm đặc biệt quan trọng của khái niệm này

Unable to expand name in dictionary format

Bởi vì tên không thể hiện ánh xạ giữa tên và đối tượng, do đó kiểu dữ liệu có thể hiển thị tham chiếu này chính là từ điển(dict), bởi vì bạn cũng có dạng tham chiếu khóa-giá trị

Ví dụ về không gian tên bằng cách gọi hàm globals(),locals()

>>> a = [1, 2, 3, 4, 5]
>>> 
>>> def foo():
...     b = 11
...     print(locals())
... 
>>> class Student:
...     pass
... 
>>> student = Student()
>>> print(globals())
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'a': [1, 2, 3, 4, 5], 'b': 'Hello World!', 'foo': <function foo at 0x101fd93b0>, 'foo0': <function foo at 0x10200c7a0>, 'foo1': <function foo at 0x10200c7a0>, 'tracked_namespaces': {'local': {}}, 'tracked_keys': dict_keys(['local']), 'ns': <module 'namespaces_student' from '/Users/ycui/PythonProjects/namespaces_student.py'>, 'working_hard': True, 'Student': <class '__main__.Student'>, 'Teacher': <class 'namespaces_teacher.Teacher'>, 'student': <__main__.Student object at 0x102027490>}
>>> foo()
{'b': 11}

Globals() build function dùng để xem các danh sách đi kèm với các đối tượng tương ứng của main trong thời gian không hiện tại. Kết quả là danh sách các đối tượng được định nghĩa như danh sách, hàm, lớp hay thực thể và các hàm xây dựng sẵn

Bên cạnh Globals() được sử dụng để theo dõi các đối tượng trong mô-đun như không gian tên toàn cục như trên, chúng ta còn có thể sử dụng locals() là hàm theo dõi các đối tượng trong một hàm nào đó như vậy . Trong ví dụ, biến địa phương b được theo dõi trong khoảng thời gian tên địa phương của hàm foo

Uninstall name has an active

Unabled name to follow the objects

Trong mã Python, chúng ta tạo ra các đối tượng cố định và xóa các đối tượng không còn được sử dụng nữa, do đó không gian tên cũng sẽ thay đổi theo dựa trên các thao tác này

Cùng xem ví dụ khi thực hiện thao tác bổ sung và xóa các thuộc tính sẽ làm thay đổi không gian tên

>>> a = [1, 2, 3, 4, 5]
>>> print(globals().keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'a'])
>>> b, c = 'Hi', (1, 2)
>>> print(globals().keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'a', 'b', 'c'])
>>> del c
>>> print(globals().keys())
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', 'a', 'b'])

Khi một chức năng được gọi, nó tạo ra một bộ không gian cục bộ tên, và không gian tên này sẽ mất đi khi chức năng hoàn thành nhiệm vụ của mình (trả về giá trị hoặc tăng lỗi). Khi đó, tên không gian cũng sẽ bị thay thế

Phạm vi là hàng rào của không gian tên

Để dễ hình dung, bạn có thể nghĩ đến phạm vi như là hàng rào xung quanh nhà bạn, còn namespace là toàn bộ đất trong đó, và trên đất có thể bao gồm cây cối, nhà cửa,. is the object

Phạm vi trong python

Bạn thấy không, không gian tên theo dõi các đối tượng trong mô-đun này, vì đám này nằm trong không gian của nó, còn phạm vi chính là đường màu cam có thể hiện hàng rào bọc bên ngoài không gian tên này

Nói cách khác, nếu mình muốn sử dụng attr0 nằm trong mô-đun ở trên một hàm “bo” chẳng hạn, nếu hàm này không thể truy cập phạm vi vào vi này thì không thể sử dụng biến đó được.

Cùng xem một ví dụ nhé

This is code in file namespace_student. py

working_hard = True

class Student:
   def study(self):
      print("I'm studing.")

Truy cập vào biên dịch PI biên dịch

________số 8

Khi mình làm việc trong PI, mô-đun mặc định ở đây là chính, nơi không gian tên có __main__ là giá trị của


# Python program processing 
# global variable 
  
count = 5
def some_method(): 
    global count 
    count = count + 1
    print(count) 
some_method() 
0

Dòng đầu in, mình không truy cập được vào biến working_hard vì bọn mình không đứng trong module namespace_student. Tuy nhiên, sau khi mình nạp mô-đun này vào, thì mình có thể truy cập tên này không thông qua tên mô-đun của nó vì ns đã thuộc về không gian tên nơi mình đang đứng (chính). Mình có thể kiểm tra điều đó bằng chức năng không gian tên toàn cầu như ở trên

Vì mình có thể sử dụng tên của mô-đun để truy cập vào các thuộc tính trong đó, nên ở các mô-đun khác nhau hoàn toàn có thể chứa các tên giống nhau

Bạn có thể cấu hình nó kiểu như là nhà mình có một cái macbook, nhà hàng xóm cũng có một cái macbook y như vậy, thì hai cái macbook này mình có thể hoàn toàn phân biệt được đúng không nào 😀

Phạm vi trong python

Không gian tên và phạm vi phân cấp đều

Bạn có để ý thấy chỉ cần truy cập vào biên dịch là mình có thể sử dụng các hàm dựng sẵn của Python như print() hay các kiểu dữ liệu như dict(), list()

Vậy các bạn này từ đâu ra thế nhỉ ?

Ngoài ra, khi tạo một mô-đun mô-đun, ta sẽ không có khoảng thời gian tên toàn cục bộ (toàn cục) của mô-đun đó, khi tạo một hàm mình sẽ không có khoảng thời gian tên cục bộ (cục bộ) của hàm đó. Khi các tên không gian được tạo ra thì các phạm vi tương ứng của chúng cũng được tạo ra

Đặc điểm quan trọng của tên không gian là chúng có mối quan hệ phân cấp như vậy

Biểu đồ dưới đây có thể thực hiện sự phân cấp này. không gian tên và phạm vi hiển thị bao trùm không gian tên và phạm vi toàn cục, và lớp này bao trùm không gian tên và phạm vi bộ

Phạm vi trong python

Hiểu luật LEGB

Vì việc xác định việc có thể truy cập các đối tượng trong một ranh giới nhất định và chúng có tính phân cấp như trên, những điều này dẫn đến việc chúng cần hiểu và nắm luật LEGB – một nguyên tắc giúp xác định phạm vi thứ tự

LEGB là bản tắc của các phạm vi cục bộ, kèm theo, toàn cầu và tích hợp

Ở trên, mình có đề cập đến các loại phạm vi. cục bộ, toàn cầu, tích hợp sẵn rồi. Thế còn phạm vi bao quanh(bao quanh) nghĩa là gì nhỉ?

Cùng nhìn ví dụ sau về phạm vi bao quanh nha

Phạm vi trong python

Ở ví dụ trên, mình có hàm outside_function có hàm bên trong là inner_function, hàm này có phạm vi cục bộ của riêng nó. With inner_function, range of outside_function function call is range phạm vi bao quanh(enclosing scope), tức nó luôn luôn bao quanh hàm trong

Do đó khi hàm inner_function được gọi, mặc dù phạm vi cục bộ của nó không có hai biến a, b, nhưng trình dịch tiếp tục tìm kiếm ở phạm vi kèm theo và tìm được hai biến này, do đó kết quả trên biến được hiển thị ba biến a

Nếu không thể tìm thấy biến cần tìm không có phạm vi kèm theo, chương trình sẽ tiếp tục tìm kiếm ở phạm vi toàn cầu của mô-đun và nếu không có nữa sẽ tìm kiếm ở phạm vi tích hợp

Nếu tìm thấy hết bốn phạm vi mà vẫn không tìm thấy thì chương trình sẽ báo lỗi NameError để chỉ cho mình biết giá trị này chưa được định nghĩa

Do đó, nguyên tắc LEGB định nghĩa thứ tự tìm kiếm của tên theo thứ tự như sau

Phạm vi trong python

Và thêm nữa, nếu tên đã được tìm kiếm ở cấp nào rồi, thì chương trình sẽ dừng việc tìm kiếm lại và sử dụng tên đó chứ không phải đi tìm ở những lớp trên nữa nha, tìm vì ra rồi thì dùng liền liền hỉ.

Ví dụ như ở trên một biến gọi trong hàm inner_function sẽ có giá trị là 11, chứ chương trình không tìm thấy cấp ở bên ngoài, nơi a có giá trị là 1 đó