파이썬 비 로컬 문장


341

Python nonlocal문은 무엇입니까 (Python 3.0 이상에서)?

공식 파이썬 웹 사이트에는 문서 help("nonlocal")가 없으며 작동하지 않습니다.



18
다음은 로컬이 아닌 공식 파이썬 웹 사이트 문서입니다 : docs.python.org/3/reference/... (공식적인 문서가 없다는 OP의 주장은 단지 잘못 있도록이 문서는 파이썬 3.0부터 사용할 수있다)는
wkschwartz

3
"There is no documentation for nonlocal".실제로, help(keyword_in_string)파이썬 3 이상에서 문서를 만들 수 있습니다
ytpillai

10
공무원에게 공정하게 말하면 주제에 대해 짜증을냅니다. 선택된 답변의 예는 상황을 매우 명확하게 해주므로 중요한 질문입니다.
Mad Physicist

공식 파이썬 튜토리얼에서는이 범위와 네임 스페이스의 개념을 잘 설명 A를 좋은 예제 .
jammon

답변:


473

이것을 사용하지 않고 이것을 비교하십시오 nonlocal:

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 0

이를 위해, 사용하는 nonlocal경우, inner()'s에하는 것은 x이제도 outer()의' x:

x = 0
def outer():
    x = 1
    def inner():
        nonlocal x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 2
# global: 0

만약 우리가를 사용한다면 , 적절하게 "전역"값에 global바인딩 될 것입니다 x:

x = 0
def outer():
    x = 1
    def inner():
        global x
        x = 2
        print("inner:", x)

    inner()
    print("outer:", x)

outer()
print("global:", x)

# inner: 2
# outer: 1
# global: 2

32
글로벌 x와 다른 점은 무엇입니까?
ooboo

52
매우 유사하지만 외부 x는 예제에서 전역이 아니지만 대신 외부 함수에서 정의됩니다.
Anon

3
@Dustin-실제로, 속성 x가있는 클래스 A와 서브 클래스 B가 정의되어 있으면 B 내에서 x를 Ax
Anon

2
내부 함수를 정의 할 때 코드가 쉽게 들여 쓰기되어 79 자 PEP8 권장 사항을 위반하게됩니다. 이 문제를 해결할 방법이 있습니까? 내부 함수를 외부 함수 외부에 배치 할 수 있습니까? 나는 그 질문이 어리석게 들린다는 것을 알고 있지만 진지합니다.
tommy.carstensen

3
@ tommy.carstensen 당신은 고차 함수의 아름다움 인 arg로 함수를 전달할 수 있습니다. 또한 함수형 프로그래밍에서 이것을 컴포지션이라고합니다. 파이썬은 순수한 FP 언어는 아니지만 확실히 기능을 사용할 수 있습니다 (생성기, 고차 함수가 일부 예)
superuseroi

90

즉, 외부 (전역이 아닌) 범위의 변수에 값을 할당 할 수 있습니다. 모든 세부 사항 은 PEP 3104 를 참조 하십시오.


41

"python nonlocal"에 대한 Google 검색에서 제안, PEP 3104 가 나타 났으며, 이 문장의 구문과 추론을 완전히 설명합니다. 간단히 말해서, global함수에 대해 전역 적이거나 로컬이 아닌 변수를 참조하는 데 사용된다는 점을 제외 하면 명령문 과 정확히 동일한 방식으로 작동합니다.

여기 당신이 할 수있는 일의 간단한 예가 있습니다. 카운터 생성기는 이것을 사용하여 다시 닫을 수 있으므로 클로저가있는 언어의 관용구처럼 보입니다.

def make_counter():
    count = 0
    def counter():
        nonlocal count
        count += 1
        return count
    return counter

분명히 이것을 다음과 같은 생성기로 작성할 수 있습니다.

def counter_generator():
    count = 0
    while True:
        count += 1
        yield count

그러나 이것은 완벽하게 관용적 인 파이썬이지만 첫 번째 버전은 초보자에게는 더 분명한 것 같습니다. 리턴 된 함수를 호출하여 제너레이터를 올바르게 사용하는 것은 일반적인 혼동 지점입니다. 첫 번째 버전은 명시 적으로 함수를 반환합니다.


1
나는 그것이 키워드 'global'이하는 일이라고 확신했습니다-그 이름을 가진 변수에 도달 할 때까지 더 높은 환경을 작동시킵니다. 변수 x는 모듈 수준에서 클래스 내부에서 선언 된 다음이 클래스 내부의 함수와 해당 함수의 내부 함수에서 개별적으로 선언 될 수 있습니다. 어떤 x가 참조 해야하는지 어떻게 알 수 있습니까?
ooboo

7
전역에 관한 것은 전역 변수에 대해서만 작동한다는 것입니다. 포괄하는 비전 역 범위에서 변수를 볼 수 없습니다.
SingleNegationElimination 3:11

make_counter를 시도했지만 발전기가 아닌 함수를 반환합니다. 나중에 발전기를 반환 할 수 있도록 발전기를 반환하는 방법이 있습니까?
Dejell

@Dejel :이 예제는 nonlocal파이썬 의 문장 을 설명하기위한 것입니다 . 일련의 자연수를 원한다면 파이썬 관용구는 실제로itertools.count()
SingleNegationElimination

yield와 같은 생성기를 반환하는 기능을 시연하고 싶습니다. yield는 실제로 생성기를 반환합니다. 내 생각은 어쩌면 비 로컬 또는 다른 솔루션을 사용하는 대신 수율을 사용하지 않는 것입니다
Dejell

15

@ooboo :

소스 코드의 참조 지점에 "가장 가까운"것을 사용합니다. 이것을 "Lexical Scoping"이라고하며 현재> 40 년 동안 표준입니다.

파이썬의 클래스 멤버는 실제로 사전에 있으며 사전 __dict__어휘 범위에 도달하지 않습니다.

지정하지 않고 nonlocal수행 x = 7하면 새 로컬 변수 "x"가 작성됩니다. 을 지정 nonlocal하면 "가장 가까운" "x"를 찾아 할당합니다. 지정 nonlocal하고 "x"가 없으면 오류 메시지가 나타납니다.

키워드 global는 가장 바깥 쪽을 제외한 다른 모든 "x"를 행복하게 무시하기 때문에 항상 이상하게 보였습니다. 기묘한.


14

help ( 'nonlocal') nonlocal진술


    nonlocal_stmt ::= "nonlocal" identifier ("," identifier)*

그만큼 nonlocal 명령문은 나열된 식별자가 가장 가까운 엔 클로징 범위에서 이전에 바인드 된 변수를 참조하게합니다. 바인딩의 기본 동작은 로컬 네임 스페이스를 먼저 검색하는 것이므로 중요합니다. 이 명령문은 캡슐화 된 코드가 전역 (모듈) 범위 외에 로컬 범위 외부에서 변수를 리 바인드 할 수 있도록합니다.

nonlocal성명서에 기재된 이름 과 달리 성명서에 기재된 이름global 은 둘러싸는 범위의 기존 바인딩을 참조해야합니다 (새 바인딩을 작성해야하는 범위를 명확하게 판별 할 수 없음).

nonlocal명령문에 나열된 이름 은 로컬 범위의 기존 바인딩과 충돌하지 않아야합니다.

또한보십시오:

PEP 3104- 외부 범위
의 이름에 대한 액세스 설명에 대한 사양 nonlocal.

관련 도움말 주제 : 전역, NAMESPACES

출처 : 파이썬 언어 레퍼런스


11
매일 새로운 것을 배우십시오. 나는 당신이 사용할 수 아무 생각이 없었다 help()(: 그리고 지금 내 마음이 울 렸습니다 키워드를 help()인수가 간다와 상호 작용 ).
Erik Youngren

6

로부터 견적 파이썬 3 참조 :

로컬이 아닌 명령문은 나열된 식별자가 전역을 제외한 가장 가까운 둘러싸는 범위에서 이전에 바인딩 된 변수를 참조하게합니다.

참조에서 언급했듯이 여러 중첩 함수의 경우 가장 가까운 둘러싸는 함수의 변수 만 수정됩니다.

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        x = 2
        innermost()
        if x == 3: print('Inner x has been modified')

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Inner x has been modified

"가장 가까운"변수는 몇 단계 떨어져있을 수 있습니다.

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    x = 1
    inner()
    if x == 3: print('Outer x has been modified')

x = 0
outer()
if x == 3: print('Global x has been modified')

# Outer x has been modified

그러나 전역 변수는 될 수 없습니다.

def outer():
    def inner():
        def innermost():
            nonlocal x
            x = 3

        innermost()

    inner()

x = 0
outer()
if x == 3: print('Global x has been modified')

# SyntaxError: no binding for nonlocal 'x' found

3
a = 0    #1. global variable with respect to every function in program

def f():
    a = 0          #2. nonlocal with respect to function g
    def g():
        nonlocal a
        a=a+1
        print("The value of 'a' using nonlocal is ", a)
    def h():
        global a               #3. using global variable
        a=a+5
        print("The value of a using global is ", a)
    def i():
        a = 0              #4. variable separated from all others
        print("The value of 'a' inside a function is ", a)

    g()
    h()
    i()
print("The value of 'a' global before any function", a)
f()
print("The value of 'a' global after using function f ", a)

2

"비 로컬"문장에 대한 개인적 이해는 (일반적으로 파이썬과 프로그래밍을 처음 접했을 때 실례합니다) "비 로컬"은 코드 자체가 아닌 반복 함수 내에서 전역 기능을 사용하는 방법이라는 것입니다 . 당신이 원한다면 함수들 사이의 글로벌 성명.


0

'비 로컬'내부 함수 (즉, 중첩 내부 함수)를 사용 하면 외부 상위 함수의 특정 변수에 대한 읽기 및 ' 쓰기 '권한 얻을 수 있습니다 . 그리고 nonlocal은 다음과 같은 내부 함수 안에서만 사용할 수 있습니다.

a = 10
def Outer(msg):
    a = 20
    b = 30
    def Inner():
        c = 50
        d = 60
        print("MU LCL =",locals())
        nonlocal a
        a = 100
        ans = a+c
        print("Hello from Inner",ans)       
        print("value of a Inner : ",a)
    Inner()
    print("value of a Outer : ",a)

res = Outer("Hello World")
print(res)
print("value of a Global : ",a)
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.