Python işlevi global değişkenler?


272

Küresel değişkenleri ilk etapta böyle bir karışıklık nedeniyle kullanmaktan kaçınmam gerektiğini biliyorum, ama bunları kullanacak olsaydım, bunları kullanmak için geçerli bir yol var mı? (Ayrı bir işlevde oluşturulan değişkenin genel kopyasını çağırmaya çalışıyorum.)

x = "somevalue"

def func_A ():
   global x
   # Do things to x
   return x

def func_B():
   x = func_A()
   # Do things
   return x

func_A()
func_B()

Does xikinci fonksiyon kullanımları küresel kopyanın aynı değere sahip olmasını xo func_akullanımlar ve tuşelere? Tanımdan sonra işlevleri çağırırken, sipariş önemli mi?


1
işlevinizde atanmış bir değişkeniniz olduğu için, python'un atamadan önce referansları bu şekilde ele alacağını varsaymamaya da dikkat edin. İlk atamaya kadar, x'i kullandıysanız, küresel atama veya yerel atama olmazdı. Yüzünde rezil UnboundLocalError istisnasını alacaksın :)
osirisgothra

Yanıtlar:


412

Sadece global bir değişkene erişmek istiyorsanız ismini kullanmanız yeterlidir. Ancak değerini değiştirmek için globalanahtar kelimeyi kullanmanız gerekir .

Örneğin

global someVar
someVar = 55

Bu, global değişkenin değerini 55 olarak değiştirir. Aksi takdirde, yerel bir değişkene sadece 55 atar.

İşlev tanımı listelerinin sırası önemli değildir (birbirlerine bir şekilde atıfta bulunmadıkları varsayılarak), çağrıldıkları sıra önemlidir.


2
Verdiğim kodda, func_B x'in global kopyasına (func_A'dan elde edildiği gibi), (2) func_A sonucunun aynı değerine sahip yerel bir x değişkenine (1) veya (3) değeri olmayan bir yerel değişken x ve (derleyicinin gözünde) "bir değer" veya func_A'daki x ile bir ilişkisi yok mu?
Akshat Shekhar

xiçinde func_Bçağrının döndürdüğü değer onun değerini alır yerel değişkendir için func_A- ben ki bu, onun senin (2) yapacak tahmin
Levon

tamam, diyelim ki x, func_A tarafından üretilen bir tür rastgele bir sekanstı (yani func_A her çalıştırıldığında farklı bir x üretti.) Programı yazılı olarak çalıştırmak, func_b'i func_a olduğunda orijinal olarak üretilenden farklı bir x değiştirir. aranan? Öyleyse, nasıl düzeltebilirim?
Akshat Shekhar

1
Evet, func_Aher çalışma sırasında genel değişkeni değiştirir func_Bve kullanmaya geri döndürürse , func_Bher seferinde değişen bir değerle çalışır. "Nasıl düzeltebilirim" konusunda emin değilim. Mevcut / orijinal sorunuza en yararlı yanıtı kabul etmek ve ardından bir takip sorusuna neye benzediğiyle ilgili farklı bir soru açmayı düşünebilirsiniz.
Levon

1
Aslında x'in ne olduğuna bağlı. X değişmezse, func_B içindeki x aynı kalır, çünkü aynı değere sahip olsalar bile yerel olarak bildirilir. Bu, tuples, ints için geçerlidir ... Örneğin, bir listenin örneğiyse ve bunu yaparsanız x.append("..."), değiştirilen global değişken x değişkendir, çünkü yerel olan küresel olanı referans alır.
jadkik94

111

Python kapsamında zaten bu kapsamda bildirilen bir değişkene atama yeni bir yerel değişkeni oluşturur sürece o değişken anahtar kelime ile global kapsamlı değişkene atıfta daha önceki işlevinde bildirildi global.

Ne olacağını görmek için sahte kodunuzun değiştirilmiş bir versiyonuna bakalım:

# Here, we're creating a variable 'x', in the __main__ scope.
x = 'None!'

def func_A():
  # The below declaration lets the function know that we
  #  mean the global 'x' when we refer to that variable, not
  #  any local one

  global x
  x = 'A'
  return x

def func_B():
  # Here, we are somewhat mislead.  We're actually involving two different
  #  variables named 'x'.  One is local to func_B, the other is global.

  # By calling func_A(), we do two things: we're reassigning the value
  #  of the GLOBAL x as part of func_A, and then taking that same value
  #  since it's returned by func_A, and assigning it to a LOCAL variable
  #  named 'x'.     
  x = func_A() # look at this as: x_local = func_A()

  # Here, we're assigning the value of 'B' to the LOCAL x.
  x = 'B' # look at this as: x_local = 'B'

  return x # look at this as: return x_local

Aslında, tüm func_Bdeğişkenler ile yeniden yazabilirsiniz x_localve aynı şekilde çalışır.

Sıra yalnızca işlevlerinizin global x'in değerini değiştiren işlemleri gerçekleştirdiği sıraya göre önemlidir. Böylece örneğimizde, func_Bçağrılar olduğu için düzen önemli değildir func_A. Bu örnekte, düzen önemlidir:

def a():
  global foo
  foo = 'A'

def b():
  global foo
  foo = 'B'

b()
a()
print foo
# prints 'A' because a() was the last function to modify 'foo'.

globalYalnızca genel nesneleri değiştirmek için gerekli olduğunu unutmayın . Bildirmeden bir işlev içinden bunlara erişebilirsiniz global. Böylece, var:

x = 5

def access_only():
  return x
  # This returns whatever the global value of 'x' is

def modify():
  global x
  x = 'modified'
  return x
  # This function makes the global 'x' equal to 'modified', and then returns that value

def create_locally():
  x = 'local!'
  return x
  # This function creates a new local variable named 'x', and sets it as 'local',
  #  and returns that.  The global 'x' is untouched.

Arasındaki farka dikkat create_locallyve access_only- access_onlyçağırarak değil rağmen küresel x erişen globalrağmen ve create_locallykullanmaz globalo beri ya yerel bir kopyasını oluşturur atama bir değer.

Buradaki karışıklık, küresel değişkenleri neden kullanmamanız gerektiğidir.


2
Bunun pratikte çok kafa karıştırıcı olduğunu düşünmüyorum, sadece python'un kapsam belirleme kurallarını anlamanız gerekiyor .
Casey Kuball

20

Diğerlerinin de belirttiği gibi, globalbu işlevin genel değişkeni değiştirebilmesini istediğinizde bir işlevde bir değişken bildirmeniz gerekir . Sadece ona erişmek istiyorsanız, o zaman ihtiyacınız yoktur global.

Bununla ilgili biraz daha ayrıntıya girmek için, "değiştir" ifadesinin anlamı şudur: global adı farklı bir nesneyi gösterecek şekilde yeniden bağlamak istiyorsanız , ad bildirilmelidirglobal işlevde .

Bir nesneyi değiştiren (değiştiren) birçok işlem , global adı farklı bir nesneyi işaret edecek şekilde yeniden bağlamaz ve bu nedenle işlevde ad bildirilmeden tümü geçerlidirglobal .

d = {}
l = []
o = type("object", (object,), {})()

def valid():     # these are all valid without declaring any names global!
   d[0] = 1      # changes what's in d, but d still points to the same object
   d[0] += 1     # ditto
   d.clear()     # ditto! d is now empty but it`s still the same object!
   l.append(0)   # l is still the same list but has an additional member
   o.test = 1    # creating new attribute on o, but o is still the same object

8

Bir parametrenin varsayılan değeri olarak bir global kullanarak beni yakalayan bir durum.

globVar = None    # initialize value of global variable

def func(param = globVar):   # use globVar as default value for param
    print 'param =', param, 'globVar =', globVar  # display values

def test():
    global globVar
    globVar = 42  # change value of global
    func()

test()
=========
output: param = None, globVar = 42

Paramın 42 değerine sahip olmasını bekliyordum. Sürpriz. Python 2.7, işlev işlevini ilk ayrıştırdığında globVar değerini değerlendirdi. GlobVar değerinin değiştirilmesi, parametreye atanan varsayılan değeri etkilemedi. Değerlendirmeyi ertelemek, aşağıdaki gibi, ihtiyacım olduğu şekilde çalıştı.

def func(param = eval('globVar')):       # this seems to work
    print 'param =', param, 'globVar =', globVar  # display values

Veya güvende olmak istiyorsanız,

def func(param = None)):
    if param == None:
        param = globVar
    print 'param =', param, 'globVar =', globVar  # display values

Bu bana boş bir listeyi varsayılan değer olarak atama sorununu hatırlattı . Ve örnekte isolduğu gibi None, normal karşılaştırma yerine bir şey olup olmadığını kontrol etmek için kullanın ==.
berna1111

6

Bir fonksiyon içindeki genel değişkene doğrudan erişebilirsiniz. Bu global değişkenin değerini değiştirmek istiyorsanız, "global değişken_adı" kullanın. Aşağıdaki örneğe bakın:

var = 1
def global_var_change():
      global var
      var = "value changed"
global_var_change() #call the function for changes
print var

Genel olarak konuşursak, bu iyi bir programlama uygulaması değildir. Ad alanı mantığını kırarak, kodu anlamak ve hata ayıklamak zor olabilir.


2

Genel globaldeğişkene atanan değeri değiştirmek istediğinizde bildirimi kullanmalısınız .

Genel bir değişkenten okumak için buna ihtiyacınız yoktur. Bir nesne üzerinde yöntem çağırmanın (o nesne içindeki verileri değiştirmesine rağmen), o nesneyi tutan değişkenin değerini değiştirmediğini (yansıtıcı sihir yok) unutmayın.


2
Bu ifade talihsiz. Python'da, bir değişkene atanan değer bir referanstır, bu yüzden teknik olarak doğrudur (ve bunu kastettiğinizden şüphem yok), ancak birçok okuyucu "değeri değiştir" i "nesneyi değiştir" olarak yorumlayabilir, durumda - xs.append(xs.pop(0))olmadan gayet iyi çalışıyor global xs.

@delnan Cevabım dikkatle yazılmıştır, ancak açıklığa kavuşacağım.
Marcin
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.