Globals (), locals () ve vars () arasındaki fark nedir?


146

Arasındaki fark nedir globals(), locals()ve vars()? Ne geri dönüyorlar? Sonuçlara ilişkin güncellemeler faydalı mı?


biri python 3 bunlardan herhangi birini güncelleyebilir ve komut dosyası gerçekten çalışır?
Charlie Parker

Yanıtlar:


173

Bunların her biri bir sözlük döndürür:

  • globals() her zaman modül ad alanının sözlüğünü döndürür
  • locals() Her zaman döndüren bir sözlüğünü akım ad
  • vars()döner ya bir (hayır seçeneği ile çağrılmış ise) Geçerli isim veya sözlüğü Tartışmanın Sözlük.

localsve varsbiraz daha açıklama yapabilir. Eğer locals()bir işlev içinde denir, o ana ve getiri bunun itibarıyla geçerli yerel değişken ad değerleri (artı herhangi kapatma değişkenler) ile bir dicti günceller. locals()Aynı yığın çerçevesinde birden çok çağrı her seferinde aynı dikdörtgeni döndürür - yığın çerçevesi nesnesine f_localsözniteliği olarak eklenir . Dikt içeriği her locals()aramada ve her f_localsözellik erişiminde güncellenir , ancak yalnızca bu aramalarda veya özellik erişimlerinde. Değişkenler atandığında otomatik olarak güncellenmez ve dikte girişlerinin atanması karşılık gelen yerel değişkenleri atamaz:

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()

bize verir:

{'x': 1}
{'x': 1, 'l': {...}}
2 1
2 3
2 2

İlki print(l)yalnızca bir 'x'girişi gösterir , çünkü atama çağrıdan lsonra gerçekleşir locals(). İkincisi print(l), locals()tekrar aradıktan sonra l, dönüş değerini kaydetmemize rağmen bir giriş gösterir . Üçüncü ve dördüncü prints değişkenleri atamanın güncellenmediğini lve tersini gösterir, ancak eriştikten sonra f_localsyerel değişkenler locals()tekrar kopyalanır .

İki not:

  1. Bu davranış CPython'a özgüdür - diğer Pythons güncelleştirmelerin yerel ad alanına otomatik olarak geri dönmesine izin verebilir.
  2. CPython 2.x'de exec "pass", bu işleve bir çizgi koyarak bu işi yapmak mümkündür . Bu, işlevi locals()yerel değişkenlerin kanonik temsili olarak dikte kullanan daha eski, daha yavaş bir yürütme moduna geçirir.

Eğer locals()denir dışında bir fonksiyonu mevcut ad alanıdır fiili sözlüğü döndürür. Ad ilave değişiklikler vardır sözlükte yansıyan ve sözlüğe değişiklikler vardır ad yansıyan:

class Test(object):
    a = 'one'
    b = 'two'
    huh = locals()
    c = 'three'
    huh['d'] = 'four'
    print huh

bize verir:

{
  'a': 'one',
  'b': 'two',
  'c': 'three',
  'd': 'four',
  'huh': {...},
  '__module__': '__main__',
}

Şimdiye kadar, söylediğim her şey locals()için de doğru vars()... işte fark: vars()tek bir nesneyi argümanı olarak kabul eder ve ona bir nesne verirseniz __dict__, o nesnenin değerini döndürür . Tipik bir nesne için, __dict__öznitelik verilerinin çoğunun saklandığı yerdir. Sınıf değişkenleri ve modül globalleri buna dahildir:

class Test(object):
    a = 'one'
    b = 'two'
    def frobber(self):
        print self.c
t = Test()
huh = vars(t)
huh['c'] = 'three'
t.frobber()

bu da bize:

three

Bir işlevin __dict__yerel değişkenler değil, öznitelik ad alanı olduğunu unutmayın . Bir işlevin __dict__yerel değişkenleri depolaması mantıklı olmaz , çünkü özyineleme ve çoklu iş parçacığı aynı anda bir işleve birden fazla çağrı olabileceği anlamına gelir, her birinin kendi yerel ayarı vardır:

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)

bu da bize:

Inner call locals: {'outer': False}
f.__dict__: {'x': 3}
Outer call locals: {'outer': True}
f.__dict__: {'x': 3}

Burada fkendini yinelemeli olarak çağırır, böylece iç ve dış çağrılar çakışır. Her biri çağrı yaparken kendi yerel değişkenlerini görür locals(), ancak her iki çağrı da aynı görür f.__dict__ve f.__dict__içinde yerel değişkenler yoktur.


4
"Ve sözlüğe yapılan atamalar gerçek yerel ad alanına yansıtılmıyor" bölümü biraz tanımlanabilir .
Sven Marnach

İşin tuhafı, kullanırsanız, bir işlev içinde adlandırılan bir vars()veya locals()sözlüğe eklenen değişkenlere erişebilirsiniz eval(). EG: yürütüldüğünde def test(): huh = locals(); huh['d'] = 4; print eval('d')4 yazdırır test()!
Mark Mikofski

1
Aslında dict(tarafından döndürülen locals()) ataması yerel ad alanına yansıtılır ve yerel ad alanında yapılan değişiklikler dict(pitonumda) yansıtılır . Tek şey, spesifikasyonun bu davranışı garanti etmemesidir.
skyking

Terim adı kapsamı kullanımı benim için ad alanından daha kolay görünüyor .
17'de

1
@overexchange: import thisve Google'dasite:docs.python.org namespace
Ethan Furman
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.