ความแตกต่างระหว่างคืออะไรglobals(), locals()และvars()? พวกเขากลับมาทำอะไร? การอัพเดตผลลัพธ์มีประโยชน์หรือไม่
ความแตกต่างระหว่างคืออะไรglobals(), locals()และvars()? พวกเขากลับมาทำอะไร? การอัพเดตผลลัพธ์มีประโยชน์หรือไม่
คำตอบ:
แต่ละรายการจะส่งคืนพจนานุกรม:
globals() มักจะส่งกลับพจนานุกรมของโมดูล namespacelocals() มักจะส่งกลับพจนานุกรมของปัจจุบัน namespacevars()ผลตอบแทนทั้งในพจนานุกรมของ namespace ที่ปัจจุบัน (ถ้าเรียกว่ามีข้อโต้แย้งไม่ได้) หรือพจนานุกรมของการโต้แย้งlocalsและvarsสามารถใช้คำอธิบายเพิ่มเติมได้บ้าง หากlocals()เรียกว่าภายในฟังก์ชั่นมันจะอัพเดท dict ด้วยค่าของ namespace ตัวแปรโลคอลปัจจุบัน (รวมถึงตัวแปรปิดใด ๆ ) ณ ขณะนั้นและส่งคืน การเรียกหลายครั้งlocals()ในเฟรมสแต็กเดียวกันจะส่งกลับค่า Dict เดียวกันทุกครั้ง - มันถูกแนบไปกับวัตถุเฟรมสแต็กเป็นf_localsคุณลักษณะ เนื้อหาของ dict จะได้รับการอัปเดตในการlocals()โทรแต่ละครั้งและf_localsการเข้าถึงแต่ละแอตทริบิวต์ แต่จะใช้เฉพาะการโทรหรือการเข้าถึงแอตทริบิวต์ดังกล่าวเท่านั้น จะไม่อัปเดตโดยอัตโนมัติเมื่อกำหนดตัวแปรและการกำหนดรายการใน dict จะไม่กำหนดตัวแปรท้องถิ่นที่เกี่ยวข้อง:
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()
ให้เรา:
{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2
รายการแรกprint(l)แสดงเฉพาะ'x'รายการเนื่องจากการมอบหมายให้lเกิดขึ้นหลังจากการlocals()โทร รายการที่สองprint(l)หลังจากโทรlocals()อีกครั้งแสดงlรายการแม้ว่าเราจะไม่ได้บันทึกค่าส่งคืน รายการที่สามและสี่printที่กำหนดตัวแปรไม่ได้อัปเดตlและในทางกลับกัน แต่หลังจากที่เราเข้าถึงf_localsแล้วตัวแปรโลคัลจะถูกคัดลอกเข้าไปlocals()อีกครั้ง
หมายเหตุสองประการ:
exec "pass"สายในฟังก์ชั่น สิ่งนี้จะสลับฟังก์ชั่นไปเป็นโหมดการดำเนินการที่เก่ากว่าและช้ากว่าซึ่งใช้locals()dict เป็นตัวแทนมาตรฐานของตัวแปรโลคัลหากlocals()เรียกว่านอกฟังก์ชั่นมันจะส่งกลับพจนานุกรมจริงที่เป็น namespace ปัจจุบัน การเปลี่ยนแปลงเพิ่มเติมของเนมสเปซจะแสดงในพจนานุกรมและการเปลี่ยนแปลงในพจนานุกรมจะปรากฏในเนมสเปซ:
class Test(object):
a = 'one'
b = 'two'
huh = locals()
c = 'three'
huh['d'] = 'four'
print huh
ให้เรา:
{
'a': 'one',
'b': 'two',
'c': 'three',
'd': 'four',
'huh': {...},
'__module__': '__main__',
}
จนถึงทุกสิ่งที่ฉันพูดเกี่ยวกับlocals()ก็เป็นจริงสำหรับvars()... นี่คือความแตกต่าง: vars()ยอมรับวัตถุเดียวเป็นอาร์กิวเมนต์ของมันและถ้าคุณให้มันวัตถุมันคืนค่า__dict__ของวัตถุนั้น สำหรับวัตถุทั่วไปนั้น__dict__เป็นที่เก็บข้อมูลคุณลักษณะส่วนใหญ่ ซึ่งรวมถึงตัวแปรคลาสและโมดูล globals:
class Test(object):
a = 'one'
b = 'two'
def frobber(self):
print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()
ซึ่งทำให้เรา:
three
โปรดทราบว่าฟังก์ชั่นของ__dict__มันคือ namespace คุณลักษณะของมันไม่ใช่ตัวแปรท้องถิ่น มันจะไม่สมเหตุสมผลสำหรับฟังก์ชั่นใน__dict__การจัดเก็บตัวแปรในตัวเครื่องเนื่องจากการเรียกซ้ำและการมัลติเธรดหมายความว่าสามารถมีการเรียกไปยังฟังก์ชั่นหลายรายการพร้อมกันโดยแต่ละคนมีคนท้องถิ่น:
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)
ซึ่งทำให้เรา:
Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}
ที่นี่fเรียกตัวเองซ้ำ ๆ ดังนั้นการโทรภายในและภายนอกซ้อนทับกัน แต่ละคนเห็นตัวแปรโลคัลของตัวเองเมื่อเรียกใช้locals()แต่การโทรทั้งสองเห็นเหมือนกันf.__dict__และf.__dict__ไม่มีตัวแปรโลคัลอยู่ในตัว
vars()หรือพจนานุกรมเรียกว่าฟังก์ชั่นภายในถ้าคุณใช้locals() eval()EG: def test(): huh = locals(); huh['d'] = 4; print eval('d')พิมพ์ 4 เมื่อtest()มีการดำเนินการ!
dict(ส่งคืนโดยlocals()) เกิดขึ้นกับภาพสะท้อนในเนมสเปซในพื้นที่และการเปลี่ยนแปลงในเนมสเปซในท้องถิ่นเกิดขึ้นที่จะสะท้อนให้เห็นในdict(ในงูหลามของฉัน) สิ่งเดียวคือสเปคไม่รับประกันพฤติกรรมนี้
import thisและใน googlesite:docs.python.org namespace