2016-10-20 1 views
2

편집 : 좋아, 나는 거의 그것을 알아 냈다. (내가 원한 것은 100 %는 아니지만, 여전히 작동한다.) 그것은 execfile() 기능입니다, 나는 그곳에 몰랐다는 것을 믿을 수 없습니다.전역 변수를 선언하는 함수 가져 오기

나는이 문구를 어떻게 표현할 지 잘 모르겠다. (이것이 나의 구글 검색이 사실상 아무 것도 나타나지 않는 이유이다.) 그러나 여기에 간다. 내가하려는 일의 단순화 된 버전을 제공 할 것입니다. 두 파일, main.pyextra.py이 있다고 가정 해 보겠습니다. 내가 콘솔에서이 작업을 실행하면

# extra.py 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    global foo 
    foo = 5 

그래서 매우 간단합니다 :

>>> setfoo() 
>>> foo 
5 

은 이제 main.py까지 머리를 뒤로하자 후자는 다음과 같이 보인다. 나는 extra.py에서 모든 가져 오기 문을 설정할 수 있습니다 :

# main.py 

from extra import * 

setfoo() 
print foo 

모든 것이 마지막 줄까지 잘 작동을; 그러나 main.pyfoo에 액세스하려고하면 foo이 실제로 파일 extra.py에 저장되므로 인식하지 못합니다. setfoo()을 실행 한 후에 모든 항목을 다시 가져 오면 foo을 가져오고 모든 것이 올바르게 작동합니다. 그래서 같이 : 나는 from...import 문 대신 표준 import 문을 사용하는 경우 또는

# main.py 

from extra import * 

setfoo() 
from extra import * 
print foo 

, extra.py의 데이터에 직접 액세스하는 것이 아니라 복사되고 있기 때문에, 모든 것을 다시 가져와야 할 필요가 없다.

# main.py 

import extra 

extra.setfoo() 
print extra.foo 

그러나, 나는 정말 extra.setfoo()에게 내가 setfoo()을 실행 할 때마다를 입력 할 필요가 싶지 않아,도 내가 extra.py에게 내가 말한 기능을 사용할 때마다 다시 가져올 싶어 : 그래서 이것은 또한 작동합니다. 이 문제에 대한 해결 방법이 있는지 알고 싶습니다. 이상적으로는 원래 코드 main.py에서 설정 한 코드가 올바르게 작동하도록 extra.py을 수정하는 방법이 있습니다. (EDIT : 여러 사람이 이것을 잘못 해석 한 것 같습니다. extra.py을 수정하려고합니다.이 코드를 가져 오려면 맨 위의 import 문을 변경하지 않고 main.py을 변경하고 싶지 않습니다.) 또한 다른 방법을 사용하여 가져 오는 extra.py (나는 PHP의 includerequire 문과 비슷한 것으로 생각합니다. 가져온 코드는 말 그대로 복사되어 파일에 붙여 넣어집니다.) 이 수정 된 import 문은 여전히 ​​한 줄의 코드 일 뿐이지 그리 오래 걸리지는 않습니다. 즉, 파일 처리와 함께 exec 문을 사용하면 아마도이 목적에 매우 편리하지 않을 것입니다.

exec 문에 대해 말하면, 내가 사용하는 코딩 방법이 얼마나 나쁜지는별로 신경 쓰지 않습니다. 이 extra.py 파일의 실제 버전이 지금부터 내 프로젝트 전부에서 사용할 계획이므로이 작업을 수행하는 방법이 필요합니다. 추가 공간을 많이 차지하지 않으려 고합니다. 이 파일을 가져올 때마다 내 코드. 어떤 도움을 주시면 감사하겠습니다.

편집 :이 글을 읽는 많은 사람들이 내가 성취하려고하는 것에 대해 정확히 명확하지 않으므로 여기에 내 코드의 실제 버전이 나와 있습니다. 그것은 "인라인 변수 할당"을 달성하기 위해 함께 사용한 구문 해킹입니다.

class use_obj(object): 
    def __rshift__(self, other): return other 

def use(**kwargs): 
    for var in kwargs: exec 'global ' + var + '; ' + var + ' = kwargs[var]' 
    return use_obj() 

구문은 다음과 같습니다 : 여기에 (다른 파일로 가져올하지 않는 경우 잘 작동) 코드입니다

print use(x = 5, y = 8) >> str(x) + " times " + str(y) + " equals " + str(x*y) 

코드 자체는 꽤 총 되나 필자는 인라인 if 문, list comprehensions, lambdas + reduce() 등의 큰 팬이므로 인라인 변수 할당을 수행하는 방법을 항상 원했습니다. 왜냐하면 단순히 함수를 반환 할 수없는 이유는 할당 된 변수를 반환하는 것이기 때문입니다. use(x = 5, y = 8) 이상한 객체를 반환하는 표현식 (문이 아닌)입니다. 그런 다음을 사용하여 코드에 밀어 넣습니다. 0 연산자와 함수를 설정하는 방식으로 인해 use() 함수가 마술처럼 반환 된 이상한 객체가 사라집니다.

나는 그것을 같이한다면 코드가 아름다움과 새로움을 많이 잃을 것이라고 생각 :

print use(x = 5, y = 8) >> str(extras.x) + " times " + str(extras.y) + " equals " + str(extras.x*extras.y) 
+0

'extra.py'를 초기화하는 동안 당신은'foo'을 설정하지 않는 어떤 이유가 있습니까? 그렇지 않으면 가능한 해결책은'foo = None'을 설정하는 것입니다. –

+0

내가 말했던 것처럼, 이것은 내가 실제로하려고하는 것의 지나치게 단순화 된 버전이다. 함수의 실제 버전은'foo'를 설정하는 방식으로 여러 변수를 설정합니다. 어떤 변수를 설정할지 알 수있는 방법이 없습니다. 그래서 창 밖입니다. –

답변

1

첫째, 는 당신의 foo는 참조를 얻기 위해 sys 모듈의 도움을 받아 할 것 추가 모듈.

import sys 
from extra import * 

print('1. Foo in globals ? {0}'.format('foo' in globals())) 
setfoo() 
print('2. Foo in globals ? {0}'.format('foo' in globals())) 
# Check if extra has foo in it 
print('2. Foo in extra ? {0}'.format(hasattr(sys.modules['extra'], 'foo'))) 
# Getting foo explicitly from extra module 
foo = sys.modules['extra'].foo 
print('3. Foo in globals ? {0}'.format('foo' in globals())) 
print("Foo={0}".format(foo)) 

출력 : 나중에 유스 케이스에 대한

1. Foo in globals ? False 
2. Foo in globals ? False 
2. Foo in extra ? True 
3. Foo in globals ? True 
Foo=5 

업데이트 : 수입을 얻고 글로벌 변수를 업데이트 수정 extra.py,

# extra.py 
import sys 

def use(**kwargs): 
    _mod = sys.modules['__main__'] 
    for k, v in kwargs.items(): 
     setattr(_mod, k, v) 

지금 모든 파일 유적에서 가져 오기 동일,

#myfile.py 
from extra import * 
print use(x = 5, y = 8), str(x) + " times " + str(y) + " equals " + str(x*y) 

출력 : 사용 기능은 아무 것도 반환하지 않습니다으로

None 5 times 8 equals 40 

None가 나타납니다.

참고 : 파이썬으로 조금 재미를 기울이지 않는 한, 더 좋은 파이썬 솔루션을 선택하는 것이 좋습니다.

파이썬 범위 규칙에 대한 참조 : Short Description of the Scoping Rules?

+0

"Python으로 약간 재미있게 지내기"가 정확합니다. 위의 편집을 참조하십시오. 원격으로 "파이썬 (pythonic)"으로 간주 될 수있는 방법은 없습니다. 제발, 당신이 위에서 쓴 것을 처리하려고합니다. –

+0

'globals()'가 지금 무엇을하는지 이해하려고 시도하지는 않습니다. (이전에이 함수에 대해 들어 보지 못했습니다.)하지만 역으로 생각한 것처럼 보입니다. 나는 'extra.py'를 수정하고 싶을 수 있습니다. 만지지 않고 싶다면'main.py'입니다. –

+0

업데이트를 확인하십시오. 이 경우 main.py를 수정하지 않아도됩니다. –

0

모듈 개체에 바인딩 변수 이름있는 네임 스페이스를 가지고있다. from extra import *을 수행하면 extra의 네임 스페이스에있는 객체를 가져 와서 새 모듈의 새 변수에 바인딩합니다. setfoo이 호출되지 않은 경우 extra에는 foo이라는 변수가없고 새 모듈 네임 스페이스에 바인딩 할 것이 없습니다.

setfoo이 있었다면, from extra import *이이를 발견했을 것입니다. 그러나 일들은 여전히 ​​펑키 할 수 있습니다. 어떤 할당 집합이 extra.foo에서 42으로 설정된다고 가정 해보십시오. 음, 다른 모듈 네임 스페이스는 그것에 대해 알지 못하므로 다른 모듈에서는 foo이 여전히 5이지만 extra.foo42이됩니다.

주어진 시간에 개체와 개체를 참조 할 수있는 것들 간의 차이점을 항상 명심하십시오. 객체는 어떤 변수 나 컨테이너가 참조를하는지 알지 못합니다 (참조 수를 세어도). 변수 또는 컨테이너가 다른 오브젝트에 리 바인드되면 다른 변수 또는 컨테이너의 바인딩은 변경되지 않습니다.

+0

네, 저도 인터넷 검색에서 배웠습니다. 'extra.py'가 가져온 파일 (이 경우'main.py')의 네임 스페이스에서 변수를 설정할 수있는 방법이 있는지 알고 있습니까? 나는 그것이 내 문제를 해결할 것이라고 생각한다. –

+0

그럴 수는 없지만 자신의 컨테이너 안에'extra '를 넣을 수 있습니다 (예를 들어'my_config = {'foo ': 5}'). 그러나 더 좋은 해결책은'여분의 import *'를하지 않는 것입니다. 방금'import extra'를 실행하고 변수를'extra.foo'로 참조하면 모든 사람이'extra' 네임 스페이스에서 동일한 객체를 참조하게 될 것입니다. 즉, 모듈은 컨테이너이므로 참조하는 것입니다. – tdelaney

+0

그것은 슬프게도 옵션이라고 생각합니다. 나는'foo'가 아니라'foo'가 아니라'foo'가 아니라'foo'에 접근 할 필요가 있습니다. 사전처럼 컨테이너에 넣으면 역시 내가하려는 것을 이루지 못할 것입니다. –

0

세부 정보가 없으면 전역 변수로 선언하는 대신 fooextra.py setfoo() 함수로 반환하는 것이 좋습니다.

이어서 main.py 글로벌 foo 선언 외부 기능 여기 setfoo()

로부터 값을 공급하는 설정을

#extra.py 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    #global foo 
    foo = 5 
    return foo 

#main.py 

from extra import setfoo 

global foo 

foo = setfoo() 
print foo 

결과 :

Python 2.7.9 (default, Dec 10 2014, 12:24:55) [MSC v.1500 32 bit (Intel)] on win32 
Type "copyright", "credits" or "license()" for more information. 
>>> ================================ RESTART ================================ 
>>> 
5 
>>> 

EDIT 1 -
이 문제는 정상입니다.

특정 요구 사항이있는 경우 __builtin__ 모듈에 변수를 추가하면 __builtin__을 포함하는 한 다른 모듈의 전역 변수로 액세스 할 수 있습니다.

#extra.py 

import __builtin__ 

def setfoo(): # sets "foo" to 5 even if it is unassigned 
    global foo 
    __builtin__.foo = 5 


#main.py 

from extra import * 
setfoo() 
print foo 

출력 : 정말 너무하려는 경우, extra.py을 수정하지 않고 변수를 가져올 수있는 방법을

>>> 
5 
>>> 
+0

'main '에서 코드를 수정하는 것을 싫어합니다.py'는 내가 수입하는 방식을 수정하는 것이 아니라면, 의문의 여지가 많습니다. 이것은 실제로 작동하는 정말 이상한 구문 "hack"을위한 것입니다. 그래서 매우 특정한 필요성이 있습니다. 그리고 그 코드 행을 표현식으로 사용해야하기 때문에'foo = setfoo()'와 같은 것을 사용할 수 없습니다. 주장이 아닌. –

+0

'extra, py'를 조금 수정할 수 있다면, 위의 수정 된 해결책을 참조하십시오. –

+0

이것은 멀리까지 조금씩 나아가고있는 것처럼 보입니다. 이렇게하면, 다른 사람에게 보내면 코드가 작동하지 않을 것입니다. 단지 그것을 명확하게하기 위해, 나는'extra.py'를 수정할 수 있었고, 이것이 내 질문의 주요 목적이었습니다.이 코드를 작동 시키려면 변경하지 않으려 고하는'main.py'가 있습니다. –