Dosyalar arasında genel değişkenler mi kullanıyorsunuz?


208

Küresel değişkenlerin nasıl çalıştığı konusunda biraz kafam karıştı. Yaklaşık 50 dosya içeren büyük bir projem var ve tüm bu dosyalar için global değişkenler tanımlamam gerekiyor.

Yaptığım şey bunları projelerim main.pydosyasında tanımlamaktı :

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

Ben kullanmaya çalışıyorum myListiçinde subfile.pyaşağıdaki gibi

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
    globals()["myList"].append("hey")

Başka bir yol denedim ama işe yaramadı

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

Ve içimde subfile.pybu vardı:

# ../myproject/subfile.py

# Import globfile
import globfile

# Save "hey" into myList
def stuff():
    globfile.myList.append("hey")

Ama yine işe yaramadı. Bunu nasıl uygulamalıyım? İki dosya birbirini gerçekten tanımadığında (iyi alt dosya ana bilmiyor), bu şekilde çalışamayacağını anlıyorum, ancak io yazma veya turşu kullanmadan nasıl yapılacağını düşünemiyorum. Yapmak istemiyorum.


Aslında, ikinci yaklaşımın benim için iyi çalışıyor. main.py doğru şekilde "hey" çıktısını alır. "Bu işe yaramadı" ile ilgili olarak bana daha açık olabilir misiniz?
rodion

@ rodion: içe aktarma döngüleri - alt dosyadaki kod, içindeki kendini geri ithal eden globfile'ı içe aktarmaya çalışır
jsbueno

1
NameError: name 'myList' is not defineddan main.pyhatprint(globfile.myList[0])

Yanıtlar:


320

Sorun tanımlı myListgelen main.py, ancak subfile.pybunu kullanması gerekir. İşte bu sorunu çözmenin temiz bir yolu: tüm globalleri bir dosyaya taşıyın, bu dosyayı çağırıyorum settings.py. Bu dosya globalleri tanımlamaktan ve başlatmaktan sorumludur:

# settings.py

def init():
    global myList
    myList = []

Ardından, subfilegloballeri içe aktarabilirsiniz:

# subfile.py

import settings

def stuff():
    settings.myList.append('hey')

Not subfileçağırmaz init()- görev ait olduğunu main.py:

# main.py

import settings
import subfile

settings.init()          # Call only once
subfile.stuff()         # Do stuff with global var
print settings.myList[0] # Check the result

Bu şekilde, global değişkenleri bir kereden fazla başlatmaktan kaçınırken hedefinize ulaşırsınız.


41
Genel yaklaşımı seviyorum ama her init()şeyi sevmiyorum . Modüller yalnızca ilk içe aktarıldıklarında değerlendirilir, bu nedenle modülün gövdesinde bu değişkenleri başlatmak mükemmel olur.
Kirk Strauser

19
+1 Kirk: Katılıyorum. Ancak, yaklaşımım ana modül başlamadan önce globals.myList 'i diğer modüllerin değiştirdiği durumu önler.
Hai Vu

2
Buna küreselden başka bir şey demelisiniz ki bu yerleşik bir isim. PyLint şu uyarıyı verir: "
Yerleşik

Teşekkürler. Herhangi bir fikir bu dosya yapısını kullanarak Eclipse PyDev görünen "Tanımlanmamış değişken ithalattan" hataları kaldırmak için nasıl (yani global değişkenleri settings.py ithal)? İdeal olmayan PyDev'de hatayı devre dışı bırakmak zorunda kaldım .
Franck Dernoncourt

@FranckDernoncourt Özür dilerim, Eclipse kullanmıyorum, bu yüzden senden bile daha fazla bilgim yok.
Hai Vu

94

Genel değişkenleri modüller arasında paylaşma hakkındaki Python'un belgesine bakın :

Tek bir program içinde modüller arasında bilgi paylaşmanın standart yolu, özel bir modül (genellikle config veya cfg olarak adlandırılır) oluşturmaktır.

config.py:

x = 0   # Default value of the 'x' configuration setting

Yapılandırma modülünü uygulamanızın tüm modüllerine içe aktarın; modül daha sonra global bir ad olarak kullanılabilir hale gelir.

main.py:

import config
print (config.x)

veya

from config import x
print (x)

Genel olarak, kullanmayın gelen modulename import * . Bunu yapmak, ithalatçının ad alanını keser ve linterin tanımsız adları tespit etmesini çok daha zorlaştırır.


1
Cankurtaran - sadece bu bağlantı için!
toonarmycaptain

4
Bu, kabul edilen cevaptan daha temiz bir yaklaşım gibi görünüyor.
JoeyC

2
Belirlediğiniz olamayacağını Not xkullanarak from config import xsadece kullanılarak,import config
Yariv

1
En basit çözüm! Teşekkürler
user1297406

22

Python global değişkenlerini "modül" değişkenleri olarak düşünebilirsiniz - ve bu nedenle bunlar C'nin geleneksel "global değişkenleri" nden çok daha yararlıdır.

Bir global değişken aslında bir modülün __dict__ ve bu modülün dışından modül niteliği olarak erişilebilir.

Yani, örneğinizde:

# ../myproject/main.py

# Define global myList
# global myList  - there is no "global" declaration at module level. Just inside
# function and methods
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

Ve:

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
     # You have to make the module main available for the 
     # code here.
     # Placing the import inside the function body will
     # usually avoid import cycles - 
     # unless you happen to call this function from 
     # either main or subfile's body (i.e. not from inside a function or method)
     import main
     main.mylist.append("hey")

1
vay, normalde biri içe aktarılan iki dosyanın sonsuz döngüye girmesini beklerdi.
Nikhil VJ

2
ha İlk bakışta öyle görünüyor, değil mi? Def stuff () 'da olan şey, dosya yüklendiğinde içe aktarmanın ....it yalnızca stuff () işlevi çağrıldığında çalışmamasıdır. Bu yüzden main ile başlayarak alt dosyayı içe aktarırız ve daha sonra main ... no loop'u ithal eden subfile.stuff () öğesini çağırırız, sadece bir kez ana olarak içe aktarırız. İçe aktarma döngüleri ile ilgili subfile.py örneğindeki nota bakın.
John

11

kullanma from your_file import * sorunlarınız çözülmelidir. Her şeyi, küresel olarak erişilebilir olacak şekilde tanımlar (elbette ithalattaki yerel değişkenler hariç).

Örneğin:

##test.py:

from pytest import *

print hello_world

ve:

##pytest.py

hello_world="hello world!"

4
Böyle bir değişkene
atarsanız

5
Ben şahsen import *referansları açık (ve kafa karıştırıcı değil) böylece pahasına kullanmaktan kaçının , Ayrıca, *herhangi bir modülde gerçekten tüm " " referansları kullandınız mı?
ThorSummoner

19
İçe aktarma YAPMAYIN *. Global değişkenleriniz artık senkronize olmayacak. Her modül kendi kopyasını alır. Bir dosyadaki değişkenin değiştirilmesi başka bir dosyada yansıtılmaz. Ayrıca docs.python.org/2/faq/…
Isa Hassen

8

Hai Vu cevap harika çalışıyor, sadece bir yorum:

Global'i diğer modülde kullanıyorsanız ve genel olarak dinamik olarak ayarlamak istiyorsanız, global değişkenleri ayarladıktan sonra diğer modülleri içe aktarmaya dikkat edin, örneğin:

# settings.py
def init(arg):
    global myList
    myList = []
    mylist.append(arg)


# subfile.py
import settings

def print():
    settings.myList[0]


# main.py
import settings
settings.init("1st")     # global init before used in other imported modules
                         # Or else they will be undefined

import subfile    
subfile.print()          # global usage

4

2. denemeniz mükemmel bir şekilde çalışacaktır ve aslında küresel olarak kullanılabilir olmasını istediğiniz değişken adlarını işlemek için gerçekten iyi bir yoldur. Ancak son satırda bir ad hatası var. İşte nasıl olması gerektiği:

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

Son satırı görüyor musunuz? myList, alt dosya değil, globfile'ın bir yıpranmasıdır. Bu istediğiniz gibi çalışacaktır.

mikrofon

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.