developer tip

다른 모듈에서 모듈 변수를 변경하는 방법은 무엇입니까?

copycodes 2020. 9. 22. 08:21
반응형

다른 모듈에서 모듈 변수를 변경하는 방법은 무엇입니까?


라는 패키지가 bar있고 다음이 포함되어 있다고 가정 합니다 bar.py.

a = None

def foobar():
    print a

__init__.py:

from bar import a, foobar

그런 다음이 스크립트를 실행합니다.

import bar

print bar.a
bar.a = 1
print bar.a
bar.foobar()

내가 기대하는 것은 다음과 같습니다.

None
1
1

내가 얻는 것은 다음과 같습니다.

None
1
None

아무도 내 오해를 설명 할 수 있습니까?


을 (를) 사용하고 from bar import a있습니다. a가져 오기 모듈의 전역 범위 (또는 가져 오기 문이 발생하는 모든 범위)에서 심볼이됩니다.

에 새 값을 할당 하면 실제 값이 아닌 aa포인트도 변경하는 것 입니다. 에서 bar.py직접 가져 와서을 설정하여 실험을 수행하십시오 . 이렇게하면 실제로이 컨텍스트에서 '실제'값을 수정 하게 됩니다.import bar__init__.pybar.a = 1bar.__dict__['a']a

세 개의 레이어로 약간 복잡하지만 실제로에서 파생 된 라는 모듈 bar.a = 1의 값을 변경합니다 . 의이 값을 변경하지 않는 때문에보고 실제 파일에서의 삶 . 변경하려면 설정할 수 있습니다.abar__init__.pyafoobarfoobarbar.pybar.bar.a

이것은 문장 from foo import bar형태 를 사용할 때의 위험 중 하나입니다 import. 그것은 bar두 개의 기호로 분할 됩니다. 하나 foo는 원래 값을 가리 키기 시작하는 전역에서 볼 수 있고 import문장이 실행되는 범위에서 볼 수있는 다른 기호 입니다. 심볼이 가리키는 위치를 변경해도 가리키는 값도 변경되지 않습니다.

이런 종류의 것들은 reload인터랙티브 인터프리터에서 모듈을 시도 할 때 킬러 입니다.


이 질문에 어려움 중 하나는 소스라는 이름의 프로그램을 가지고있다 bar/bar.py: import bar수입하거나 bar/__init__.py또는 bar/bar.py이 조금 성가신를 추적 할 수있는 완료 위치에 따라 a입니다 bar.a.

작동 방식은 다음과 같습니다.

무슨 일이 일어나는지 이해하는 열쇠는 당신의 __init__.py,

from bar import a

사실상 다음과 같은 일을한다

a = bar.a  # … with bar = bar/bar.py (as if bar were imported locally from __init__.py)

and defines a new variable (bar/__init__.py:a, if you wish). Thus, your from bar import a in __init__.py binds name bar/__init__.py:a to the original bar.py:a object (None). This is why you can do from bar import a as a2 in __init__.py: in this case, it is clear that you have both bar/bar.py:a and a distinct variable name bar/__init__.py:a2 (in your case, the names of the two variables just happen to both be a, but they still live in different namespaces: in __init__.py, they are bar.a and a).

Now, when you do

import bar

print bar.a

you are accessing variable bar/__init__.py:a (since import bar imports your bar/__init__.py). This is the variable you modify (to 1). You are not touching the contents of variable bar/bar.py:a. So when you subsequently do

bar.foobar()

you call bar/bar.py:foobar(), which accesses variable a from bar/bar.py, which is still None (when foobar() is defined, it binds variable names once and for all, so the a in bar.py is bar.py:a, not any other a variable defined in another module—as there might be many a variables in all the imported modules). Hence the last None output.


To put another way: Turns out this misconception is very easy to make. It is sneakily defined in the Python language reference: the use of object instead of symbol. I would suggest that the Python language reference make this more clear and less sparse..

The from form does not bind the module name: it goes through the list of identifiers, looks each one of them up in the module found in step (1), and binds the name in the local namespace to the object thus found.

HOWEVER:

When you import, you import the current value of the imported symbol and add it to your namespace as defined. You are not importing a reference, you are effectively importing a value.

Thus, to get the updated value of i, you must import a variable that holds a reference to that symbol.

In other words, importing is NOT like an import in JAVA, external declaration in C/C++ or even a use clause in PERL.

Rather, the following statement in Python:

from some_other_module import a as x

is more like the following code in K&R C:

extern int a; /* import from the EXTERN file */

int x = a;

(caveat: in the Python case, "a" and "x" are essentially a reference to the actual value: you're not copying the INT, you're copying the reference address)

참고URL : https://stackoverflow.com/questions/3536620/how-to-change-a-module-variable-from-another-module

반응형