Python Language
변수 범위 및 바인딩
수색…
통사론
- 전역 a, b, c
- 국소가 아닌 a, b
- x = 무언가 # binds x
- (x, y) = something #은 x와 y를 묶는다.
- x + = something #은 x를 묶는다. 다른 모든 "op ="
- del x #는 x를 묶는다.
- x는 무언가를 위해 : # binds x
- 뭔가있는 x : # binds x
- 예를 제외하고 Exception을 제외하고 : # 블록 안에 ex를 바인드한다.
전역 변수
파이썬에서, 함수 내의 변수는 대입 문의 왼쪽 또는 다른 바인딩 어커런스에 나타나는 경우에만 로컬로 간주됩니다. 그렇지 않으면 이러한 바인딩은 전역 함수 범위를 감싸는 함수에서 찾는다. 할당 문을 실행하지 않아도 마찬가지입니다.
x = 'Hi'
def read_x():
print(x) # x is just referenced, therefore assumed global
read_x() # prints Hi
def read_y():
print(y) # here y is just referenced, therefore assumed global
read_y() # NameError: global name 'y' is not defined
def read_y():
y = 'Hey' # y appears in an assignment, therefore it's local
print(y) # will find the local y
read_y() # prints Hey
def read_x_local_fail():
if False:
x = 'Hey' # x appears in an assignment, therefore it's local
print(x) # will look for the _local_ z, which is not assigned, and will not be found
read_x_local_fail() # UnboundLocalError: local variable 'x' referenced before assignment
일반적으로 범위 내의 할당은 동일한 이름의 모든 외부 변수를 섀도 잉합니다.
x = 'Hi'
def change_local_x():
x = 'Bye'
print(x)
change_local_x() # prints Bye
print(x) # prints Hi
이름을 global
선언하면 나머지 범위의 경우 이름에 대한 모든 할당이 모듈의 최상위 수준에서 발생합니다.
x = 'Hi'
def change_global_x():
global x
x = 'Bye'
print(x)
change_global_x() # prints Bye
print(x) # prints Bye
global
키워드는 프로그램의 최상위 수준이 아니라 모듈의 최상위 수준에서 배정이 이루어짐을 의미합니다. 다른 모듈은 여전히 모듈 내의 변수에 대한 일반적인 점선 액세스가 필요합니다.
요약 : 변수 x
가 함수에 대해 로컬인지 여부를 확인하려면 전체 함수를 읽어야합니다.
-
global x
찾은 경우x
는 전역 변수입니다. -
nonlocal x
찾았 으면x
는 둘러싼 함수에 속하며 로컬도 아니고 글로벌도 아닙니다. -
x = 5
또는for x in range(3)
또는 다른 바인딩에x
가있는 경우x
는 지역 변수입니다 - 그렇지 않으면
x
는 몇 가지 범위 (함수 범위, 전역 범위 또는 내장 함수)에 속합니다.
지역 변수
이름이 함수 내에서 바인드 되면 기본적으로 함수 내에서만 액세스 할 수 있습니다.
def foo():
a = 5
print(a) # ok
print(a) # NameError: name 'a' is not defined
제어 흐름 구조는 범위를 except
는 예외적으로 영향을 미치지 않지만 아직 할당되지 않은 변수에 액세스하는 것은 오류입니다.
def foo():
if True:
a = 5
print(a) # ok
b = 3
def bar():
if False:
b = 5
print(b) # UnboundLocalError: local variable 'b' referenced before assignment
일반적인 바인딩 작업은 루프에 for
할당 및 a += 5
와 같은 확장 된 할당입니다.
비 지역 변수
Python 3은 nonlocal 이라는 새로운 키워드를 추가했습니다. nonlocal 키워드는 내부 범위에 범위 오버라이드를 추가합니다. PEP 3104에서이 모든 것을 읽을 수 있습니다. 이것은 몇 가지 코드 예제를 통해 가장 잘 설명됩니다. 가장 일반적인 예 중 하나는 증가 할 수있는 함수를 만드는 것입니다.
def counter():
num = 0
def incrementer():
num += 1
return num
return incrementer
이 코드를 실행하려고하면 num 변수가 가장 안쪽 함수에 지정되기 전에 참조되기 때문에 UnboundLocalError 를 받게됩니다. 믹스에 로컬이 아닌 것을 추가해 봅시다.
def counter():
num = 0
def incrementer():
nonlocal num
num += 1
return num
return incrementer
c = counter()
c() # = 1
c() # = 2
c() # = 3
기본적으로 nonlocal
변수는 외부 범위의 변수에 할당 할 수 있지만 전역 범위는 할당 할 수 없습니다. 그래서 counter
함수에서 nonlocal
을 사용할 수 없습니다. 왜냐하면 전역 함수를 할당하려고하기 때문입니다. 시도 SyntaxError
빨리 얻을 수 있습니다. 대신 중첩 된 함수에서 nonlocal
것을 사용해야합니다.
(여기에 제시된 기능은 발전기를 사용하여 구현하는 것이 더 낫다는 점에 유의하십시오.)
바인딩 발생
x = 5
x += 7
for x in iterable: pass
위의 각 명령문은 바인딩 어커런스입니다 . x
는 5
로 표시된 오브젝트에 바인드됩니다. 이 명령문이 함수 안에 있으면 x
는 기본적으로 함수 로컬이됩니다. 바인딩 문 목록은 "구문"절을 참조하십시오.
이름을 찾을 때 함수가 클래스 범위를 건너 뜁니다.
클래스는 정의 중에 로컬 범위가 있지만 클래스를 참조하는 함수는 이름을 찾을 때 해당 범위를 사용하지 않습니다. 람다는 함수이기 때문에 함수 범위를 사용하여 이해가 구현되기 때문에 이것은 놀라운 행동으로 이어질 수 있습니다.
a = 'global'
class Fred:
a = 'class' # class scope
b = (a for i in range(10)) # function scope
c = [a for i in range(10)] # function scope
d = a # class scope
e = lambda: a # function scope
f = lambda a=a: a # default argument uses class scope
@staticmethod # or @classmethod, or regular instance method
def g(): # function scope
return a
print(Fred.a) # class
print(next(Fred.b)) # global
print(Fred.c[0]) # class in Python 2, global in Python 3
print(Fred.d) # class
print(Fred.e()) # global
print(Fred.f()) # class
print(Fred.g()) # global
이 범위의 작동 방식에 익숙하지 않은 사용자는 b
, c
및 e
가 class
를 인쇄 할 것으로 예상 할 수 있습니다.
클래스 범위의 이름에 액세스 할 수 없습니다. 이름은 가장 안쪽에있는 함수 범위에서 해석됩니다. 중첩 된 범위의 체인에서 클래스 정의가 발생하면 해결 프로세스는 클래스 정의를 건너 뜁니다.
명명과 바인딩 에 관한 파이썬의 문서에서 :
클래스 블록에 정의 된 이름의 범위는 클래스 블록으로 제한됩니다. 메소드의 코드 블록까지 확장되지 않습니다. 이것은 함수 범위를 사용하여 구현되기 때문에 이해력과 생성자 표현식을 포함합니다. 즉, 다음과 같은 경우 실패합니다.
class A: a = 42 b = list(a + i for i in range(10))
이 예제는 Martijn Pieters 가이 답변의 참고 문헌을 사용하는데, 여기에는이 동작에 대한 깊이있는 분석이 포함되어 있습니다.
del 명령
이 명령에는 몇 가지 관련되어 있지만 별개의 양식이 있습니다.
del v
v
가 변수 인 경우 명령 del v
는 해당 범위에서 변수를 제거합니다. 예 :
x = 5
print(x) # out: 5
del x
print(x) # NameError: name 'f' is not defined
참고
del
명시 적으로 언급되지 않는 (사용하는 것을 의미 결속 선두로부터 인nonlocal
또는global
)del v
것v
현재 범위에 국부적. 외부 범위에서v
를 삭제하려는 경우,del v
명령문의 동일한 범위에서nonlocal v
또는global v
를 사용하십시오.
다음 모든면에서 명령의 의도는 기본 동작이지만 언어에 의해 강제되지는 않습니다. 클래스는이 의도를 무효화하는 방법으로 작성 될 수 있습니다.
del v.name
이 명령은 v.__delattr__(name)
대한 호출을 트리거합니다.
의도는 속성 name
사용할 수 없도록 만드는 것입니다. 예 :
class A:
pass
a = A()
a.x = 7
print(a.x) # out: 7
del a.x
print(a.x) # error: AttributeError: 'A' object has no attribute 'x'
del v[item]
이 명령은 v.__delitem__(item)
대한 호출을 트리거합니다.
의도는 item
v
의해 구현 된 맵핑에 속하지 않는다는 것입니다. 예 :
x = {'a': 1, 'b': 2}
del x['a']
print(x) # out: {'b': 2}
print(x['a']) # error: KeyError: 'a'
del v[a:b]
이것은 실제로 v.__delslice__(a, b)
호출합니다.
의도는 위에서 설명한 것과 비슷하지만 슬라이스가 있습니다. 단일 항목 대신 항목의 범위입니다. 예 :
x = [0, 1, 2, 3, 4]
del x[1:3]
print(x) # out: [0, 3, 4]
가비지 콜렉션 # del 명령을 참조하십시오.
지역 대 글로벌 범위
로컬 및 글로벌 범위 란 무엇입니까?
코드의 어느 시점에서 액세스 할 수있는 모든 Python 변수는 로컬 범위 또는 전역 범위에 있습니다.
로컬 범위에는 현재 함수에 정의 된 모든 변수가 포함되고 전역 범위에는 현재 함수 외부에 정의 된 변수가 포함됩니다.
foo = 1 # global
def func():
bar = 2 # local
print(foo) # prints variable foo from global scope
print(bar) # prints variable bar from local scope
어떤 변수가 어떤 범위에 있는지 검사 할 수 있습니다. 내장 함수 locals()
및 globals()
는 전체 범위를 사전으로 반환합니다.
foo = 1
def func():
bar = 2
print(globals().keys()) # prints all variable names in global scope
print(locals().keys()) # prints all variable names in local scope
이름 충돌은 어떻게됩니까?
foo = 1
def func():
foo = 2 # creates a new variable foo in local scope, global foo is not affected
print(foo) # prints 2
# global variable foo still exists, unchanged:
print(globals()['foo']) # prints 1
print(locals()['foo']) # prints 2
전역 변수를 수정하려면, 키워드를 사용하여 global
:
foo = 1
def func():
global foo
foo = 2 # this modifies the global foo, rather than creating a local variable
범위는 함수의 전체 본문에 대해 정의됩니다!
이것이 의미하는 바는 변수가 함수와 지역의 절반에 대해 전역 적이 지 않을 것이며 그 반대도 마찬가지입니다.
foo = 1
def func():
# This function has a local variable foo, because it is defined down below.
# So, foo is local from this point. Global foo is hidden.
print(foo) # raises UnboundLocalError, because local foo is not yet initialized
foo = 7
print(foo)
마찬가지로, oposite :
foo = 1
def func():
# In this function, foo is a global variable from the begining
foo = 7 # global foo is modified
print(foo) # 7
print(globals()['foo']) # 7
global foo # this could be anywhere within the function
print(foo) # 7
함수 내의 함수
함수 내에는 여러 수준의 함수가 중첩되어있을 수 있지만, 한 함수 내에는 해당 함수와 전역 범위에 대해 하나의 로컬 범위 만 있습니다. 중간 범위가 없습니다.
foo = 1
def f1():
bar = 1
def f2():
baz = 2
# here, foo is a global variable, baz is a local variable
# bar is not in either scope
print(locals().keys()) # ['baz']
print('bar' in locals()) # False
print('bar' in globals()) # False
def f3():
baz = 3
print(bar) # bar from f1 is referenced so it enters local scope of f3 (closure)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
def f4():
bar = 4 # a new local bar which hides bar from local scope of f1
baz = 4
print(bar)
print(locals().keys()) # ['bar', 'baz']
print('bar' in locals()) # True
print('bar' in globals()) # False
global
대 nonlocal
(Python 3에만 해당)
이 두 키워드는 현재 함수에 국한되지 않은 변수에 대한 쓰기 액세스를 얻는 데 사용됩니다.
global
키워드는 이름이 전역 변수로 취급되어야한다고 선언합니다.
foo = 0 # global foo
def f1():
foo = 1 # a new foo local in f1
def f2():
foo = 2 # a new foo local in f2
def f3():
foo = 3 # a new foo local in f3
print(foo) # 3
foo = 30 # modifies local foo in f3 only
def f4():
global foo
print(foo) # 0
foo = 100 # modifies global foo
반면에, 파이썬 3에서 사용할 수있는 nonlocal
( Nonlocal Variables 참조)은 지역 변수를 둘러싼 범위에서 현재 함수의 로컬 범위로 가져옵니다.
nonlocal
의 Python 문서에서 :
nonlocal 문은 나열된 식별자가 전역을 제외한 가장 가까운 포함 범위에서 이전에 바인딩 된 변수를 참조하도록합니다.
def f1():
def f2():
foo = 2 # a new foo local in f2
def f3():
nonlocal foo # foo from f2, which is the nearest enclosing scope
print(foo) # 2
foo = 20 # modifies foo from f2!