source

모듈 간 변수를 만드는 방법은 무엇입니까?

ittop 2023. 8. 5. 11:01
반응형

모듈 간 변수를 만드는 방법은 무엇입니까?

__debug__변수는 모든 모듈에 영향을 미치기 때문에 부분적으로 유용합니다.동일한 방식으로 작동하는 다른 변수를 생성하려면 어떻게 해야 합니까?

변수(원래 변수로 'foo'라고 부르자)는 한 모듈에서 foo를 변경하면 다른 모듈에서 업데이트된다는 점에서 진정한 글로벌 변수일 필요는 없습니다.다른 모듈을 가져오기 전에 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 앱에서는 객체를 가져와서 설정을 사용하지만).

저는 어떤 식으로든, 형태로든 이 해결책을 지지하지 않습니다.에 하면,__builtin__module,를 수 .__builtin__기본적으로 모든 것입니다.

a.py 에는 다음이 포함됩니다.

print foo

b.py 에는 다음이 포함됩니다.

import __builtin__
__builtin__.foo = 1
import a

그 결과 "1"이 인쇄됩니다.

편집: The__builtin__ 기호는 "Module"입니다.__builtins__그것이 이 답변들 중 두 개 사이의 불일치의 이유입니다. 또참고는 다음과 .__builtin__로 이름이 변경되었습니다.builtins파이썬3로.

저는 그것이 이치에 맞는 많은 상황이 있다고 생각하며, 그것은 프로그래밍을 단순화하여 여러 모듈에 걸쳐 알려진 일부 글로벌을 갖게 합니다.이러한 정신으로, 저는 글로벌 모듈을 참조할 필요가 있는 모듈이 가져온 글로벌 모듈을 갖는 아이디어에 대해 조금 더 자세히 설명하고 싶습니다.

그러한 모듈이 하나만 있을 때, 저는 그것을 "g"라고 이름 지었습니다.여기서 전역으로 취급하려는 모든 변수에 기본값을 할당합니다.이 중 하나를 사용하는 각 모듈에서는 "from gimport var"를 사용하지 않습니다. 이는 가져오기 시에만 g에서 초기화되는 로컬 변수만 발생하기 때문입니다.저는 대부분 g.var 형식으로 참조하며, "g."는 제가 다른 모듈에 액세스할 수 있는 변수를 처리하고 있다는 것을 지속적으로 상기시키는 역할을 합니다.

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

또한 이러한 글로벌 모듈을 여러 모듈의 다른 하위 집합에서 공유하여 보다 엄격하게 제어할 수 있습니다.글로벌 모듈에 짧은 이름을 사용하는 이유는 코드가 너무 복잡해지는 것을 방지하기 위해서입니다.약간의 경험만으로, 그들은 1~2개의 문자만으로 충분히 기억력이 좋아집니다.

x가 아직 정의되지 않은 경우 g.x에 할당할 수 있으며 다른 모듈이 g.x에 액세스할 수 있습니다.하지만, 통역사가 그것을 허락하더라도, 이 접근법은 그렇게 투명하지 않고, 저는 그것을 피합니다.할당에 대한 변수 이름의 오타로 인해 실수로 새 변수 g가 생성될 가능성이 여전히 있습니다.때때로 dir(g)의 검사는 그러한 사고로 인해 발생했을 수 있는 놀라운 이름을 발견하는 데 유용합니다.

모듈("globalbaz"라고 함)을 정의하고 내부에 변수를 정의합니다.이 "pseudglobal"을 사용하는 모든 모듈은 "globalbaz" 모듈을 가져와 "globalbaz"를 사용하여 참조해야 합니다.var_name"

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

설명하자면, 글로벌 바즈입니다.파이는 다음과 같이 보입니다.

var_name = "my_useful_string"

한 모듈의 전역을 다른 모듈로 전달할 수 있습니다.

모듈 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

이 예에서는 분명해야 하지만 대규모 코드 기반에서는 매우 혼란스러울 수 있습니다.

변수 값을 전달하기 위해 글로벌/하이브리드 네임스페이스가 아닌 클래스 네임스페이스를 사용하여 글로벌 변수를 사용할 때의 몇 가지 단점(예: http://wiki.c2.com/ ?GlobalVariablesAreBad)을 피할 수 있는지 궁금합니다.다음 코드는 두 방법이 본질적으로 동일함을 나타냅니다.아래 설명과 같이 클래스 네임스페이스를 사용하면 약간의 이점이 있습니다.

또한 다음 코드 조각은 전역/모듈 이름 공간과 클래스 이름 공간 모두에서 속성 또는 변수가 동적으로 생성 및 삭제될 수 있음을 보여줍니다.

wall.py

# Note no definition of global variables

class router:
    """ Empty class """

변수를 튕겨낼 때 사용하기 때문에 저는 이 모듈을 '벽'이라고 부릅니다.빈 클래스 'router'의 글로벌 변수와 클래스 전체 속성을 임시로 정의하는 공간 역할을 합니다.

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.msg그리고.wall.router.msg더 이상 존재하지 않습니다.

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

글로벌: 안녕하세요!
안녕 세상아!
: 메시지 없음: 없음
없음: 없음: 메시지 없음

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

많은 변수를 공유해야 하는 경우 wall1, wall2 등과 같은 여러 개의 wall-type 모듈을 사용하거나 단일 파일에 여러 개의 라우터 유형 클래스를 정의하여 네임스페이스 오염을 관리할 수 있습니다.후자가 약간 더 깔끔하기 때문에 아마도 클래스 변수 메커니즘의 사용에 대한 한계 이점을 나타낼 수 있습니다.

이것은 수정하는 것처럼 들립니다.__builtin__네임스페이스입니다.수행 방법:

import __builtin__
__builtin__.foo = 'some-value'

사용 안 함__builtins__직접(추가 "s" 포함) - 명백히 사전 또는 모듈일 수 있습니다.이 점을 지적해 주신 τωτζιο 덕분에, 여기에서 더 많은 것을 찾을 수 있습니다.

지금이다foo어디서나 사용할 수 있습니다.

일반적으로 이 작업을 수행하는 것을 권장하지는 않지만, 이 작업의 사용은 프로그래머에게 달려 있습니다.

위와 같이 할당해야 합니다. 설정만 하면 됩니다.foo = 'some-other-value'현재 네임스페이스에서만 설정됩니다.

저는 이것을 제가 정말로 부족하다고 느꼈던 내장된 원시적인 기능에 사용합니다.하나의 예는 필터, 맵, 축소와 동일한 사용 의미를 갖는 찾기 함수입니다.

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()가 내장된 것처럼 보입니다.

find(lambda i: i < 0, [1, 3, 0, -5, -10])  # Yields -5, the first negative.

참고: 물론 필터와 다른 라인을 사용하여 제로 길이를 테스트하거나 하나의 이상한 라인을 축소하여 이 작업을 수행할 수 있지만, 저는 항상 이상하다고 느꼈습니다.

사전을 사용하여 교차 모듈 수정 가능(또는 가변) 변수를 얻을 수 있었습니다.

# 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초입니다.

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

반응형