를, 솔루션보다 모듈 수준의 변수에 의존하는 것이 아니라 다른 방법으로 객체의 상태를 유지하는 것입니다. 파이썬 모듈은 "싱글 톤 (singletons)"입니다. 즉, 모듈에 의해 일단 임포트되면, 인터프리터 와이드 버전이 하나만 존재합니다. 예를 들어, 원하는 동작은 클래스를 사용하면 무료로 얻을 수 있습니다 상속 - 하위 클래스는 일부를 사용자 정의 할 수 있지만 모든 클래스를 다시 작성할 필요는 없습니다. 당신이 많은 클래스 내부에 "foo는"코드를 캡슐화 같은 경우
그래서 - 당신도 인스턴스를 필요로하는 클래스를 작성해야하지 않을 수 있습니다, 당신은 기능을 얻을 당신은 이미 원하는 :
#foo module:
class Foo(object):
sanitize = "value 1"
@classmethod
def parse(cls):
print cls.sanitize
#foo2
from foo import Foo
class Foo2(Foo):
sanitize = "value 2"
# code:
from foo import Foo
from foo2 import Foo2
Foo.parse()
Foo2.parse()
의 물론, 파이썬이 허용하는 내성과 메타 프로그래밍의 치어 리더 양과 함께라면, 은이 원하는대로 할 수 있습니다.하지만 문제가 복잡 할 수 있습니다. 모듈 변수는 C 코드에서 전역 변수와 동일한 단점을 가지고 있습니다.
foo2를 통해 액세스 할 때 "foo"를 작성하여 변수를 즉시 변경하고 "foo"의 함수를 호출 한 다음 exit시 previosu 값을 복원하는 것이 한 가지 방법입니다. 모듈 "foo2"의 "foo"에 대한 속성 액세스에서 임의의 코드가 트리거되도록하려면 "foo"가 "속성"속성이있는 객체를 참조해야합니다. -
이렇게 작성한 EXA 예제는 에서는 foo2 더 또는 덜 작성된 경우, BTW하는 concurency 안전하지 않은 방법으로 매우 안전하지 않은 방법을 실행
import foo as _foo
SANITIZE = "value2"
class _FooWrapper(object):
def __getattribute__(self, attr):
self.change_vars()
original_function = getattr(_foo, attr)
if callable(original):
def wrapper(func):
def new_func(*args, **kw):
res = func(*args, **kw)
self.restore_vars()
return res
return new_func
return wrapper(original)
return original
def change_vars(self):
self.original_sanitize = _foo.SANITIZE
_foo.SANITIZE = SANITIZE
def restore_vars(self):
__foo.SANITIZE = self.original_sanitize
foo = _FooWrapper()
이 액세스 한 모듈에서는 foo2에 "foo는"객체를 생성은, 어떤에서 속성을 요청 검색 대신 원래 "foo"모듈. 그래서 "foo2.foo.parse"는 "foo"구문 분석 함수를 얻을 것이지만 -이 접근법에서 "hackiness"의 양을 인식합니다. - 내부에있는 "foo"모듈의 원래 값을 복원 할 수 있습니다. 파이썬 인터프리터는 함수가 foo2에서 가져온 후, 함수가 리턴했을 때 값 자체를 복원합니다. 이렇게하는 유일한 방법은 반환 할 때 추가 코드를 실행하도록 함수를 수정하는 것입니다. 위의 코드로 즉석에서 꾸며집니다.
이 예제는 가능한 경우 모듈 수준 구성을 사용하는 것이이 경우에는 사용할 수 없다는 것을 분명히합니다.
편집 O.P. 댓글 :
감사 jsbueno, 불행하게도이 내 코드가 아닙니다 내가 에 모듈 수준 변수를 의존해야합니다. 래퍼 클래스 방법은 재미 있지만 말했듯이, 매우 해키 내가 두려워 이
응답에서
것과 내 경우에하지 않을거야 믿을 수 없을 정도로 비 스레드 안전 :
모듈은 "싱글 톤"이므로 모듈의 변수를 변경하면 에 어떤 점이든 스레드가 안전하지 않게됩니다. 내가 생각할 수있는 다른 방법은 을 가져올 때 클래스, 속성 및 다른 인스턴스의 인스턴스를 실제로 다시 만드는 "복사기"모듈을 만드는 것입니다. 모든 함수 전역 변수를 리 바인드합니다 (메소드는 으로 여전히 처리됩니다). 그것은 "unfeasable"로 들리 겠지만이 설명을 읽고이 수준의 기능)
- 그러나 그것은 쉽게보다 수행 설명 - 다음은 위의 않습니다 내 "에서는 foo2"모듈을 다음을 :
from types import ModuleType, FunctionType
import foo as _foo
SANITIZE = "value 2"
def rebuild_function(func, glob):
"""Rebinds the globals in the given functions to globals in
this module by default"""
new_func = FunctionType(func.func_code,
glob,
func.func_name,
func.func_defaults,
func.func_closure)
return new_func
def rebuild_class(cls, glob):
metatype = type(cls)
dct = cls.__dict__.copy()
for key, value in dct.items():
if isinstance(value, FunctionType):
dct[key] = rebuild_function(value, glob)
return metatype(cls.__name__, cls.__bases__, dct)
def rebuild_module(mod,glob):
new_module = ModuleType(mod.__name__)
for key, value in mod.__dict__.items():
if isinstance(value, FunctionType):
value = rebuild_function(value, glob)
elif isinstance(value, type):
value = rebuild_class(value, glob)
setattr(new_module, key, value)
return new_module
foo = rebuild_module(_foo, globals())
__all__ = ["foo", "SANITIZE"]
이 코드는 정확하게 수행한다. 필자가 설명한 바에 따르면, 원래 모듈에있는 모든 함수 객체를 다시 만들고 각 함수에 대한 전역 명령을 재구성합니다. 동시성에 안전합니다. 클론 된 모듈이 네이티브 코드 클래스 나 함수를 가리키는 경우 ("FunctionType"이 아닌) 몇 가지 경우가 있습니다. 다중 클래스 상속, 메타 클래스를 많이 사용하는 경우 - 작업을하거나하지 않습니다.
나는 간단한 클래스를 테스트하고 그것을 잘 작동 :
#module "foo"
SANITIZE='foo'
def parse():
print SANITIZE
class Parser(object):
def __init__(self):
print SANITIZE * 2
그리고
#test script
import foo
import foo2
foo2.foo.parse() #i want this to print 'foo2'
foo2.foo.Parser()
foo.parse() #i want this to print 'foo'
foo.Parser()
을 출력 :
[[email protected] tmp16]$ python test_foo.py
foofoo
value 2
value 2value 2
foo
foofoo
[[email protected] tmp16]$
이 코드는 의미, foo.parse가되지 않습니다()는 어떤 경우에도 'foo'를 출력 할 것이고, 어떤 식 으로든 SANITIZE에 의존하지 않는 상수이다. – yurib
유 리브에 대해 미안 해요. – djs22
당신은 언제든지 delf와 foo.py를 다시로드 할 수 있습니다. –