2014-04-01 39 views
6

MinimalPython kapsam sorunu

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     # works 
     print({e : loadings[e] for e in loadings}) 
     # NameError global name 'loadings' not defined 

Ben de sınıf ad alanına başvurma denedik örnek ama bu çalışmıyor ya

class foo: 
    loadings = dict(hi=1) 
    if 'hi' in loadings: 
     print(loadings['hi']) 
     #works 
     print({e : foo.loadings[e] for e in foo.loadings}) 
     #NameError: name 'foo' is not defined 

Ve tabii ki

, Bu, beklendiği gibi çalışır Bu kapsam sorununun neden olduğunu anlayabilmek için karınca, eğer bir şey yapmaya çalışıyorsam, aksi halde bunu yapmanın en iyi yolunu anlıyorum. Duygularım, ilk kod snip'in olduğu gibi çalışması gerektiğiydi, ama tabi ki değil.

gol

ben konserve veritabanı sorgu ile birlikte bazı csv/json dosyaları için bir Datamanager sınıf/modülü oluşturma, benim programı ve elde veri için tek bir mağazası. Bazı statik veriler ve bazı dinamik veriler vardır, bu nedenle aynı sınıftaki statik ve statik olmayan veri elemanlarının harika bir kullanımı gibi görünüyordu. Bunların modül seviyesi değişkenleri olabileceğini anladığım halde, statik sınıf veri üyelerine sahip olma konseptini (muhtemelen Java'dan gelen bir önyargı nedeniyle) seviyorum. Herhangi bir yardım çok ben üstündeki bu

class foo: 
    loadings = dict(hi=1) 
    temp = dict() 
    for e in loadings: 
     temp[e] = loadings[e] # keep in mind this is a minimal example, I probably wouldn't do (just) this 
    print(temp) # works 
    del temp 

gibi bir şey olacak içinde, sınıf kapsamına kalmak liste anlama unfurling sona erdi

(şimdilik)

Benim çözüm takdir oldukça değil ama Name and Binding docs Başına şimdi

+0

Ben onun da ilginç not etmek düşünüyorum –

+0

.... 'baskı ({k o loadings.items()}) işlevinde k, v çalışır.Yani 'yüklemeler' en azından dict anlaşmasında görülebilir. – cmd

+0

Bu, init işlevinde yapılmadı çünkü bu, bir kez yüklenen sınıfın statik verileridir. 'Runonce' ya da bir şey gibi bir bayrak alabilirdim ama sınıf seviyesi kodunun bir sebepten dolayı varmış gibi görünüyordu. – user25064

cevap

4

için çalışır:

Bir sınıf bloğunda tanımlanan adların kapsamı, bloğu ile sınırlıdır; kod bloklarına uzanmaz, bu , anlamalarını ve bir işlev kapsamı kullanılarak uygulanan olduğu için jeneratör ifadelerini içerir. Bu şu başarısız olacağı anlamına gelir:

class A: 
    a = 42 
    b = list(a + i for i in range(10)) 

fazla ayrıntı için this answer bakınız.

dict([(e,loadings[e]) for e in loadings]) 

Ama Python3 içinde çalıştırırsanız bu kod kırardı: bunlar işlevi kapsamını kullanmadan uygulanmıştır beri Python2 yılında


, liste kullanmak mümkündür. Yani burada Python2 ve Python3 çalışacağını alternatif çözüm budur: v için: Bir init işlevi içinde bütün bu yapmalıyım

class Foo: 
    def loadings(): 
     load = dict(hi=1) 
     if 'hi' in load: 
      print(load['hi']) 
      print({e:load[e] for e in load}) 
     return load 
    loadings = loadings() 

print(Foo.loadings) 
+0

Açık ve özlü bir açıklama için çok teşekkür ederim! Son kod bloğunun son iki satırını 'print (Foo.loadings)' gibi bir şeyle değiştirmek ve onu statik veri üyesi olarak kullanmak niyetimin size işaret etmek istediğini belirtmek istedim. – user25064