Yanıtlar:
Genel bir değişkeni, global
kendisine atanan her işlevde olduğu gibi bildirerek diğer işlevlerde kullanabilirsiniz :
globvar = 0
def set_globvar_to_one():
global globvar # Needed to modify global copy of globvar
globvar = 1
def print_globvar():
print(globvar) # No need for global declaration to read value of globvar
set_globvar_to_one()
print_globvar() # Prints 1
Bunun nedeni, küresel değişkenler çok tehlikeli olduğu için, Python'un global
anahtar kelimeyi açıkça isteyerek gerçekten bununla oynadığınızı bildiğinizden emin olmak istediğini hayal ediyorum .
Genel bir değişkeni modüller arasında paylaşmak istiyorsanız diğer yanıtlara bakın.
global
anahtar kelimeyi gerektirmesinin sebebi , küresellerin tehlikeli olmasından kaynaklanmıyor. Aksine, dilin açıkça değişkenleri bildirmenizi gerektirmemesi ve aksi belirtilmedikçe, atadığınız bir değişkenin işlev kapsamına sahip olduğunu otomatik olarak varsaymasıdır. global
Anahtar kelime başka bir şey isteyene verilir araçtır.
f2()
durum değiştirmek yani şimdi f3()
? Beklenmeyen bir şey yapabilir fonksiyonları artık dış program durumuna agnostik çalışabilir.
Durumunuzu doğru bir şekilde anlıyorsam, gördüğünüz şey Python'un yerel (işlev) ve genel (modül) ad alanlarını nasıl işlediğinin sonucudur.
Diyelim ki böyle bir modülünüz var:
# sample.py
myGlobal = 5
def func1():
myGlobal = 42
def func2():
print myGlobal
func1()
func2()
Bu 42 yazdırmaya bekliyor olabilir, ancak bir 'eklerseniz bunun yerine, 5. Daha önce bahsedildiği yazdırır global
için' beyanı func1()
sonra, func2()
42 yazdırılır.
def func1():
global myGlobal
myGlobal = 42
Burada olup bitenler, Python'un , bir işlev içinde herhangi bir yere atanan herhangi bir adın, aksi açıkça belirtilmediği sürece bu işlev için yerel olduğunu varsayar . Yalnızca bir addan okuyorsa ve ad yerel olarak mevcut değilse, adı içeren kapsamlarda (örneğin, modülün global kapsamı) aramaya çalışır.
Bu myGlobal
nedenle ada 42 atadığınızda , Python aynı adın genel değişkenini gölgeleyen yerel bir değişken oluşturur. Yerel kapsam dışına gider ve olduğu çöp toplama zaman func1()
döner; bu arada, func2()
(değiştirilmemiş) global ad dışında hiçbir şey göremezsiniz. Bu ad alanı kararının derleme zamanında değil, çalışma zamanında gerçekleştiğine dikkat edin - atamadan önce myGlobal
içerideki değeri okuyacak func1()
olsaydınız, alırsınız UnboundLocalError
, çünkü Python zaten yerel bir değişken olmasına karar verdi, ancak henüz onunla ilişkili bir değere sahip değil. Ancak ' global
' ifadesini kullanarak, Python'a yerel olarak atamak yerine ad için başka bir yere bakması gerektiğini söylersiniz.
(Bu davranışın büyük ölçüde yerel ad alanlarının optimizasyonundan kaynaklandığına inanıyorum - bu davranış olmadan, Python VM'sinin bir işlev içinde her yeni bir ad atandığında en az üç ad araması yapması gerekir (adın t zaten modül / yerleşik düzeyde mevcut), bu çok yaygın bir işlemi önemli ölçüde yavaşlatır.)
MyGlobal = 5
x
Yerel olduğuna karar vermek , yerel adın ilk kez kullanılmadan önce bir değere bağlı olup olmadığını çalışma zamanında denetlemekten farklıdır.
MY_GLOBAL = 5
. Python Kodu için Stil Kılavuzuna bakın .
Ad alanları kavramını keşfetmek isteyebilirsiniz . Python'da, modül küresel veriler için doğal bir yerdir :
Her modülün, modülde tanımlanan tüm işlevler tarafından genel sembol tablosu olarak kullanılan kendi özel sembol tablosu vardır. Böylece, bir modülün yazarı, bir kullanıcının global değişkenleriyle yanlışlıkla çarpışmadan endişe etmeden modüldeki global değişkenleri kullanabilir. Öte yandan, ne yaptığınızı biliyorsanız, bir modülün işlevlerine atıfta bulunmak için kullanılan aynı gösterime sahip global değişkenlere dokunabilirsiniz
modname.itemname
.
Genel modül içinde özel kullanımı burada açıklanmıştır - Genel değişkenleri modüller arasında nasıl paylaşabilirim? ve eksiksiz olması için içerik burada paylaşılır:
Tek bir programda modüller arasında bilgi paylaşmanın standart yolu, özel bir yapılandırma modülü (genellikle config veya cfg olarak adlandırılır) oluşturmaktır ) oluşturmaktır. Yapılandırma modülünü uygulamanızın tüm modüllerine aktarmanız yeterlidir; modül global bir ad olarak kullanılabilir hale gelir. Her modülün yalnızca bir örneği olduğundan, modül nesnesinde yapılan değişiklikler her yere yansıtılır. Örneğin:
Dosya: config.py
x = 0 # Default value of the 'x' configuration setting
Dosya: mod.py
import config config.x = 1
Dosya: main.py
import config import mod print config.x
config.x
ondan kurtulabilir miyim? Geldim x = lambda: config.x
ve sonra yeni bir değere sahibim x()
. bir nedenden dolayı, sahip olmak a = config.x
benim için hile yapmaz.
from config import x
çözüyor mu?
Python, hangi kapsamdan yerel ve küresel arasında bir değişken yüklemesi gerektiğine karar vermek için basit bir buluşsal yöntem kullanır. Bir ödevin sol tarafında bir değişken adı görünüyor ancak global olarak bildirilmiyorsa, yerel olduğu varsayılır. Bir ödevin sol tarafında görünmezse, küresel olduğu varsayılır.
>>> import dis
>>> def foo():
... global bar
... baz = 5
... print bar
... print baz
... print quux
...
>>> dis.disassemble(foo.func_code)
3 0 LOAD_CONST 1 (5)
3 STORE_FAST 0 (baz)
4 6 LOAD_GLOBAL 0 (bar)
9 PRINT_ITEM
10 PRINT_NEWLINE
5 11 LOAD_FAST 0 (baz)
14 PRINT_ITEM
15 PRINT_NEWLINE
6 16 LOAD_GLOBAL 1 (quux)
19 PRINT_ITEM
20 PRINT_NEWLINE
21 LOAD_CONST 0 (None)
24 RETURN_VALUE
>>>
Bir ödevin sol tarafında görünen baz'ın foo()
tek LOAD_FAST
değişken olduğunu görün.
for
döngü ve sonra adı as
içinde with
ve except
ifadeleri de bağlanmıştır.
as
Bir except
maddeden sonraki isim için bu benim için açık değildi. Ancak hafızadan tasarruf etmek için otomatik olarak silinir.
as ...
, istisna işleyicisindeki hedef de dahil olmak üzere tüm çağrı yığını boyunca her yerel ve global ad alanına başvurmasıdır .
Bir işlevdeki bir genel değişkene başvurmak istiyorsanız, genel hangi değişkenlerin genel olduğunu bildirmek anahtar sözcüğünü . Her durumda kullanmak zorunda değilsiniz (burada birinin yanlış iddia ettiği gibi) - bir ifadede atıfta bulunulan ad yerel kapsamda bulunamazsa veya bu işlevin tanımlandığı işlevlerin kapsamlarında bulunamazsa, genel değişkenler.
Ancak, işlevde global olarak bildirilmeyen yeni bir değişkene atarsanız, dolaylı olarak yerel olarak bildirilir ve aynı ada sahip varolan herhangi bir genel değişkeni gölgede bırakabilir.
Ayrıca, küresel değişkenler, aksi halde iddia eden bazı OOP zekâllerinin aksine, özellikle OOP'un aşırı dolu olduğu daha küçük komut dosyaları için kullanışlıdır.
Bir işlevde genel değişken oluşturursam, bu değişkeni başka bir işlevde nasıl kullanabilirim?
Aşağıdaki işlevle bir global oluşturabiliriz:
def create_global_variable():
global global_variable # must declare it to be a global first
# modifications are thus reflected on the module's global scope
global_variable = 'Foo'
Bir işlev yazmak aslında kodunu çalıştırmaz. Bu yüzden create_global_variable
işlevi çağırırız :
>>> create_global_variable()
Hangi nesneyi işaret ettiğini değiştirmeyi beklemediğiniz sürece kullanabilirsiniz.
Örneğin,
def use_global_variable():
return global_variable + '!!!'
ve şimdi global değişkeni kullanabiliriz:
>>> use_global_variable()
'Foo!!!'
Genel değişkeni farklı bir nesneye yönlendirmek için genel anahtar kelimeyi tekrar kullanmanız gerekir:
def change_global_variable():
global global_variable
global_variable = 'Bar'
Bu işlevi yazdıktan sonra, aslında değiştiren kodun hala çalışmadığını unutmayın:
>>> use_global_variable()
'Foo!!!'
Yani işlevi çağırdıktan sonra:
>>> change_global_variable()
küresel değişkenin değiştiğini görebiliriz. global_variable
Adı artık işaret 'Bar'
:
>>> use_global_variable()
'Bar!!!'
Python'daki "global" değerin gerçekten global olmadığını unutmayın - sadece modül düzeyinde globaldir. Bu yüzden sadece küresel olduğu modüllerde yazılan fonksiyonlar için kullanılabilir. İşlevler, yazıldıkları modülü hatırlar, bu nedenle diğer modüllere dışa aktarıldıklarında, küresel değişkenleri bulmak için oluşturuldukları modüle bakarlar.
Aynı ada sahip bir yerel değişken oluşturursanız, global bir değişkeni gölgede bırakır:
def use_local_with_same_name_as_global():
# bad name for a local variable, though.
global_variable = 'Baz'
return global_variable + '!!!'
>>> use_local_with_same_name_as_global()
'Baz!!!'
Ancak bu yanlış adlandırılmış yerel değişkeni kullanmak genel değişkeni değiştirmez:
>>> use_global_variable()
'Bar!!!'
Ne yaptığınızı tam olarak bilmiyorsanız ve bunu yapmak için çok iyi bir nedeniniz yoksa, global değişkenlerle aynı adlara sahip yerel değişkenleri kullanmaktan kaçınmanız gerektiğini unutmayın. Henüz böyle bir sebeple karşılaşmadım.
Yorum takip edildiğinde:
bir sınıf içindeki bir işlevin içinde global bir değişken oluşturmak ve başka bir sınıf içindeki başka bir işlevin içindeki bu değişkeni kullanmak istersem ne yapmalıyım?
Burada, düzenli işlevlerde yaptığımız yöntemlerle aynı davranışı elde ettiğimizi göstereceğim:
class Foo:
def foo(self):
global global_variable
global_variable = 'Foo'
class Bar:
def bar(self):
return global_variable + '!!!'
Foo().foo()
Ve şimdi:
>>> Bar().bar()
'Foo!!!'
Ancak modül ad alanını karmaşıklaştırmaktan kaçınmak için global değişkenleri kullanmak yerine sınıf özniteliklerini kullanırsınız. Ayrıca self
burada argümanlar kullanmadığımızı unutmayın - bunlar sınıf yöntemleri (sınıf niteliğini normal cls
argümandan mutasyona uğrarsa kullanışlıdır ) veya statik yöntemler (hayır self
veya cls
) olabilir.
Mevcut cevaplara ek olarak ve bunu daha karmaşık hale getirmek için:
Python'da, yalnızca bir işlev içinde başvurulan değişkenler dolaylı olarak geneldir . Bir değişkene fonksiyonun gövdesinde herhangi bir yerde yeni bir değer atanırsa, yerel olarak kabul edilir . Bir değişkene işlev içinde yeni bir değer atanırsa, değişken dolaylı olarak yereldir ve bunu açıkça 'global' olarak bildirmeniz gerekir.
İlk başta biraz şaşırtıcı olsa da, bir anın düşüncesi bunu açıklıyor. Bir yandan, atanan değişkenler için global gereksinimi, istenmeyen yan etkilere karşı bir çubuk sağlar. Öte yandan, tüm global referanslar için global gerekiyorsa, her zaman global kullanırsınız. Yerleşik bir işleve veya içe aktarılan bir modülün her bileşenine yapılan her başvuruyu genel olarak bildirmeniz gerekir. Bu karmaşa, yan etkilerin tanımlanması için küresel bildirgenin yararlılığını bozacaktır.
Kaynak: Python'daki yerel ve global değişkenler için kurallar nelerdir? .
Paralel yürütme ile, ne olduğunu anlamıyorsanız genel değişkenler beklenmedik sonuçlara neden olabilir. Aşağıda, çoklu işlemede genel bir değişken kullanımına bir örnek verilmiştir. Her sürecin, değişkenin kendi kopyasıyla çalıştığını açıkça görebiliriz:
import multiprocessing
import os
import random
import sys
import time
def worker(new_value):
old_value = get_value()
set_value(random.randint(1, 99))
print('pid=[{pid}] '
'old_value=[{old_value:2}] '
'new_value=[{new_value:2}] '
'get_value=[{get_value:2}]'.format(
pid=str(os.getpid()),
old_value=old_value,
new_value=new_value,
get_value=get_value()))
def get_value():
global global_variable
return global_variable
def set_value(new_value):
global global_variable
global_variable = new_value
global_variable = -1
print('before set_value(), get_value() = [%s]' % get_value())
set_value(new_value=-2)
print('after set_value(), get_value() = [%s]' % get_value())
processPool = multiprocessing.Pool(processes=5)
processPool.map(func=worker, iterable=range(15))
Çıktı:
before set_value(), get_value() = [-1]
after set_value(), get_value() = [-2]
pid=[53970] old_value=[-2] new_value=[ 0] get_value=[23]
pid=[53971] old_value=[-2] new_value=[ 1] get_value=[42]
pid=[53970] old_value=[23] new_value=[ 4] get_value=[50]
pid=[53970] old_value=[50] new_value=[ 6] get_value=[14]
pid=[53971] old_value=[42] new_value=[ 5] get_value=[31]
pid=[53972] old_value=[-2] new_value=[ 2] get_value=[44]
pid=[53973] old_value=[-2] new_value=[ 3] get_value=[94]
pid=[53970] old_value=[14] new_value=[ 7] get_value=[21]
pid=[53971] old_value=[31] new_value=[ 8] get_value=[34]
pid=[53972] old_value=[44] new_value=[ 9] get_value=[59]
pid=[53973] old_value=[94] new_value=[10] get_value=[87]
pid=[53970] old_value=[21] new_value=[11] get_value=[21]
pid=[53971] old_value=[34] new_value=[12] get_value=[82]
pid=[53972] old_value=[59] new_value=[13] get_value=[ 4]
pid=[53973] old_value=[87] new_value=[14] get_value=[70]
Anlaşıldığı gibi, cevap her zaman basittir.
İşte bir main
tanımda göstermenin basit bir yoluna sahip küçük bir örnek modül :
def five(enterAnumber,sumation):
global helper
helper = enterAnumber + sumation
def isTheNumber():
return helper
Bir main
tanımda nasıl gösterileceği aşağıda açıklanmıştır :
import TestPy
def main():
atest = TestPy
atest.five(5,8)
print(atest.isTheNumber())
if __name__ == '__main__':
main()
Bu basit kod aynı şekilde çalışır ve yürütülür. Umut ediyorum bu yardım eder.
global_vars
verileri init_global_vars
başlatıyorum. Sonra, sadece tanımlanmış her global var. Umarım bunu birden fazla kez değerlendirebilirim! Teşekkürler Peter!
Kullanmak istediğiniz her işlevde global değişkene başvurmanız gerekir.
Aşağıdaki gibi:
var = "test"
def printGlobalText():
global var #wWe are telling to explicitly use the global version
var = "global from printGlobalText fun."
print "var from printGlobalText: " + var
def printLocalText():
#We are NOT telling to explicitly use the global version, so we are creating a local variable
var = "local version from printLocalText fun"
print "var from printLocalText: " + var
printGlobalText()
printLocalText()
"""
Output Result:
var from printGlobalText: global from printGlobalText fun.
var from printLocalText: local version from printLocalText
[Finished in 0.1s]
"""
Global olanı yerel bir değişkende saklamıyorsunuz, sadece orijinal global referansınızın başvurduğu nesneye yerel bir referans oluşturuyorsunuz. Python'daki hemen hemen her şeyin bir nesneye atıfta bulunan bir isim olduğunu ve normal işlemde hiçbir şeyin kopyalanmadığını unutmayın.
Bir tanımlayıcının önceden tanımlanmış bir global değere ne zaman başvuracağını açıkça belirtmeniz gerekmediyse, muhtemelen tanımlayıcının ne zaman yeni bir yerel değişken olduğunu açıkça belirtmeniz gerekir (örneğin, 'var' komutu gibi bir şeyle) JavaScript'te görüldü). Ciddi ve önemsiz olmayan sistemlerde yerel değişkenler küresel değişkenlerden daha yaygın olduğundan, Python'un sistemi çoğu durumda daha mantıklıdır.
Sen olabilir o var ya o olmasaydı yerel bir değişken oluşturmak eğer küresel bir değişkeni kullanarak, tahmin girişiminde bulunan dili var. Ancak, bu hataya çok açıktır. Örneğin, başka bir modülün içe aktarılması yanlışlıkla programınızın davranışını değiştirerek bu ada göre global bir değişken oluşturabilir.
Bunu dene:
def x1():
global x
x = 6
def x2():
global x
x = x+1
print x
x = 5
x1()
x2() # output --> 7
Aynı ada sahip bir yerel değişkeniniz varsa, bu globals()
işlevi kullanmak isteyebilirsiniz .
globals()['your_global_var'] = 42
Eklentiyi izleyip eklerken, yerel olarak bildirilen tüm genel değişkenleri içerecek bir dosya kullanın ve ardından import as
:
Dosya initval.py :
Stocksin = 300
Prices = []
Dosya getstocks.py :
import initval as iv
def getmystocks():
iv.Stocksin = getstockcount()
def getmycharts():
for ic in range(iv.Stocksin):
import ... as ...
? Neden sadece import ...
?
global
:-) => +1 :-) anahtar kelimesini kullanmaya gerek yok. Lütfen diğer kişilerin de sahip olabileceği bu sorgulamaları netleştirmek için cevabınızı düzenleyin. Şerefe
Genel dizinin açık öğelerine yazmak, genel olarak bildirime ihtiyaç duymaz, ancak buna "toptan satış" yazmak için şu gereksinime sahiptir:
import numpy as np
hostValue = 3.14159
hostArray = np.array([2., 3.])
hostMatrix = np.array([[1.0, 0.0],[ 0.0, 1.0]])
def func1():
global hostValue # mandatory, else local.
hostValue = 2.0
def func2():
global hostValue # mandatory, else UnboundLocalError.
hostValue += 1.0
def func3():
global hostArray # mandatory, else local.
hostArray = np.array([14., 15.])
def func4(): # no need for globals
hostArray[0] = 123.4
def func5(): # no need for globals
hostArray[1] += 1.0
def func6(): # no need for globals
hostMatrix[1][1] = 12.
def func7(): # no need for globals
hostMatrix[0][0] += 0.33
func1()
print "After func1(), hostValue = ", hostValue
func2()
print "After func2(), hostValue = ", hostValue
func3()
print "After func3(), hostArray = ", hostArray
func4()
print "After func4(), hostArray = ", hostArray
func5()
print "After func5(), hostArray = ", hostArray
func6()
print "After func6(), hostMatrix = \n", hostMatrix
func7()
print "After func7(), hostMatrix = \n", hostMatrix
Bunu diğer cevapların hiçbirinde görmediğim için ekliyorum ve benzer bir şeyle mücadele eden biri için yararlı olabilir. globals()
İşlevi, bir değişken küresel bir simge sözlüğü döner nerede kodunun geri kalanı için kullanılabilir yapabilirsiniz "sihirli" marka verileri. Örneğin:
from pickle import load
def loaditem(name):
with open(r"C:\pickle\file\location"+"\{}.dat".format(name), "rb") as openfile:
globals()[name] = load(openfile)
return True
ve
from pickle import dump
def dumpfile(name):
with open(name+".dat", "wb") as outfile:
dump(globals()[name], outfile)
return True
Değişkenleri genel ad alanının dışına ve dışına dökmenize izin verir. Süper uygun, muss yok, karışıklık yok. Sadece Python 3 olduğundan eminim.
globals()
her zaman yerel bağlamda kullanılabilir globalleri döndürür, bu nedenle buradaki bir mutasyon başka bir modüle yansıtmayabilir.
Değişikliğin görünmesini istediğiniz sınıf ad alanına başvurun.
Bu örnekte runner, config dosyasından max kullanıyor . Testimin runner kullanırken max değerini değiştirmesini istiyorum .
Ana / config.py
max = 15000
Ana / runner.py
from main import config
def check_threads():
return max < thread_count
Testler / runner_test.py
from main import runner # <----- 1. add file
from main.runner import check_threads
class RunnerTest(unittest):
def test_threads(self):
runner.max = 0 # <----- 2. set global
check_threads()
Bir tarafta Windows / Mac OS ve diğer tarafta Linux gibi farklı platformlarda / ortamlarda çoklu işlemle bağlantılı küreseller zahmetlidir.
Bunu size, bir süre önce karşılaştığım bir sorunu gösteren basit bir örnekle göstereceğim.
Windows / MacOs ve Linux'ta neden farklı olduğunu anlamak istiyorsanız, bilmeniz gereken yeni bir işlem başlatmak için varsayılan mekanizma ...
Bellek tahsisi başlatma işleminde farklıdırlar ... (ama buraya girmiyorum).
Soruna bir göz atalım / örnek ...
import multiprocessing
counter = 0
def do(task_id):
global counter
counter +=1
print(f'task {task_id}: counter = {counter}')
if __name__ == '__main__':
pool = multiprocessing.Pool(processes=4)
task_ids = list(range(4))
pool.map(do, task_ids)
Bunu Windows'ta çalıştırırsanız (Ve sanırım MacOS'ta da), aşağıdaki çıktıyı alırsınız ...
task 0: counter = 1
task 1: counter = 2
task 2: counter = 3
task 3: counter = 4
Bunu Linux'ta çalıştırırsanız, bunun yerine aşağıdakileri elde edersiniz.
task 0: counter = 1
task 1: counter = 1
task 2: counter = 1
task 3: counter = 1