Sự khác nhau giữa là gì globals(), locals()và vars()? Họ trở về làm gì? Là cập nhật cho kết quả hữu ích?
Sự khác nhau giữa là gì globals(), locals()và vars()? Họ trở về làm gì? Là cập nhật cho kết quả hữu ích?
Câu trả lời:
Mỗi trong số này trả về một từ điển:
globals() luôn trả về từ điển của không gian tên mô-đunlocals() luôn trả về một từ điển của không gian tên hiện tạivars()lợi nhuận hoặc là một từ điển của không gian tên hiện tại (nếu gọi mà không có đối số) hoặc các từ điển của các đối số.localsvà varscó thể sử dụng một số giải thích thêm. Nếu locals()được gọi bên trong một hàm, nó cập nhật một dict với các giá trị của không gian tên biến cục bộ hiện tại (cộng với bất kỳ biến đóng) nào tại thời điểm đó và trả về nó. Nhiều lệnh gọi locals()trong cùng một khung ngăn xếp trả về cùng một lệnh mỗi lần - nó được gắn vào đối tượng khung ngăn xếp làm f_localsthuộc tính của nó . Nội dung của dict được cập nhật trên mỗi locals()cuộc gọi và từng f_localsquyền truy cập thuộc tính, nhưng chỉ trên các cuộc gọi hoặc quyền truy cập thuộc tính đó. Nó không tự động cập nhật khi các biến được gán và việc gán các mục trong dict sẽ không gán các biến cục bộ tương ứng:
import inspect
def f():
x = 1
l = locals()
print(l)
locals()
print(l)
x = 2
print(x, l['x'])
l['x'] = 3
print(x, l['x'])
inspect.currentframe().f_locals
print(x, l['x'])
f()
cho chúng tôi:
{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2
Đầu tiên print(l)chỉ hiển thị một 'x'mục, bởi vì việc chuyển nhượng lsẽ xảy ra sau locals()cuộc gọi. Thứ hai print(l), sau khi gọi locals()lại, hiển thị một lmục, mặc dù chúng tôi không lưu giá trị trả về. Các thứ ba và thứ tư printcho thấy việc gán các biến không cập nhật lvà ngược lại, nhưng sau khi chúng tôi truy cập f_locals, các biến cục bộ được sao chép locals()lại.
Hai lưu ý:
exec "pass"dòng trong hàm. Điều này chuyển chức năng sang chế độ thực thi cũ hơn, chậm hơn, sử dụng locals()dict làm biểu diễn chính tắc của các biến cục bộ.Nếu locals()được gọi bên ngoài một hàm, nó trả về từ điển thực tế là không gian tên hiện tại. Những thay đổi khác đối với không gian tên được phản ánh trong từ điển và những thay đổi đối với từ điển được phản ánh trong không gian tên:
class Test(object):
a = 'one'
b = 'two'
huh = locals()
c = 'three'
huh['d'] = 'four'
print huh
cho chúng tôi:
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
Cho đến nay, mọi thứ tôi đã nói locals()cũng đúng với vars()... đây là điểm khác biệt: vars()chấp nhận một đối tượng làm đối số của nó và nếu bạn đưa cho nó một đối tượng, nó sẽ trả về __dict__đối tượng đó. Đối với một đối tượng điển hình, đó __dict__là nơi lưu trữ hầu hết dữ liệu thuộc tính của nó. Điều này bao gồm các biến lớp và toàn cầu mô-đun:
class Test(object):
a = 'one'
b = 'two'
def frobber(self):
print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()
cung cấp cho chúng tôi:
three
Lưu ý rằng một hàm __dict__là không gian tên thuộc tính của nó, không phải là các biến cục bộ. Sẽ không có ý nghĩa đối với một hàm __dict__lưu trữ các biến cục bộ, vì đệ quy và đa luồng có nghĩa là có thể có nhiều lệnh gọi đến một hàm cùng một lúc, mỗi hàm có các biến cục bộ riêng:
def f(outer):
if outer:
f(False)
print('Outer call locals:', locals())
print('f.__dict__:', f.__dict__)
else:
print('Inner call locals:', locals())
print('f.__dict__:', f.__dict__)
f.x = 3
f(True)
cung cấp cho chúng tôi:
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
Ở đây, fcác cuộc gọi chính nó đệ quy, vì vậy các cuộc gọi bên trong và bên ngoài chồng chéo. Mỗi người nhìn thấy các biến cục bộ của chính nó khi nó gọi locals(), nhưng cả hai cuộc gọi đều thấy giống nhau f.__dict__và f.__dict__không có bất kỳ biến cục bộ nào trong đó.
vars()hoặc locals()từ điển được gọi trong một hàm nếu bạn sử dụng eval(). EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')in 4 khi test()được thực thi!
dict(được trả về bởi locals()) xảy ra được phản ánh trong không gian tên cục bộ và các thay đổi đối với không gian tên cục bộ sẽ được phản ánh trong dict(trong python của tôi). Điều duy nhất là đặc tả không đảm bảo hành vi này.
import thisvà trong googlesite:docs.python.org namespace