Soru Bir fonksiyonda global değişkenlerin kullanılması


Bir işlevde global bir değişken nasıl oluşturabilir veya kullanabilirim?

Tek bir işlevde global bir değişken oluşturursam, bu global değişkeni başka bir işlevde nasıl kullanabilirim? Global değişkeni, erişimine ihtiyacı olan işlevin yerel değişkeninde saklamak zorunda mıyım?


2478
2018-01-08 05:45


Menşei




Cevaplar:


Bir global değişkeni, diğer işlevlerde bunu, global ona atanan her işlevde:

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 sebebi, küresel değişkenlerin çok tehlikeli olmasından dolayı, Python'un, oyunun ne olduğunu açıkça anladığınızı bildiğinizden emin olmak istediğini düşünüyorum. global Anahtar kelime.

Genel bir değişkeni modüllerde paylaşmak istiyorsanız diğer cevaplara bakın.


3509
2018-01-08 08:39



Küresellere "çok tehlikeli" denen aşırı abartıdır. Globals, şimdiye kadar var olan ve var olan her dilde mükemmel derecede iyidir. Onların yeri var. Söylemeniz gereken şey, nasıl program yapacağınız konusunda hiçbir fikriniz yoksa sorunlara neden olabilir. - Anthony
Bence oldukça tehlikelidirler. Ancak python'da "global" değişkenler aslında bir çok sorunu çözen modül seviyesidir. - Fábio Santos
Python'un nedenini gerektirdiğine katılmıyorum. global anahtar kelime, çünkü globals tehlikelidir. Aksine, dil, değişkenleri açıkça bildirmenizi gerektirmez ve otomatik olarak atadığınız bir değişkenin, aksi belirtilmedikçe işlev kapsamına sahip olduğunu varsayar. global anahtar kelime, aksi belirtilmedikçe sağlanan araçlardır. - Nate C-K
Global değişkenler, profesyonel olarak kullandığım her dilde bir tasarım kokusu. Üç boole alan bir işleviniz olduğunu varsayalım: Kontrol etmek için 8 olası kod yolu. Aynı sayıda boole yayı ile 3 işleviniz varsa, 24 olası kod yolu. Ardından tek bir boolean global değişkeni ekleyin, şimdi 24 ^ 2 olası kod yoluna bakıyorsunuz çünkü TÜM fonksiyonların bu global değişkenin durumunu değiştirme yeteneğine sahip olduğunu hesaba katmanız gerekiyor. Bu yüzden fonksiyonel programlama teknikleri popüler hale gelmiştir. - avgvstvs
@LightnessRacesinOrbit Senin puanını anlamıyorum. Küresel bir değişkeni kaldırırsanız, şu anda karmaşık faktörü ortadan kaldırırsınız. keyfi işlevler artık program durumunu değiştiremezYürütmenin çeşitli noktalarında - dolayısıyla, bu değişkeni kullanan diğer işlevlere başka şekilde algılanamayacak şekilde yürütmeyi değiştirir. Artık takip etmek zorunda değilsiniz, " f2() durumu şimdi değiştir f3() beklenmedik bir şey yapabilir mi? Fonksiyonlar artık harici program durumuna agnostik olarak çalışabilir. - avgvstvs


Durumunuzu doğru anlıyorsam, gördüğünüz şey Python'un yerel (işlev) ve global (modül) ad alanlarını nasıl işlediğinin sonucudur.

Bunun gibi bir modül olduğunu varsayalım:

# sample.py
myGlobal = 5

def func1():
    myGlobal = 42

def func2():
    print myGlobal

func1()
func2()

Bunu 42 yazdırmak için bekliyor olabilirsiniz, ancak bunun yerine 5. yazdırır.global'beyanı func1(), sonra func2() 42 yazdıracaktır.

def func1():
    global myGlobal
    myGlobal = 42

Burada olan şey, Python’un atandıBir işlev içinde herhangi bir yerde, aksi açıkça belirtilmediği sürece bu işleve yereldir. Eğer sadece okuma Bir addan ve ad yerel olarak mevcut değilse, adı herhangi bir kapsamda (örneğin, modülün genel kapsamı) aramaya çalışır.

Adına 42 tane atadığınızda myGlobalbu nedenle, Python aynı adın global değişkenini gölgeleyen yerel bir değişken oluşturur. Bu yerel kapsam dışı ve çöp toplama işlemine ne zaman func1() döner; o esnada, func2() (değiştirilmemiş) küresel addan başka bir şey göremez. Bu ad alanı kararının, çalışma zamanında değil derleme zamanında gerçekleştiğini unutmayın. myGlobal içeride func1() atamadan önce bir UnboundLocalErrorÇünkü Python zaten bir yerel değişken olması gerektiğine karar verdi, ancak henüz onunla ilişkili herhangi bir değeri yoktu. Ama 'kullanarakglobaldeyim, Python'a, yerel olarak ona vermek yerine ismin başka bir yerde görünmesi 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'un VM'si her seferinde bir fonksiyona yeni bir isim atandığında en az üç isim araması yapmak zorunda kalacaktır (ismin yapılmadığından emin olmak için) t, çok yaygın bir işlemi önemli ölçüde yavaşlatan modül / yerleşik seviyesinde zaten var.)


661
2018-01-08 09:19



Ad alanı kararının şu anda gerçekleştiğini belirttiniz. Derleme zamanı, Bunun doğru olduğunu düşünmüyorum. python’un derlemesini öğrendiklerimden sadece sözdizimi hatası, isim hatası değil kontrol eder bu örneği dene def A (): x + = 1eğer koşmazsan, olacak UnboundLocalError vermek değil, lütfen doğrulayın - watashiSHUN
Genel değişkenler için büyük harf kullanmak yaygındır. MyGlobal = 5 - Vassilis
@watashiSHUN: İsim alanı kararı yapar derleme zamanında olur. Buna karar vermek x Yerel ad, ilk kez kullanılmadan önce yerel değerin bir değere bağlı olması durumunda çalışma zamanında kontrol etmekten farklıdır. - BlackJack
@Vassilis: Büyük harf için yaygındır herşey harfler: MY_GLOBAL = 5. Bakın Python Kodu için Stil Kılavuzu. - BlackJack
@BlackJack, evet dostum, haklısın! (Ben c alıyorum) - Vassilis


Kavramını keşfetmek isteyebilirsiniz ad. Python’da modül için doğal bir yer global veri:

Her modülün, modülde tanımlanan tüm işlevler tarafından global sembol tablosu olarak kullanılan kendi özel sembol tablosu vardır. Böylelikle, bir modülün yazarı, bir kullanıcının küresel değişkenleri ile kazara meydana gelen çarpışmalardan endişe etmeden modüldeki global değişkenleri kullanabilir. Öte yandan, ne yaptığınızı biliyorsanız, bir modülün global değişkenlerine, işlevlerine başvurmak için kullanılan aynı notaja dokunabilirsiniz. modname.itemname.

Global-in-a-module'nin belirli bir kullanımı burada açıklanmıştır - nasıl-do-i-paylaşım-küresel-değişkenler-genelinde-modüllerve tamlık için içerik burada paylaşılır:

Tek bir program içinde modüller arasında bilgi paylaşmanın kuralsal yolu, özel bir yapılandırma modülü (genellikle config veya cfg olarak adlandırılır) oluşturmaktır. Konfigürasyon modülünü uygulamanızın tüm modüllerine aktarın; Modül daha sonra küresel bir isim olarak kullanılabilir hale gelir. Her bir modülün yalnızca bir örneği olduğu için, modül nesnesinde yapılan tüm 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

175
2018-01-08 05:59



bir sebepten dolayı sevmiyorum config.x  ondan kurtulabilir miyim? Ben geldim x = lambda: config.x ve sonra bende yeni değeri x(). bir sebepten dolayı a = config.x benim için hile yapmaz. - vladosaurus


Python, yerel ve global arasında bir değişkeni hangi kapsamda yüklemesi gerektiğine karar vermek için basit bir sezgisel kullanır. Bir ödevin sol tarafında bir değişken adı görünür, ancak global olarak bildirilmemişse, yerel olarak kabul edilir. Bir ödevin sol tarafında görünmüyorsa, genel olarak kabul edilir.

>>> 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 nasıl yapıldığını görün foo(), sadece LOAD_FAST değişken.


75
2017-07-12 12:35



Buluşsal arar bağlama işlemleri. Atama, böyle bir işlemdir, diğerini içe aktarır. Ama bir hedef for döngü ve sonra adı as içinde with ve except ifadeler de bağlı. - Martijn Pieters♦


Bir işlevde global değişkene başvurmak isterseniz, global hangi değişkenlerin global olduğunu bildiren anahtar kelime. Her durumda onu kullanmak zorunda değilsiniz (burada yanlış iddiada olduğu gibi) - eğer bir ifadede atıfta bulunulan isim yerel kapsamda veya bu işlevin tanımlandığı işlevlerde kapsamda bulunamıyorsa, bu durum global olarak araştırılır. değişkenler.

Ancak, işlev olarak global olarak bildirilmeyen yeni bir değişken atarsanız, bu durum yerel olarak örtük olarak bildirilir ve aynı adla var olan tüm global değişkenleri gölgeleyebilir.

Ayrıca, küresel değişkenler, özellikle OOP'un aşırı kalabalık olduğu küçük senaryolar için, aksi iddia eden bazı OOP zenginliklerine aykırıdır.


48
2018-01-08 09:03





Zaten mevcut cevaplara ek olarak ve bunu daha kafa karıştırıcı hale getirmek için:

Python'da, yalnızca bir işlevin içinde başvurulan değişkenler vardır.    dolaylı küresel. Bir değişkene her yerde yeni bir değer atanmışsa   İşlev gövdesinde, bir yerel. Eğer bir değişken   işlev içinde hiç yeni bir değer atanmış, değişken   dolaylı olarak yerel ve açıkça "global" olarak bildirmeniz gerekiyor.

İlk başta biraz şaşırtıcı olsa da, bir andaki düşünce açıklıyor   bu. Bir yandan, atanan değişkenler için global gereksinim duyulması,   istenmeyen yan etkilere karşı çubuk. Öte yandan, küresel olsaydı   tüm global referanslar için gerekli, tüm dünyayı kullanıyor olmanız   zaman. Yerleşik tüm referansları global olarak ilan etmeniz gerekir   işlev veya içe aktarılmış bir modülün bir bileşeni. Bu dağınıklık   Tanımlama için küresel deklarasyonun yararlılığını yenmek   yan etkiler.

Kaynak: Python'da yerel ve global değişkenler için kurallar nelerdir?.


36
2017-07-04 10:23





Bir işlevde global 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şlevin yazılması aslında kodunu çalıştırmaz. Biz diyoruz create_global_variable fonksiyon:

>>> create_global_variable()

Modifikasyon olmadan globals kullanmak

Hangi nesneyi göstereceğ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!!!'

Global değişkenin bir fonksiyonun içinden değiştirilmesi

Global değişkeni farklı bir nesneyle göstermek 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 şimdi puan 'Bar':

>>> use_global_variable()
'Bar!!!'

Python'daki "global" in gerçekten küresel olmadığını unutmayın - sadece modül seviyesinde küreseldir. Bu yüzden sadece global olduğu modüllerde yazılmış işlevler için kullanılabilir. Fonksiyonlar, yazıldıkları modülü hatırlar, böylece diğer modüller içine aktarıldığında, hala global değişkenleri bulmak için oluşturuldukları modülü ararlar.

Aynı ada sahip yerel değişkenler

Aynı ada sahip bir yerel değişken oluşturursanız, global bir değişken gölgeler:

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, 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 bilmedikçe ve bunu yapmak için çok iyi bir nedeniniz olmadıkça, yerel değişkenleri globals ile aynı isimlerle kullanmaktan kaçınmanız gerektiğini unutmayın. Henüz böyle bir sebeple karşılaşmadım.


31
2018-01-01 19:55





Paralel yürütme ile, ne olduğunu anlamazsanız, global değişkenler beklenmedik sonuçlara neden olabilir. İşte, çok işlemli bir global değişken kullanmanın bir örneğidir. Her sürecin, değişkenin kendi kopyasıyla birlikte ç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]

28
2017-10-03 05:41





Kullanmak istediğiniz her işlevde global değişkeni referans almanı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]
"""

19
2017-12-20 12:45



'kullanmak istediğiniz her işlevde' doğru olmayan bir şekilde yanlıştır: 'istediğiniz her işleve güncelleştirme' - spazm


Demek istediğin bu yöntemi kullanmak:

globvar = 5

def f():
    var = globvar
    print(var)

f()  # Prints 5

Ama daha iyi bir yol, küresel değişkeni bu şekilde kullanmaktır:

globavar = 5
def f():
    global globvar
    print(globvar)
f()   #prints 5

Her ikisi de aynı çıktıyı verir.


19
2017-12-04 06:27



İlk kod bir sözdizimi hatası verir. - Fermi paradox
Teşekkürler @Fermiparadox Düzenlemeyi yaptım. - gxyd