Nasıl Python modülü-geniş değişkenleri oluşturmak için?
Bir şekilde bir modül içinde global bir değişken ayarlama var mı? Göründüğü gibi en belirgin şekilde yapmak için aşağıda çalıştığımda, Python yorumlayıcısı değişken __DBNAME__
yok dedi.
...
__DBNAME__ = None
def initDB(name):
if not __DBNAME__:
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
...
Ve farklı bir dosya modülü aldıktan sonra
...
import mymodule
mymodule.initDB('mydb.sqlite')
...
Ve traceback oldu: UnboundLocalError: local variable '__DBNAME__' referenced before assignment
Herhangi bir fikir? this fellow's tavsiye olarak başına bir modül kullanarak bir singleton kurmak için çalışıyorum.
CEVAP
Neler oluyor burada.
İlk olarak, sadece global değişkenler Python gerçekten var modül kapsamlı değişkenlerdir. Olamaz gerçekten global bir değişken yapmak; yapabileceğin tek şey, belirli bir kapsamda bir değişken olun. Python yorumlayıcısı içinde bir değişken haline getirmek ve daha sonra diğer modülleri alma (eğer değişken dıştaki kapsamında ve Python oturumunda küresel böylece.)
Modül-global bir değişken yapmak için yapmanız gereken tek şey bir isim atayın.
Bir dosya bu tek satır içeren: foo.py adı verilen hayal
X = 1
Şimdi aldıktan düşünün.
import foo
print(foo.X) # prints 1
Ancak umalım ki bu örnekte bir işlev içinde, genel olarak bir modül kapsam değişkenleri kullanmak istediğinizi varsayalım. Python varsayılan fonksiyon değişkenleri yerel olduğunu varsayalım. Sen küresel kullanmayı denemeden önce sadece fonksiyonu global
beyan ekleyin.
def initDB(name):
global __DBNAME__ # add this line!
if __DBNAME__ is None: # see notes below; explicit test for None
__DBNAME__ = name
else:
raise RuntimeError("Database name has already been set.")
Bu örnek için, if not __DBNAME__
basit test herhangi bir dize değeri boş bir dize dışında herhangi bir gerçek veritabanı adı doğru değerlendirecek kadar doğru değerlendirir çünkü yeterli. Ama değişkenleri içerebilir bir sayı değeri olabilir 0, yapamazsın söyle if not variablename
; bu durumda, gerekir açıkça test için None
is
operatör. Örnek None
açık bir test eklemek için değiştirilmiş. None
açık test asla yanılmaz, ben bunu kullanarak gerçekler.
Son olarak, başkalarının bu sayfada belirttiği gibi, iki önde gelen sinyaller altını çiziyor değişken olmak istediğiniz Python "özel" modülü. Eğer bunu bir daha yaparsan* *21, bir Python adını uzaya önde gelen iki alt çizgi ile isimleri almaz. Ama eğer sadece basit bir import mymodule
ve sonra dir(mymodule)
görürsünüz "özel" değişkenleri listesinde, ve eğer açıkça başvurmak için mymodule.__DBNAME__
Python olmayacak, sadece izin bakın. Çift kişilik lider altını çiziyor kendi değeri için bu ismi onlara yeniden birleştirme istemediğiniz modül kullanıcıları için büyük bir ipucu.
En iyi Python uygulama import *
ama bağlamanın en aza indirmek ve açıkça from mymodule import something
gibi bir ithalat yaparak ya mymodule.something
kullanarak veya explicitness en üst düzeye çıkarmak için yapmak kabul edilmez.
EDİT: nedense global
anahtar yok Python çok eski bir sürümünde böyle bir şey yapmak gerekiyorsa, kolay bir çözüm yoktur. Doğrudan modülü global bir değişken ayarlamak yerine, modül küresel düzeyde değişken bir tip kullanın ve içine değerleri saklamak.
Senin fonksiyonlarda global değişken adı salt okunur olur; gerçek bir genel değişken adı yeniden bağlamanız mümkün olmayacaktır. Eğer bu değişken adını atarsanız (fonksiyon içinde fonksiyon içinde yerel değişken adı etkileyecektir.) Ama bu yerel değişken adı gerçek küresel nesnesi ve bunun içinde saklayabilirsiniz.
list
bir kullanabilirsiniz ama kodunuzu çirkin olacak:
__DBNAME__ = [None] # use length-1 list as a mutable
# later, in code:
if __DBNAME__[0] is None:
__DBNAME__[0] = name
dict
bir daha iyidir. Ama en rahat sınıf bir örneğidir ve sadece önemsiz bir sınıf kullanabilirsiniz:
class Box:
pass
__m = Box() # m will contain all module-level values
__m.dbname = None # database name global in module
# later, in code:
if __m.dbname is None:
__m.dbname = name
(Gerçekten veritabanı adı değişken yararlanmak gerek yok.)
Sadece __m.dbname
kullanarak sözdizimsel şeker yerine __m["DBNAME"]
; bence en uygun çözüm gibi görünüyor seviyorum. Ama dict
çözüm iyi de çalışıyor.
Bir dict
kullanabilirsiniz herhangi bir hashable değer olarak bir anahtar, ama ne zaman sen are mutlu ile adları, geçerli bir tanımlayıcı kullanabilirsiniz önemsiz bir ders gibi Box
yukarıdaki.
Nasıl Python ortam değişkenleri erişme...
Nasıl Python listesi tüm permütasyon o...
Nasıl Python ile bir GUID oluşturmak i...
Nasıl Python bir modülü yazmak için?...
Nasıl python modülü sürümü kontrol etm...