IT

크로스 모듈 변수를 만드는 방법?

lottoking 2020. 7. 18. 09:44
반응형

크로스 모듈 변수를 만드는 방법?


__debug__는 모든 모듈에 영향을주기 때문에 변수는 부분에 편리합니다. 같은 방식으로 작동하는 다른 변수를 만들려면 어떻게해야합니까?

하나의 모듈에서 foo를 변경하면 다른 모듈에서 업데이트가 의미에서 변수는 (원래로하고 'foo'라고 부릅니다) 실제로 전역적일 필요는 없습니다. 다른 모듈을 접근하기 오기 전에 foo를 접근 할 수 있습니다. 그런 다음 같은 값을 볼 수 있습니다.


나는 어떤 식 으로든, 형태 나 형태 로이 솔루션을 보증하지 않습니다. 그러나 __builtin__모듈에 변수를 추가하면 __builtin__기본적으로 모든 모듈을 포함하는 다른 모듈의 전역 변수 처럼 액세스 할 수 있습니다 .

a.py 포함

print foo

b.py는 포함

import __builtin__
__builtin__.foo = 1
import a

결과적으로 "1"이 인쇄됩니다.

편집 :__builtin__모듈은 로컬 기호로 사용 가능 __builtins__합니다. 두 가지 답변이 일치하지 않습니다. 또한 python3에서 __builtin__이름이 바뀌 었습니다 builtins.


전역 교차 모듈 변수가 필요한 경우 간단한 전역 모듈 수준 변수로 충분합니다.

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


모듈을 정의하고 ( "globalbaz"라고 함) 변수를 정의하십시오. 이 "의사 전역"을 사용하는 모든 모듈은 "globalbaz"를 가져 오기 위해 "globalbaz.var_name"을 사용하여 참조해야합니다.

변경 위치에 관계없이 작동 상황 가져 오기 전후에 변수를 사용합니다. 모듈 모듈은 최신 값을 사용합니다. (나는 장난감 예제에서 이것을 테스트했다)

설명을 위해 globalbaz.py는 다음과 가변됩니다.

var_name = "my_useful_string"

나는 그것이 의미가있는 상황이 많이 많이 믿으며 여러 (단단히 결합 된) 모듈에서 일부 장치를 갖도록 프로그래밍을 단순화합니다. 이 정신에서, 나는 많은 것을 참조 할 필요가있는 모듈에 의해 수입되는 전역 모듈을 아이디어에 대해 조금 자세히 설명하고 싶습니다.

모듈이 하나만 있으면 이름을 "g"로 지정합니다. 여기에서 전역으로 취급하려는 모든 변수에 언급을 지정합니다. 사용하는 각 모듈에서 "from g import var"를 사용하지 않습니다. 이것은 로컬 변수 때 생성 만 생성되기 때문입니다. g.var 형식과 "g"형식으로 대부분 참조합니다. 다른 모듈에서 액세스 할 수있는 변수를 다루고 있음을 확인합니다.

지역 변수 전역의 값을 모듈의 일부 함수에서 자주 사용하는 경우 해당 함수는 로컬 복사본을 만들 수 있습니다. var = g.var. 그러나 var에 대한 할당은 로컬이며 할당에서 g.var을 ​​명시 적으로 참조하지 전역 g.var을 ​​업데이트 할 수 없습니다.

모듈의 다른 하위 집합에서 공유하는 여러 전역 모듈을 사용하여 작업을 좀 더 엄격하게 제어 할 수 있습니다. 전역 모듈에 짧은 이름을 사용하는 이유는 코드가 너무 많아서 코드가 복잡해지지 않습니다. 약간의 경험만으로도 1-2 자만으로 충분히 기억할 수 있습니다.

x가 g에 아직 정의되어 있지 않은 경우 gx에 할당을 할 수없는 다른 모듈이 gx에 액세스 할 수 있고, 인터프리터가 허용이 방법은 투명하지 피할 수 없습니다. 그것. 대입 변수 이름에 오타가있어 실수로 g에 새 변수를 생성 할 가능성이 있습니다. (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__하는 것이 일반적으로 이런 종류의 전역을 수행하는 더 깔끔한 방법입니다.


모듈 수준 변수로 이미이 작업을 수행 할 수 있습니다. 모듈은 가져 오는 모듈에 관계없이 동일합니다. 따라서 어떤 모듈에서든 변수를 모듈 수준의 변수로 만들고 다른 모듈에서 액세스하거나 할당 할 수 있습니다. 변수의 값을 설정하거나 일부 단일 객체의 속성으로 만드는 함수를 호출하는 것이 좋습니다. 이렇게하면 변수가 변경 될 때 일부 코드를 실행해야하는 경우 모듈의 외부 인터페이스를 손상시키지 않고 실행할 수 있습니다.

일반적으로 작업을 수행하는 좋은 방법은 아닙니다. 전역을 사용하는 경우는 드뭅니다.하지만 이것이 가장 깨끗한 방법이라고 생각합니다.


변수를 찾을 수없는 경우가 있다는 답변을 게시하고 싶었습니다.

주기적 가져 오기는 모듈 동작을 손상시킬 수 있습니다.

예를 들면 :

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

이 모듈은 벽을 가져오고 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.msgwall.router.msg더 이상 존재한다.

프로그램의 출력은 다음과 같습니다.

글로벌 : 안녕하세요!
라우터 : 안녕하세요!
글로벌 : 메시지 없음
라우터 : 메시지 없음

위의 코드 조각은 모듈 / 글로벌 및 클래스 / 클래스 변수 메커니즘이 본질적으로 동일 함을 보여줍니다.

많은 변수를 공유해야하는 경우 여러 벽 유형 모듈 (예 : wall1, wall2 등)을 사용하거나 단일 파일에 여러 라우터 유형 클래스를 정의하여 네임 스페이스 오염을 관리 할 수 ​​있습니다. 후자는 약간 더 깔끔하므로 클래스 변수 메커니즘을 사용하는 데있어 약간의 이점을 나타낼 수 있습니다.

참고 URL : https://stackoverflow.com/questions/142545/how-to-make-a-cross-module-variable

반응형