Python 2.x의 nonlocal 키워드
Python 2.6에서 폐쇄를 구현하려고 하는데 비로컬 변수에 액세스해야 하는데 이 키워드는 Python 2.x에서 사용할 수 없는 것 같아.이러한 버전의 파이썬에서 폐쇄의 비로컬 변수에 어떻게 접근해야 하는가?
내부 함수는 비 국부적 변수를 2.x로 읽을 수 있지만, 재바인딩하지 않는다.이것은 귀찮지만, 너는 그것을 해결할 수 있다.사전을 만들고 그 안에 데이터를 요소로 저장하십시오.내부 함수는 비로컬 변수가 참조하는 객체를 변이하는 것을 금지하지 않는다.
위키백과의 예를 사용하려면:
def outer():
d = {'y' : 0}
def inner():
d['y'] += 1
return d['y']
return inner
f = outer()
print(f(), f(), f()) #prints 1 2 3
다음의 해결책은 엘리아스 자마리아(Elias Zamaria)의 대답에서 영감을 받지만, 그 대답과는 반대로 외부 기능의 여러 호출을 정확하게 처리한다."변수"inner.y
현재 통화의 지역적 위치outer
. 단지 그것은 금지되어 있기 때문에 변수가 아니라 객체 속성(개체가 함수임)이다.inner
그 자체다이것은 매우 추하다(속성은 다음에나 생성될 수 있다는 점에 유의한다).inner
함수가 정의되어 있지만 효과적인 것 같다.
def outer():
def inner():
inner.y += 1
return inner.y
inner.y = 0
return inner
f = outer()
g = outer()
print(f(), f(), g(), f(), g()) #prints (1, 2, 1, 3, 2)
사전이라기 보다는, 지역적이지 않은 수업은 덜 복잡하다.@ChrisB의 예 수정:
def outer():
class context:
y = 0
def inner():
context.y += 1
return context.y
return inner
그러면
f = outer()
assert f() == 1
assert f() == 2
assert f() == 3
assert f() == 4
각각의 외부() 호는 컨텍스트라고 하는 새롭고 뚜렷한 클래스를 만든다(단순한 새로운 인스턴스만이 아니다).그래서 그것은 공유된 맥락에 대한 나다니엘의 주의를 피한다.
g = outer()
assert g() == 1
assert g() == 2
assert f() == 5
여기서 핵심은 '접근'이 의미하는 것이라고 생각한다.예를 들어, 닫힘 범위 밖의 변수를 읽는 데 문제가 없어야 한다.
x = 3
def outer():
def inner():
print x
inner()
outer()
예상대로 작동해야 한다(제3장).단, 예를 들어 x의 값을 재정의하는 것은 작동하지 않는다.
x = 3
def outer():
def inner():
x = 5
inner()
outer()
print x
여전히 3번 인쇄될 것이다.내가 PEP-3104에 대해 이해한 바로는 이것이 비로컬 키워드를 다루기 위한 것이다.PEP에서 언급된 바와 같이, 같은 것을 성취하기 위해 클래스를 사용할 수 있다(일종의 지저분함).
class Namespace(object): pass
ns = Namespace()
ns.x = 3
def outer():
def inner():
ns.x = 5
inner()
outer()
print ns.x
Python 2에서 비로컬 변수를 구현하는 또 다른 방법이 있는데, 여기서의 답변 중 어떤 것이든 어떤 이유로든 바람직하지 않은 경우:
def outer():
outer.y = 0
def inner():
outer.y += 1
return outer.y
return inner
f = outer()
print(f(), f(), f()) #prints 1 2 3
변수의 할당명세서에 있는 함수명을 사용하는 것은 중복되지만, 내가 보기에는 변수를 사전에 넣는 것보다 간단하고 깨끗해 보인다.그 가치는 크리스 B의 대답에서처럼 한 통화에서 다른 통화로 기억된다.
알로이스 마달이 다른 대답에 대해 논평에서 한 제안에서 영감을 얻은 것이 있다.
class Nonlocal(object):
""" Helper to implement nonlocal names in Python 2.x """
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def outer():
nl = Nonlocal(y=0)
def inner():
nl.y += 1
return nl.y
return inner
f = outer()
print(f(), f(), f()) # -> (1 2 3)
비단뱀의 범위 지정 규칙에는 사마귀가 있다 - 할당은 변수를 즉시 둘러싸는 함수 범위에 로컬로 만든다.라면 이 를 '로마'로 할 수 것이다global
키워드
해결책은 두 범위 사이에 공유되는 물체를 도입하는 것인데, 여기에는 변이 가능한 변수가 포함되어 있지만, 그 자체가 할당되지 않은 변수를 통해 참조되는 것이다.
def outer(v):
def inner(container = [v]):
container[0] += 1
return container[0]
return inner
또 다른 방법은 다음과 같은 종류의 해킹이다.
def outer(v):
def inner(varname = 'v', scope = locals()):
scope[varname] += 1
return scope[varname]
return inner
매개 변수의 이름을 다음과 같은 방법으로 알아낼 수 있을 것이다.outer
, 그런 다음 varname으로 전달하지만 이름에 의존하지 않고outer
Y 콤비네이터를 사용해야 한다.
다른 방법(너무 장황하긴 하지만):
import ctypes
def outer():
y = 0
def inner():
ctypes.pythonapi.PyCell_Set(id(inner.func_closure[0]), id(y + 1))
return y
return inner
x = outer()
x()
>> 1
x()
>> 2
y = outer()
y()
>> 1
x()
>> 3
Martineau의 우아한 솔루션을 실용적이고 다소 덜 우아한 사용 사례로 확대:
class nonlocals(object):
""" Helper to implement nonlocal names in Python 2.x.
Usage example:
def outer():
nl = nonlocals( n=0, m=1 )
def inner():
nl.n += 1
inner() # will increment nl.n
or...
sums = nonlocals( { k:v for k,v in locals().iteritems() if k.startswith('tot_') } )
"""
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
def __init__(self, a_dict):
self.__dict__.update(a_dict)
전역 변수 사용
def outer():
global y # import1
y = 0
def inner():
global y # import2 - requires import1
y += 1
return y
return inner
f = outer()
print(f(), f(), f()) #prints 1 2 3
개인적으로, 나는 세계적인 변수들을 좋아하지 않는다.그러나 나의 제안은 https://stackoverflow.com/a/19877437/1083704의 답변에 기초한다.
def report():
class Rank:
def __init__(self):
report.ranks += 1
rank = Rank()
report.ranks = 0
report()
사용자가 전역 변수를 선언해야 하는 경우ranks
당신이 전화할때마다report
됨 나의 개선으로 인해 사용자로부터 함수 변수를 초기화할 필요가 없어졌다.
참조URL: https://stackoverflow.com/questions/3190706/nonlocal-keyword-in-python-2-x
'Programing' 카테고리의 다른 글
python Simple을 실행할 수 있는가?로컬 호스트에서만 HTTPServer를 사용하시겠습니까? (0) | 2022.03.29 |
---|---|
Vue.js—v-model과 v-bind의 차이 (0) | 2022.03.28 |
사용 중지 경고:태핑 가능.플러그인이 더 이상 사용되지 않음..hooks에 새 API를 대신 사용 (0) | 2022.03.28 |
Vue2에서 디바운스를 구현하는 방법? (0) | 2022.03.28 |
OS X에서 Python의 기본 버전을 3.x로 설정하는 방법 (0) | 2022.03.28 |