파이썬 함수 전역 변수?


272

이와 같은 혼란으로 인해 전역 변수를 먼저 사용하지 않아야한다는 것을 알고 있지만 변수를 사용하는 경우 다음과 같은 유효한 방법을 사용합니까? (별도의 함수로 만든 변수의 전역 복사본을 호출하려고합니다.)

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()

합니까 x두 번째 함수가 사용의 글로벌 사본의 동일한 값을 가지고 xfunc_a사용과 수정을? 정의 후 함수를 호출 할 때 순서가 중요합니까?


1
함수에 파이썬이 할당 전에 참조를 처리 할 변수가 할당되어 있다고 가정하지 않도록주의하십시오. 첫 번째 할당까지 x를 사용한 경우 전역 할당 또는 로컬 할당이 아닙니다. 당신 : 당신의 얼굴에서 악명 높은 UnboundLocalError 예외를 얻을 것이다
osirisgothra

답변:


412

단순히 전역 변수에 액세스하려면 해당 이름 만 사용하십시오. 그러나 값 을 변경 하려면 global키워드 를 사용해야합니다 .

예 :

global someVar
someVar = 55

전역 변수의 값을 55로 변경합니다. 그렇지 않으면 55를 로컬 변수에 할당합니다.

함수 정의 목록의 순서는 중요하지 않습니다 (어떻게 든 서로를 참조하지 않는다고 가정 할 때).


2
내가 준 코드에서 func_B는 (1) 전역 복사본 x (func_A에서 얻은), (2) func_A 결과와 동일한 값을 가진 로컬 변수 x 또는 (3) 값이없고 (컴파일러의 관점에서) "일부 값"또는 func_A의 x와 관련이없는 지역 변수 x?
Akshat Shekhar

xin func_B은 호출의 반환 값에서 값을 얻는 로컬 변수입니다. func_A그래서 그것이 당신의 (2)가 될 것이라고 생각합니다.
Levon

x가 func_A에 의해 생성 된 임의의 종류의 시퀀스라고 가정 해 봅시다 (즉, func_A는 실행될 때마다 다른 x를 생성했습니다). 전화 했어? 그렇다면 어떻게 해결할 수 있습니까?
Akshat Shekhar 1

1
예, func_A각 실행 중에 전역 변수를 변경하고 func_B사용 func_B하도록 되 돌리면 매번 변경된 값으로 작동합니다. "고치는 방법"에 대해 잘 모르겠습니다. 현재 / 원래 질문에 가장 유용한 답변을 수락 한 후 후속 질문에 대한 다른 질문을 열어보십시오.
Levon

1
실제로 그것은 x가 무엇인지에 달려 있습니다. x가 변경 불가능한 경우 func_B의 x는 동일한 값을 가지더라도 로컬로 선언되므로 func_B의 x는 그대로 유지됩니다. 이것은 튜플, 정수에 적용됩니다 ... 예를 들어 목록의 인스턴스이고 당신이 x.append("...")하는 경우 로컬 변수가 전역 변수를 참조하기 때문에 변경되는 전역 변수 x입니다.
jadkik94

111

Python 범위 내에서 해당 범위 내에서 아직 선언되지 않은 변수에 할당하면 해당 변수가 키워드로 전역 범위 변수를 참조하는 것으로 함수에서 일찍 선언 되지 않는 한 새 로컬 변수가 작성 global됩니다.

무슨 일이 일어나는지 알아보기 위해 수정 된 의사 코드 버전을 살펴 보겠습니다.

# 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

실제로 func_B이름이 지정된 변수로 모두 다시 작성할 수 x_local있으며 동일하게 작동합니다.

순서는 함수가 전역 x의 값을 변경하는 연산을 수행하는 순서까지만 중요합니다. 따라서이 예에서는 func_Bcalls 이므로 order는 중요하지 않습니다 func_A. 이 예에서 순서는 중요합니다.

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'.

global에만 전역 개체를 수정해야합니다. 선언하지 않고 함수 내에서 액세스 할 수 있습니다 global. 따라서, 우리는 :

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.

사이의 차이를 참고 create_locally하고 access_only- access_only호출되지에도 불구하고 글로벌 X에 액세스 global하더라도, 그리고 create_locally사용하지 않는 global것이 이후 중 하나, 그것은 로컬 복사본을 만들어 할당 값을.

여기서 혼란은 전역 변수를 사용하지 않아야하는 이유입니다.


2
나는 이것이 실제로 혼란스럽지 않다고 생각하지 않습니다 . 파이썬의 범위 규칙 을 이해하면 됩니다 .
Casey Kuball

20

다른 사람들이 지적했듯이, global함수가 전역 변수를 수정할 수있게하려면 함수에서 변수를 선언해야 합니다. 액세스 만하려면 필요하지 않습니다 global.

그것에 대해 좀 더 자세히 설명하기 위해, "수정"의 의미는 다음과 같습니다. 전역 이름 을 다시 바인딩 하여 다른 객체를 가리 키려면 global함수에서 이름을 선언해야합니다 .

객체를 수정 (돌연변이)하는 많은 작업 은 전역 이름을 다른 객체를 가리 키도록 다시 바인딩 하지 않으므로 함수 에서 이름 을 선언하지 않고 모두 유효global 합니다.

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

다음은 매개 변수의 기본값으로 전역을 사용하여 나를 잡은 한 가지 사례입니다.

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의 값은 42가 될 것으로 예상했습니다. Python 2.7은 함수 func을 처음 구문 분석 할 때 globVar의 값을 평가했습니다. globVar의 값을 변경해도 param에 지정된 기본값에는 영향을 미치지 않습니다. 다음과 같이 평가 지연은 내가 원하는대로 작동했습니다.

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

안전을 원한다면

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

빈 목록을 기본값으로 할당하는 문제를 생각 나게했습니다 . 그리고 예에서 와 같이 일반 비교 대신 is무언가가 있는지 확인 하는 데 사용 하십시오 . None==
berna1111

6

함수 내에서 전역 변수에 직접 액세스 할 수 있습니다. 해당 전역 변수의 값을 변경하려면 "global variable_name"을 사용하십시오. 다음 예를 참조하십시오.

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

일반적으로 이것은 좋은 프로그래밍 관행이 아닙니다. 네임 스페이스 논리를 깨 뜨리면 코드를 이해하고 디버깅하기가 어려워 질 수 있습니다.


2

global전역 변수에 지정된 값을 변경 하려면 선언을 사용해야합니다 .

전역 변수에서 읽을 필요는 없습니다. 객체에서 메소드를 호출해도 (객체 내의 데이터가 변경 되더라도) 해당 객체를 보유하는 변수의 값은 변경되지 않습니다 (반사 마술이 없음).


2
이 말은 불행하다. 파이썬에서 변수에 할당 된 값은 참조이므로 기술적으로 정확하지만 (의문의 여지가 없습니다) 많은 독자들이 "값 변경"을 "객체 변경"으로 해석 할 수 있습니다. 경우- xs.append(xs.pop(0))없이 잘 작동합니다 global xs.

@delnan 내 대답은주의 깊게 표현되어 있지만 명확하게 설명하겠습니다.
Marcin
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.