Python'da "global" anahtar kelimenin kullanımı


285

Belgeleri okumaktan anladığım şey, Python'un işlevler için ayrı bir ad alanına sahip olması ve bu işlevde genel bir değişken kullanmak istiyorsam kullanmam gerekiyor global.

Python 2.7 kullanıyorum ve bu küçük testi denedim

>>> sub = ['0', '0', '0', '0']
>>> def getJoin():
...     return '.'.join(sub)
...
>>> getJoin()
'0.0.0.0'

Görünüşe göre işler sorunsuz çalışıyor global. Global değişkene sorunsuzca ulaşabildim.

Bir şey eksik mi? Ayrıca, aşağıdaki Python belgelerinden alınmıştır:

Genel ifadede listelenen adlar, resmi parametreler olarak veya bir döngü denetimi hedefi, sınıf tanımı, işlev tanımı veya içe aktarma ifadesinde tanımlanmamalıdır.

Biçimsel parametreler ve sınıf tanımı benim için anlamlı olsa da, döngü kontrol hedefi ve fonksiyon tanımı üzerindeki kısıtlamayı anlayamıyorum.


1
Ben küresel anahtar kelime kullanımını gerektiren php ile karışık olduğunu düşünüyorum - python docs bunu onaylamak - temelde yerel olarak tanımlanmış değilse küresel olarak kabul edilir
tobyodavies 14:11

11
İfadenize dikkat edin: Python'un işlevler için ayrı bir ad alanı yoktur (bu, sahip olabileceğiniz def foo(): ...ve foo = ...aynı zamanda olabileceği anlamına gelir ). Her işlev çağrısı için yeni bir kapsam oluşturur. (Peki bu, dünyadaki diğer tüm uzaktan üst düzey dillerden nasıl farklıdır?)

Yanıtlar:


366

Anahtar kelime globalyalnızca global değişkenleri yerel bağlamda değiştirmek veya oluşturmak için yararlıdır, ancak global değişkenler oluşturmak nadiren iyi bir çözüm olarak kabul edilir.

def bob():
    me = "locally defined"    # Defined only in local context
    print(me)

bob()
print(me)     # Asking for a global variable

Yukarıdakiler size verecektir:

locally defined
Traceback (most recent call last):
  File "file.py", line 9, in <module>
    print(me)
NameError: name 'me' is not defined

İfadeyi kullanırsanız, globaldeğişken fonksiyonun kapsamı dışında "etkin" olacak ve etkin bir şekilde global bir değişken haline gelecektir.

def bob():
    global me
    me = "locally defined"   # Defined locally but declared as global
    print(me)

bob()
print(me)     # Asking for a global variable

Yukarıdaki kod size verecektir:

locally defined
locally defined

Ayrıca, python'un doğası nedeniyle, globalişlevleri, sınıfları veya diğer nesneleri yerel bağlamda bildirmek için de kullanabilirsiniz . Her ne kadar bir şeyler ters giderse veya hata ayıklamaya ihtiyaç duyuyorsa kabuslara neden olduğu için buna karşı tavsiye ederim.


59
Bu bağlamdaki "global" ifadesi "global" olarak kabul edilen diğer dillerden farklı görünmektedir. Python'da "global" bir referans hala modülün sınırları içindedir ve bu modülün dışından beklendiği gibi "global_var" yerine "module.global_var" olarak referans verilmesi gerekir.
meyve suyu

17
@juice - Python'da, globalstüm ad alanlarında otomatik olarak tanımlanan mutlak (şükür) diye bir şey yoktur . Doğru bir şekilde işaret ettiğiniz gibi, bir global bir modül içindeki bir ad alanına bağlıdır, ancak başka bir modüle from module import variableveya olarak alınabilir import module.variable. İlk durumda, içe aktarma, değişkeni variablereferans gerektirmeden erişilebilir hale getirir module.. Modül kapsamında bir global olarak kabul edilirse, ithal edildiği yere bağlı olacaktır. Ayrıca nonlocal, python 3'te yeni bir kapsamla ilgili anahtar kelime olarak da bakın
2013'te

3
Global değişkenlerin neden iyi bir çözüm olmadığını açıklayabilir misiniz? Bunu sık sık duyuyorum, ama şu anki projemde tam olarak yapmam gerekenleri yapıyorlar. Düşündüğüm daha uğursuz bir şey var mı?
Robin Newhouse

5
@RobinNewhouse SO hakkında bu konuyu ve diğer SO olmayan makaleleri kapsayan birkaç soru var .
16'da unode

213

Global değişkenlere globalanahtar kelime olmadan erişebilirsiniz , ancak bunları değiştirmek isterseniz globalanahtar kelimeyi kullanmanız gerekir . Örneğin:

foo = 1
def test():
    foo = 2 # new local foo

def blub():
    global foo
    foo = 3 # changes the value of the global foo

Sizin durumunuzda, sadece listeye erişiyorsunuz sub.


3
Tek bir uyarı ile: foo = 3global işler olmadan, ancak foo blubfonksiyon kapsamında yerel olarak tekrar tanımlanır ve orijinal foo değişkenini değiştirmez. Bu benim için oldukça kafa karıştırıcıydı.
chhantyal

1
@chhantyal eğer çalışırsa bir hata atmadığını kastediyorsanız, haklısınız, ancak Ivo Wetzel'in bağlamında amaçlandığı gibi çalışmaz. Bu tür davranışlar için kullanımlar vardır, ancak programcının istediği şey genellikle bu değildir.
democidist

77

Bu, isme erişme ve bir kapsam içinde bağlama arasındaki farktır .

Değerini okumak için sadece bir değişken arıyorsanız, hem küresel hem de yerel kapsama erişebilirsiniz.

Ancak adı yerel kapsamda, sen edilir değil mi bir değişkene atarsanız bağlama (ve bu ad aynı zamanda küresel bir şekilde varsa, o gizleriz) bu kapsamda içine bu ismi.

Genel ada atamak istiyorsanız, ayrıştırıcıya yeni bir yerel ad bağlamak yerine genel adı kullanmasını söylemeniz gerekir - bu 'global' anahtar kelimenin yaptığı şeydir.

Bir blok içinde herhangi bir yere bağlanma, o bloktaki her yerde adın bağlanmasına neden olur, bu da bazı garip görünümlü sonuçlara neden olabilir (örn. UnboundLocalError aniden daha önce çalışan kodda görünebilir).

>>> a = 1
>>> def p():
    print(a) # accessing global scope, no binding going on
>>> def q():
    a = 3 # binding a name in local scope - hiding global
    print(a)
>>> def r():
    print(a) # fail - a is bound to local scope, but not assigned yet
    a = 4
>>> p()
1
>>> q()
3
>>> r()
Traceback (most recent call last):
  File "<pyshell#35>", line 1, in <module>
    r()
  File "<pyshell#32>", line 2, in r
    print(a) # fail - a is bound to local scope, but not assigned yet
UnboundLocalError: local variable 'a' referenced before assignment
>>> 

çok
mantıksız

52

Diğer cevaplar sorunuza cevap veriyor. Python'daki isimler hakkında bilinmesi gereken bir diğer önemli şey, kapsam başına bazda yerel veya küresel olmalarıdır.

Bunu düşünün, örneğin:

value = 42

def doit():
    print value
    value = 0

doit()
print value

Muhtemelen value = 0ifadenin yerel bir değişkene atayacağını ve doit()işlevin dışında bildirilen aynı değişkenin değerini etkilemeyeceğini tahmin edebilirsiniz . Yukarıdaki kodun çalışmadığını keşfetmek daha şaşırtıcı olabilir . print valueİşlevin içindeki ifade birUnboundLocalError.

Bunun nedeni, Python'un işlevin başka bir yerinde adı atadığınızı valueve valuehiçbir yerde bildirilmediğini fark etmesidir global. Bu onu yerel bir değişken yapar. Ancak yazdırmaya çalıştığınızda, yerel ad henüz tanımlanmadı. Bu durumda Python, diğer bazı dillerde olduğu gibi adı global bir değişken olarak aramaya geri dönmez . Aslında, işlevin herhangi bir yerinde aynı ada sahip bir yerel değişken tanımladıysanız, genel bir değişkene erişemezsiniz .


1
Bunu işaret ettiğiniz için teşekkürler. Bu nedenle, yerel kapsamınız dışında bulunan bir ada atamadığı sürece, yerel kapsamdaki başvurular dış adı kullanır. Ancak, işlevinizin herhangi bir yerinde bu ada atadığınız takdirde, o yerel kapsamdaki başvurular, yerel atamadan önce bile dışarıya bakmaz.
Dmitry Minkovsky

1
Kesinlikle, anladın. global(veya nonlocalPython 3.x sürümünde) bu davranışı geçersiz kılar ve harici adı yeniden atamanıza olanak tanır.
kindall

2
Diğer dillerde, bu "kaldırma" olarak adlandırılıyor gibi görünüyor, örneğin: github.com/shichuan/javascript-patterns/blob/master/…
Dmitry Minkovsky

Yaralanma hakaret eklemek için, değişkenler anahtar kelime yeni JavaScript ilan letedilir değil hoisted.
17'de tür

Bildirilen global bir değişkene erişmek daha mı hızlı globalveya önemli değil mi?
mato

14

Bir ada erişmek ve bir isim atamak farklıdır. Sizin durumunuzda sadece bir isme erişiyorsunuz.

Bir işlev içindeki bir değişkene atarsanız, global olarak bildirmediğiniz sürece bu değişkenin yerel olduğu varsayılır. Bunun yokluğunda küresel olduğu varsayılır.

>>> x = 1         # global 
>>> def foo():
        print x       # accessing it, it is global

>>> foo()
1
>>> def foo():   
        x = 2        # local x
        print x 

>>> x            # global x
1
>>> foo()        # prints local x
2

7
  • Global anahtar kelimelere anahtar kelime olmadan erişebilirsiniz global
  • Bunları değiştirebilmek için anahtar kelimenin global olduğunu açıkça belirtmeniz gerekir. Aksi takdirde, anahtar kelime yerel kapsamda beyan edilir.

Misal:

words = [...] 

def contains (word): 
    global words             # <- not really needed
    return (word in words) 

def add (word): 
    global words             # must specify that we're working with a global keyword
    if word not in words: 
        words += [word]

2

Bir işlevin dışında bildirilen herhangi bir değişkenin global olduğu varsayılır; yalnızca bunları işlevlerin içinden (yapıcılar hariç) bildirirken, değişkenin genel olduğunu belirtmeniz gerekir.


1

Bu Python SSS bölümünde iyi açıklanmıştır

Python'daki yerel ve global değişkenler için kurallar nelerdir?

Python'da, yalnızca bir işlev içinde başvurulan değişkenler dolaylı olarak geneldir. Bir değişkene, işlev gövdesinin herhangi bir yerinde bir değer atanırsa, açıkça genel olarak bildirilmedikçe yerel olarak kabul edilir.

İlk başta biraz şaşırtıcı olsa da, bir anın düşüncesi bunu açıklıyor. Bir yandan, globalatanan değişkenlere ihtiyaç duyulması, istenmeyen yan etkilere karşı bir çubuk sağlar. Öte yandan, globaltüm global referanslar için gerekli olsaydı , globalher zaman kullanırsınız. Yerleşik globalbir işleve veya içe aktarılan modülün bir bileşenine yapılan her başvuru olarak bildirmeniz gerekir . Bu karışıklık, globalyan etkilerin tanımlanması için bildirimin yararlılığını bozacaktır .

https://docs.python.org/3/faq/programming.html#what-are-the-rules-for-local-and-global-variables-in-python


0

Bu, aşağıdakileri yapmamanız gerektiği anlamına gelir:

x = 1

def myfunc():
  global x

  # formal parameter
  def localfunction(x):
    return x+1

  # import statement
  import os.path as x

  # for loop control target
  for x in range(10):
    print x

  # class definition
  class x(object):
    def __init__(self):
      pass

  #function definition
  def x():
    print "I'm bad"

ikostia, global kullandığınız için 'x' kullanamayacağınız her şeyi numaralandırıyor - docs.python.org/reference/…
pycruft

1
@Unode: Sadece NikhilRathod'un sözünde verdiği tüm davaları kötülüyorum.
ikostia

0

Global değişkeni "Global" yapar

def out():
    global x
    x = 1
    print(x)
    return


out()

print (x)

Bu, 'x' işlevinin dışında normal bir değişken gibi davranır. Globali çıkarırsanız, bir fonksiyonun içindeki bir değişkeni yazamadığı için hata verir.

def out():
     # Taking out the global will give you an error since the variable x is no longer 'global' or in other words: accessible for other commands
    x = 1
    print(x)
    return


out()

print (x)
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.