Python 2에서 부모 범위의 변수에 어떻게 쓰나요?
함수 안에 다음 코드가 있습니다.
stored_blocks = {}
def replace_blocks(m):
block = m.group(0)
block_hash = sha1(block)
stored_blocks[block_hash] = block
return '{{{%s}}}' % block_hash
num_converted = 0
def convert_variables(m):
name = m.group(1)
num_converted += 1
return '<%%= %s %%>' % name
fixed = MATCH_DECLARE_NEW.sub('', template)
fixed = MATCH_PYTHON_BLOCK.sub(replace_blocks, fixed)
fixed = MATCH_FORMAT.sub(convert_variables, fixed)
요소를 추가하면 stored_blocks
잘 작동하지만 num_converted
두 번째 하위 기능을 늘릴 수는 없습니다 .
UnboundLocalError : 할당 전에 참조 된 지역 변수 'num_converted'
사용할 수는 global
있지만 전역 변수는 추악하며 실제로 해당 변수가 전역일 필요는 없습니다.
그래서 부모 함수의 범위에있는 변수에 어떻게 쓸 수 있는지 궁금합니다. nonlocal num_converted
아마도 일을 할 것이지만 Python 2.x에서 작동하는 솔루션이 필요합니다.
문제 : 이것은 Python의 범위 지정 규칙이 수정 되었기 때문입니다. +=
할당 연산자 의 존재는 대상 num_converted
을 둘러싸는 함수의 범위에 대한 로컬로 표시하며 Python 2.x에서는 거기에서 하나의 범위 지정 수준에만 액세스 할 수있는 적절한 방법이 없습니다. global
키워드 만 현재 범위에서 변수 참조를 들어 올릴 수 있으며 맨 위로 바로 이동합니다.
수정 : 십시오 num_converted
단일 요소의 배열로.
num_converted = [0]
def convert_variables(m):
name = m.group(1)
num_converted[0] += 1
return '<%%= %s %%>' % name
(편집 된 답변은 아래 참조)
다음과 같이 사용할 수 있습니다.
def convert_variables(m):
name = m.group(1)
convert_variables.num_converted += 1
return '<%%= %s %%>' % name
convert_variables.num_converted = 0
이 방법 num_converted
은 convert_variable 메소드의 C와 유사한 "정적"변수로 작동합니다.
(편집 됨)
def convert_variables(m):
name = m.group(1)
convert_variables.num_converted = convert_variables.__dict__.get("num_converted", 0) + 1
return '<%%= %s %%>' % name
이렇게하면 기본 절차에서 카운터를 초기화 할 필요가 없습니다.
global
키워드를 사용하는 것이 좋습니다. 당신이 쓰는 경우 :
num_converted = 0
def convert_variables(m):
global num_converted
name = m.group(1)
num_converted += 1
return '<%%= %s %%>' % name
... num_converted
doesn't become a "global variable" (i.e. it doesn't become visible in any other unexpected places), it just means it can be modified inside convert_variables
. That seems to be exactly what you want.
To put it another way, num_converted
is already a global variable. All the global num_converted
syntax does is tell Python "inside this function, don't create a local num_converted
variable, instead, use the existing global one.
What about using a class instance to hold the state? You instantiate a class and pass instance methods to subs and those functions would have a reference to self...
I have couple of remarks.
First, one application for such nested functions comes up when dealing with raw callbacks, as are used in libraries like xml.parsers.expat. (That the library authors chose this approach may be objectionable, but ... there are reasons to use it nonetheless.)
Second: within a class, there are much nicer alternatives to the array (num_converted[0]). I suppose this is what Sebastjan was talking about.
class MainClass:
_num_converted = 0
def outer_method( self ):
def convert_variables(m):
name = m.group(1)
self._num_converted += 1
return '<%%= %s %%>' % name
It's still odd enough to merit a comment in the code... But the variable is at least local to the class.
Modified from: https://stackoverflow.com/a/40690954/819544
You can leverage the inspect
module to access the calling scope's globals dict and write into that. That means this trick can even be leveraged to access the calling scope from a nested function defined in an imported submodule.
import inspect
def get_globals(scope_level=0):
return dict(inspect.getmembers(inspect.stack()[scope_level][0]))["f_globals"]
num_converted = 0
def foobar():
get_globals(0)['num_converted'] += 1
foobar()
print(num_converted)
# 1
Play with the scope_level
argument as needed. Setting scope_level=1
works for a function defined in a submodule, scope_level=2
for the inner function defined in a decorator in a submodule, etc.
NB: Just because you can do this, doesn't mean you should.
'your programing' 카테고리의 다른 글
읽을 수있는 스트림을 닫는 방법 (종료 전)? (0) | 2020.10.14 |
---|---|
jscs가 파일, 블록 또는 줄당 규칙을 무시하는 방법이 있습니까? (0) | 2020.10.14 |
Git에서 부모없이 커밋을 생성하려면 어떻게해야합니까? (0) | 2020.10.14 |
CSS 한 줄 또는 여러 줄 수직 정렬 (0) | 2020.10.14 |
GCC : 행진은 mtune과 어떻게 다른가요? (0) | 2020.10.14 |