모듈에서 __getattr__
어떻게 이와 동등한 기능을 구현할 수 있습니까?__getattr__
수업에서, 모듈에서?
예
모듈의 정적으로 정의된 속성에 존재하지 않는 함수를 호출할 때 해당 모듈에 클래스의 인스턴스를 만들고 모듈의 속성 조회에서 실패한 것과 동일한 이름으로 메서드를 호출합니다.
class A(object):
def salutation(self, accusative):
print "hello", accusative
# note this function is intentionally on the module, and not the class above
def __getattr__(mod, name):
return getattr(A(), name)
if __name__ == "__main__":
# i hope here to have my __getattr__ function above invoked, since
# salutation does not exist in the current namespace
salutation("world")
이는 다음을 제공합니다.
matt@stanley:~/Desktop$ python getattrmod.py
Traceback (most recent call last):
File "getattrmod.py", line 9, in <module>
salutation("world")
NameError: name 'salutation' is not defined
여기에는 두 가지 기본적인 문제가 있습니다.
__xxx__
됩니다.TypeError: can't set attributes of built-in/extension type 'module'
어떤 솔루션이든 검사 중인 모듈을 추적해야 한다는 것을 의미합니다. 그렇지 않으면 모든 모듈이 인스턴스-분포 동작을 갖게 됩니다. (2) (1)이 불가능하다는 것을 의미합니다.적어도 직접적으로는 아닙니다.
것에 까다롭지 는 작동할액세스 ".modules")import somemodule; somemodule.salutation('world')
에 .globals()
수업에 사용자 지정 방법이 있거나(나는 사용하는 것을 좋아합니다)..export()
: 이미을 사용합니다. 또는 일반 기능(예: 이미 답변으로 나열된 기능)을 사용합니다.한 가지 명심해야 할 것은 래퍼가 매번 새로운 인스턴스를 만들고 글로벌 솔루션이 그렇지 않다면 미묘하게 다른 동작을 하게 된다는 것입니다. 둘 다 할 수 것은 중 입니다.', 고두가동사수것있아닙니다은아다둘니입하나. 중그리지.
갱신하다
Guido van Rossum에서:
실제로 가끔 사용되고 권장되는 해킹이 있습니다. 모듈은 원하는 기능을 가진 클래스를 정의할 수 있으며, 마지막에 sys.modules에서 자신을 해당 클래스의 인스턴스(또는 굳이 말하자면 클래스로)로 대체할 수 있습니다. 하지만 일반적으로 그것은 덜 유용합니다.예:
# module foo.py
import sys
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
sys.modules[__name__] = Foo()
이것은 가져오기 기계가 이 해킹을 활성화하고 있으며, 마지막 단계에서 로드 후 sys.modules에서 실제 모듈을 꺼내기 때문에 작동합니다. (이것은 사고가 아닙니다.)해킹은 오래 전에 제안되었고 우리는 수입 기계에서 지원할 만큼 충분히 좋다고 결정했습니다.)
것을 으로 "" " " " " " " 를 대체합니다.sys.modules[__name__]
당신의 수업의 예와 함께 -- 그리고 이제 당신은 가지고 놀 수 있습니다.__getattr__
/__setattr__
/__getattribute__
필요에 따라
참고 1: 이 기능을 사용할 경우 글로벌, 기타 기능 등 모듈의 다른 모든 기능은 다음 시간에 손실됩니다.sys.modules
할당이 이루어지므로 필요한 모든 항목이 대체 클래스 내에 있는지 확인합니다.
참고 2: 지원 대상from module import *
은 분은명히가 합니다.__all__
클래스에 정의됨. 예:
class Foo:
def funct1(self, <args>): <code>
def funct2(self, <args>): <code>
__all__ = list(set(vars().keys()) - {'__module__', '__qualname__'})
파이썬 버전에 따라 생략할 수 있는 다른 이름이 있을 수 있습니다.__all__
.set()
Python 2 호환성이 필요하지 않은 경우 생략할 수 있습니다.
얼마 전 Guido는 새로운 스타일의 클래스에 대한 모든 특별한 메소드 조회가 바이패스 및 .Dunder 메소드가 이전에 모듈에서 작동했다고 선언했습니다. 예를 들어, 단순히 정의함으로써 모듈을 컨텍스트 관리자로 사용할 수 있습니다.__enter__
그리고.__exit__
그 속임수들이 터지기 전에.
최근 몇 가지 역사적 특징들이 다시 등장했습니다, 모듈입니다.__getattr__
그들 중에서, 그래서 기존의 해킹(자신을 클래스로 대체하는 모듈).sys.modules
더 이상 필요하지 않아야 합니다.
Python 3.7+에서는 한 가지 분명한 방법을 사용합니다. 액세스를 하려면 " " " " " " 을 합니다.__getattr__
의 인수를입니다.AttributeError
:
# my_module.py
def __getattr__(name: str) -> Any:
...
" 즉, "from" 로 후크할 수 있습니다. 즉, "from" "from" "할 수 .from my_module import whatever
.
"getattr"을 .__dir__
자세한 내용은 PEP 562를 참조하십시오.
이것은 해킹이지만 클래스로 모듈을 감쌀 수 있습니다.
class Wrapper(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, name):
# Perform custom logic here
try:
return getattr(self.wrapped, name)
except AttributeError:
return 'default' # Some sensible default
sys.modules[__name__] = Wrapper(sys.modules[__name__])
우리는 보통 그런 식으로 하지 않습니다.
우리가 하는 일은 이것입니다.
class A(object):
....
# The implicit global instance
a= A()
def salutation( *arg, **kw ):
a.salutation( *arg, **kw )
왜죠? 암묵적인 글로벌 인스턴스를 볼 수 있도록 말입니다.
예를들어참, ▁at▁for시▁look참,십을 보세요.random
모듈은 암시적 전역 인스턴스를 만들어 "임의의" 난수 생성기를 원하는 사용 사례를 약간 단순화합니다.
것과해야 하는 (@ S 안한게하예유, 에구하야는경해우현제을모법사, 듈마가것과예▁@▁similar하는경(▁(:h우like▁on▁where▁case,:__getattr__
), , , , 에서types.ModuleType
그리고 그것을 집어넣습니다.sys.modules
정의가 하는 것을 권장합니다.)ModuleType
정의됨).
Werkzeug의 기본 파일에서 이를 상당히 강력하게 구현할 수 있습니다.
이건 좀 촌스럽긴 한데...
# Python 2.7
import types
class A(object):
def salutation(self, accusative):
print("hello", accusative)
def farewell(self, greeting, accusative):
print(greeting, accusative)
def AddGlobalAttribute(classname, methodname):
print("Adding " + classname + "." + methodname + "()")
def genericFunction(*args):
return globals()[classname]().__getattribute__(methodname)(*args)
globals()[methodname] = genericFunction
# set up the global namespace
x = 0 # X and Y are here to add them implicitly to globals, so
y = 0 # globals does not change as we iterate over it.
toAdd = []
def isCallableMethod(classname, methodname):
someclass = globals()[classname]()
something = someclass.__getattribute__(methodname)
return callable(something)
for x in globals():
print("Looking at", x)
if isinstance(globals()[x], (types.ClassType, type)):
print("Found Class:", x)
for y in dir(globals()[x]):
if y.find("__") == -1: # hack to ignore default methods
if isCallableMethod(x,y):
if y not in globals(): # don't override existing global names
toAdd.append((x,y))
# Returns:
# ('Looking at', 'A')
# ('Found Class:', 'A')
# ('Looking at', 'toAdd')
# ('Looking at', '__builtins__')
# ('Looking at', 'AddGlobalAttribute')
# ('Looking at', 'register')
# ('Looking at', '__package__')
# ('Looking at', 'salutation')
# ('Looking at', 'farewell')
# ('Looking at', 'types')
# ('Looking at', 'x')
# ('Looking at', 'y')
# ('Looking at', '__name__')
# ('Looking at', 'isCallableMethod')
# ('Looking at', '__doc__')
# ('Looking at', 'codecs')
for x in toAdd:
AddGlobalAttribute(*x)
if __name__ == "__main__":
salutation("world")
farewell("goodbye", "world")
# Returns:
# hello world
# goodbye world
이 작업은 글로벌 네임스페이스의 모든 개체에 대해 반복적으로 수행됩니다.항목이 클래스인 경우 클래스 속성을 통해 반복됩니다.속성을 호출할 수 있으면 이 속성을 함수로 글로벌 네임스페이스에 추가합니다.
"__"을 포함하는 모든 특성을 무시합니다.
이것을 생산 코드에 사용하지는 않겠지만, 당신을 시작하게 해줄 것입니다.
여기 저의 보잘것없는 기여가 있습니다. @Hovard S의 높은 평가를 받은 답변을 약간 장식했지만, 조금 더 명확하게 표현했습니다. @S도 받아들일 수 있을 것입니다.로트, OP에 충분하지 않을 수도 있지만):
import sys
class A(object):
def salutation(self, accusative):
print "hello", accusative
class Wrapper(object):
def __init__(self, wrapped):
self.wrapped = wrapped
def __getattr__(self, name):
try:
return getattr(self.wrapped, name)
except AttributeError:
return getattr(A(), name)
_globals = sys.modules[__name__] = Wrapper(sys.modules[__name__])
if __name__ == "__main__":
_globals.salutation("world")
클래스가 있는 모듈 파일을 만듭니다.모듈을 가져옵니다.려달을 합니다.getattr
모듈에서 다운로드할 수 있습니다.다음을 사용하여 동적 가져오기를 수행할 수 있습니다.__import__
sys.sys.sys.module에서 .
의 모듈이 있습니다.some_module.py
:
class Foo(object):
pass
class Bar(object):
pass
그리고 다른 모듈에서는:
import some_module
Foo = getattr(some_module, 'Foo')
동적으로 이 작업 수행:
import sys
__import__('some_module')
mod = sys.modules['some_module']
Foo = getattr(mod, 'Foo')
언급URL : https://stackoverflow.com/questions/2447353/getattr-on-a-module
'source' 카테고리의 다른 글
Git가 프록시 서버와 함께 작동하도록 하는 중 - "Request timeout"(요청 시간 초과됨)으로 인해 실패합니다. (0) | 2023.05.02 |
---|---|
ASP의 주장은 무엇입니까?NET 아이덴티티 (0) | 2023.05.02 |
Makefile targets에서 Bash 구문을 사용하려면 어떻게 해야 합니까? (0) | 2023.04.27 |
Haskell을 사용한 Excel 자동화로 세그먼트 결함 발생 (0) | 2023.04.27 |
ASP에서 divs를 위한 코드 뒤에 있는 파일에서 CSS 스타일을 어떻게 수정합니까?NET? (0) | 2023.04.27 |