Мой вопрос очень похож на этот, но в моем случае принятый ответ не украшает все функции в пакете, когда они используются внутри пакета, и я не уверен, почему.
Например, у меня есть такой проект:
project/
package/
__init__.py
module_a.py
module_b.py
main.py
__init__.py
from .module_a import *
from .module_b import *
import types
# This is the decorator that will be used
from functools import lru_cache
for name, obj in list(globals().items()):
if isinstance(obj, types.FunctionType):
globals()[name] = lru_cache(maxsize=100)(obj)
module_a.py
from .module_b import b
def a(arg):
return b
module_b.py
def b(arg):
return arg
main.py
import package
print(package.a.cache_info())
print(package.a(None).cache_info())
print(package.b.cache_info())
Когда пакет импортируется, __init__.py
прекрасно украшает функции в globals
при пошаговом выполнении кода. Однако, если я выполняю main.py
, я получаю следующую ошибку:
C:\Users\pbreach\Anaconda3\python.exe C:/Users/pbreach/PycharmProjects/project/main.py
Traceback (most recent call last):
CacheInfo(hits=0, misses=0, maxsize=100, currsize=0)
File "C:/Users/pbreach/PycharmProjects/project/main.py", line 4, in <module>
print(package.a(None).cache_info())
AttributeError: 'function' object has no attribute 'cache_info'
Это означало бы, что b
не украшается при импорте из module_b
в module_a
.
Почему это происходит только во второй строке? Как можно этого добиться?
Я нормально выполняю декорирование либо во время импорта в __init__.py
, либо в main.py
, но я бы предпочел не применять декоратор внутри каждого модуля в package
, поскольку в моем случае их довольно много.
РЕДАКТИРОВАТЬ:
Я думаю, проблема в том, что globals
в __init__.py
- это другое пространство имен, чем когда b
импортируется в module_a
, что означает наличие двух разных экземпляров одной и той же функции. Это можно обойти?