답변:
나는이 솔루션을 어떤 방식, 형태 또는 형태로도지지하지 않습니다. 그러나 __builtin__
모듈에 변수를 추가하면 __builtin__
기본적으로 모두 포함 된 다른 모듈에서 전역 인 것처럼 액세스 할 수 있습니다 .
a.py는
print foo
b.py는
import __builtin__
__builtin__.foo = 1
import a
그 결과 "1"이 인쇄됩니다.
편집 :__builtin__
모듈이 지역의 상징으로 볼 수 있습니다 __builtins__
-이 답변 둘 사이의 차이에 대한 이유입니다. 또한 python3에서 __builtin__
로 이름이 변경되었습니다 builtins
.
hasattr(__builtin__, "foo")
.
전역 교차 모듈 변수가 필요한 경우 간단한 전역 모듈 수준 변수로 충분할 것입니다.
a.py :
var = 1
b.py :
import a
print a.var
import c
print a.var
c.py :
import a
a.var = 2
테스트:
$ python b.py
# -> 1 2
실제 예 : Django의 global_settings.py (Django 앱 설정은 개체 를 가져 오는 데 사용됨 django.conf.settings
).
a.py
)에 main()
? 그게 그렇게 중요한 건가?
if __name__=="__main__"
가드 를 사용 하여 가져올 때 예기치 않은 코드 실행을 방지하십시오.
id()
신원 확인에 사용 )
나는 그것이 의미가있는 많은 상황이 있다고 믿고 그것은 몇 개의 (단단하게 결합 된) 모듈에 걸쳐 알려진 몇몇 전역을 가지도록 프로그래밍을 단순화합니다. 이 정신에서 나는 그들을 참조 할 필요가있는 모듈들에 의해 반입되는 글로벌 모듈을 갖는 아이디어에 대해 조금 더 자세히 설명하고 싶습니다.
그러한 모듈이 하나 뿐인 경우 "g"로 이름을 지정합니다. 여기에서 전역으로 처리하려는 모든 변수에 기본값을 할당합니다. 이들 중 하나를 사용하는 각 모듈에서는 "from g import var"를 사용하지 않습니다. 이는 가져 오기시에만 g에서 초기화되는 지역 변수를 생성하기 때문입니다. 대부분의 참조는 g.var 및 "g"형식으로 작성합니다. 다른 모듈에서 잠재적으로 액세스 할 수있는 변수를 다루고 있음을 지속적으로 상기시켜줍니다.
이러한 전역 변수의 값이 모듈의 일부 함수에서 자주 사용되는 경우 해당 함수는 로컬 복사본을 만들 수 있습니다. var = g.var. 그러나 var에 대한 할당은 로컬이고 전역 g.var는 할당에서 명시 적으로 g.var를 참조하지 않고는 업데이트 할 수 없다는 것을 인식하는 것이 중요합니다.
모듈의 다른 하위 집합에서 공유하는 여러 전역 모듈을 사용하여 좀 더 엄격하게 제어 할 수도 있습니다. 내 전역 모듈에 짧은 이름을 사용하는 이유는 코드가 너무 복잡해지지 않도록하기 위해서입니다. 약간의 경험만으로도 1 ~ 2 개의 캐릭터만으로도 충분히 니모닉이됩니다.
x가 g에 이미 정의되지 않았을 때 gx에 할당하는 것은 여전히 가능하며 다른 모듈이 gx에 액세스 할 수 있습니다. 그러나 인터프리터가 허용하더라도이 접근 방식은 투명하지 않습니다. 그것. 할당에 대한 변수 이름의 오타로 인해 g에 실수로 새 변수를 만들 가능성이 여전히 있습니다. 때때로 dir (g) 검사는 그러한 사고로 인해 생긴 놀라운 이름을 발견하는 데 유용합니다.
한 모듈의 전역을 다른 모듈로 전달할 수 있습니다.
모듈 A에서 :
import module_b
my_var=2
module_b.do_something_with_my_globals(globals())
print my_var
모듈 B :
def do_something_with_my_globals(glob): # glob is simply a dict.
glob["my_var"]=3
전역 변수는 일반적으로 나쁜 생각이지만 다음을 지정하여 수행 할 수 있습니다 __builtins__
.
__builtins__.foo = 'something'
print foo
또한 모듈 자체는 모든 모듈에서 액세스 할 수있는 변수입니다. 따라서 다음과 같은 모듈을 정의하면 my_globals.py
:
# my_globals.py
foo = 'something'
그런 다음 어디서나 사용할 수 있습니다.
import my_globals
print my_globals.foo
수정보다는 모듈을 사용 __builtins__
하는 것이 일반적으로 이런 종류의 전역을 수행하는 더 깨끗한 방법입니다.
__builtins__
의 CPython 특색은, 당신이 정말로 그것을 사용하지 말아야 -보다 효율적으로 사용 __builtin__
(또는 builtins
같은 Python3에서) 허용 대답의 쇼
모듈 수준 변수로 이미이 작업을 수행 할 수 있습니다. 모듈은 가져 오는 모듈에 관계없이 동일합니다. 따라서 어떤 모듈에서든 변수를 모듈 수준의 변수로 만들고 다른 모듈에서 액세스하거나 할당 할 수 있습니다. 변수의 값을 설정하거나 단일 객체의 속성으로 만드는 함수를 호출하는 것이 좋습니다. 이렇게하면 변수가 변경 될 때 일부 코드를 실행해야하는 경우 모듈의 외부 인터페이스를 손상시키지 않고 실행할 수 있습니다.
일반적으로 작업을 수행하는 좋은 방법은 아닙니다. 전역을 사용하는 경우는 드뭅니다.하지만 이것이 가장 깨끗한 방법이라고 생각합니다.
변수를 찾을 수없는 경우가 있다는 답변을 게시하고 싶었습니다.
주기적 가져 오기는 모듈 동작을 손상시킬 수 있습니다.
예를 들면 :
first.py
import second
var = 1
second.py
import first
print(first.var) # will throw an error because the order of execution happens before var gets declared.
main.py
import first
이 예제에서는 분명해야하지만 큰 코드 기반에서는 정말 혼란 스러울 수 있습니다.
이것은 __builtin__
이름 공간을 수정하는 것처럼 들립니다 . 그렇게하려면 :
import __builtin__
__builtin__.foo = 'some-value'
__builtins__
직접 사용하지 마십시오 (추가 "s"에 유의하십시오). 분명히 이것은 사전이나 모듈 일 수 있습니다. 이것을 지적한 ΤΖΩΤΖΙΟΥ에게 감사드립니다 . 여기 에서 더 많은 것을 찾을 수 있습니다 .
이제 foo
어디에서나 사용할 수 있습니다.
나는 이것을 일반적으로 권장하지 않지만 이것을 사용하는 것은 프로그래머에게 달려 있습니다.
할당은 위와 같이해야하며 설정 만하면 foo = 'some-other-value'
현재 네임 스페이스에서만 설정됩니다.
필자는 실제로 누락되었다고 느꼈던 몇 가지 기본 제공 기본 함수에 이것을 사용합니다. 한 가지 예는 filter, map, reduce와 동일한 사용 의미를 갖는 찾기 함수입니다.
def builtin_find(f, x, d=None):
for i in x:
if f(i):
return i
return d
import __builtin__
__builtin__.find = builtin_find
일단 이것이 실행되면 (예를 들어, 진입 점 근처에서 가져옴으로써) 모든 모듈은 마치 내장 된 것처럼 find ()를 사용할 수 있습니다.
find(lambda i: i < 0, [1, 3, 0, -5, -10]) # Yields -5, the first negative.
참고 : 물론 필터와 다른 라인을 사용하여 길이가 0인지 테스트하거나 한 종류의 이상한 라인에서 감소를 사용하여이 작업을 수행 할 수 있지만 항상 이상하다고 느꼈습니다.
사전을 사용하여 모듈 간 수정 가능 (또는 변경 가능 ) 변수를 얻을 수 있습니다 .
# in myapp.__init__
Timeouts = {} # cross-modules global mutable variables for testing purpose
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 60
# in myapp.mod1
from myapp import Timeouts
def wait_app_up(project_name, port):
# wait for app until Timeouts['WAIT_APP_UP_IN_SECONDS']
# ...
# in myapp.test.test_mod1
from myapp import Timeouts
def test_wait_app_up_fail(self):
timeout_bak = Timeouts['WAIT_APP_UP_IN_SECONDS']
Timeouts['WAIT_APP_UP_IN_SECONDS'] = 3
with self.assertRaises(hlp.TimeoutException) as cm:
wait_app_up(PROJECT_NAME, PROJECT_PORT)
self.assertEqual("Timeout while waiting for App to start", str(cm.exception))
Timeouts['WAIT_JENKINS_UP_TIMEOUT_IN_SECONDS'] = timeout_bak
를 시작할 때 test_wait_app_up_fail
실제 시간 초과 기간은 3 초입니다.
변수 값을 전달하기 위해 global / module 네임 스페이스 대신 클래스 네임 스페이스 를 사용하여 전역 변수 (예 : http://wiki.c2.com/?GlobalVariablesAreBad 참조 )를 사용하는 단점을 피할 수 있는지 궁금했습니다. . 다음 코드는 두 메서드가 본질적으로 동일 함을 나타냅니다. 아래에 설명 된대로 클래스 네임 스페이스를 사용하면 약간의 이점이 있습니다.
다음 코드 조각은 또한 전역 / 모듈 네임 스페이스와 클래스 네임 스페이스 모두에서 특성 또는 변수가 동적으로 생성 및 삭제 될 수 있음을 보여줍니다.
wall.py
# Note no definition of global variables
class router:
""" Empty class """
이 모듈은 변수를 바운스하는 데 사용되기 때문에 '벽'이라고 부릅니다. 빈 클래스 '라우터'의 전역 변수 및 클래스 전체 속성을 임시로 정의하는 공간 역할을합니다.
source.py
import wall
def sourcefn():
msg = 'Hello world!'
wall.msg = msg
wall.router.msg = msg
이 모듈은 wall을 가져 sourcefn
와서 메시지를 정의하고 하나는 전역을 통해 하나는 라우터 기능을 통해 두 개의 서로 다른 메커니즘으로 메시지를 방출 하는 단일 기능 을 정의합니다. wall.msg
및 변수 wall.router.message
는 각각의 네임 스페이스에서 처음으로 여기에서 정의됩니다.
dest.py
import wall
def destfn():
if hasattr(wall, 'msg'):
print 'global: ' + wall.msg
del wall.msg
else:
print 'global: ' + 'no message'
if hasattr(wall.router, 'msg'):
print 'router: ' + wall.router.msg
del wall.router.msg
else:
print 'router: ' + 'no message'
이 모듈은 destfn
소스에서 방출 된 메시지를 수신하기 위해 두 가지 다른 메커니즘을 사용 하는 함수 를 정의합니다 . 변수 'msg'가 존재하지 않을 가능성을 허용합니다.destfn
또한 표시되면 변수를 삭제합니다.
main.py
import source, dest
source.sourcefn()
dest.destfn() # variables deleted after this call
dest.destfn()
이 모듈은 이전에 정의 된 함수를 순서대로 호출합니다. 에 대한 첫 번째 호출 후 dest.destfn
변수 wall.msg
와 wall.router.msg
더 이상 존재한다.
프로그램의 출력은 다음과 같습니다.
글로벌 : 안녕하세요!
라우터 : 안녕하세요!
글로벌 : 메시지 없음
라우터 : 메시지 없음
위의 코드 조각은 모듈 / 글로벌 및 클래스 / 클래스 변수 메커니즘이 본질적으로 동일 함을 보여줍니다.
많은 변수를 공유해야하는 경우 여러 벽 유형 모듈 (예 : wall1, wall2 등)을 사용하거나 여러 라우터 유형 클래스를 단일 파일에 정의하여 네임 스페이스 오염을 관리 할 수 있습니다. 후자는 약간 더 깔끔하므로 클래스 변수 메커니즘을 사용하는 데있어 약간의 이점을 나타낼 수 있습니다.