/ / Použitie dekoratéra na všetky funkcie v balíku python - python, python-3.x, python-import, memoizácia, python-decorators

Použitie dekorátora na všetky funkcie balíka python - python, python-3.x, python-import, memoization, python-decorators

Moja otázka je veľmi podobná toto, ale v mojom prípade prijatá odpoveď nezdobí všetky funkcie v balení, keď sa používajú v rámci balíka a ja si nie som istý prečo.

Napríklad mám nastavený projekt takto:

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())

Keď sa balík importuje, __init__.py zdobí funkcie v globals v poriadku, keď prechádzate kódom. Ak však vykonám main.py Mám nasledujúcu chybu:

C:UserspbreachAnaconda3python.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"

Čo by to znamenalo b nie je ozdobený, ak je dovezený module_b v module_a.

Prečo k tomu dochádza len v druhom riadku? Čo by to mohlo byť?

Som v pohode s robiť zdobenie buď pri dovoze do __init__.py alebo v main.py, ale radšej by nemusel aplikovať dekoratéra vo vnútri každého modulu package ako v mojom prípade je ich pomerne málo.

Myslím si, že problémom je, že globals v __init__.py je iný menný priestor ako kedykoľvek b sa importuje do module_a znamená, že existujú dve rôzne inštancie rovnakej funkcie. Existuje nejaká cesta okolo toho?

odpovede:

1 pre odpoveď č. 1

Dovážíte b z module_b v module_a skôr, než dostanete šancu ju ozdobiť functools.lru_cache.

Vidím len jedinú životaschopnú alternatívu, ktorá je najprv explicitne zdobená funkciami, ktoré sa dovážajú a používajú v iných submodulách a potom aplikujú dekoratér na všetky ostatné funkcie.

Pomocou svojho príkladu najprv ozdobte b z module_b a potom ozdobíme zvyšok:

from package import module_b

import types
# This is the decorator that will be used
from functools import lru_cache
module_b.b = lru_cache(maxsize=100)(module_b.b)

from .module_a import *
from .module_b import *

for name, obj in list(globals().items()):
if isinstance(obj, types.FunctionType):
globals()[name] = lru_cache(maxsize=100)(obj)

Ďalšou možnosťou, ako som uviedol v komentári, by bolo použiť if klauzuly vo vnútri modulov, ktoré obsahujú funkcie, ktoré sú zahrnuté v iných moduloch, kde by sa tam nachádzalo balenie.

Takže v module_b.py mohli by ste vykonať niečo takéto:

if __name__ != "__main__":
from functools import lru_cache
b = lru_cache(b)

toto len zachytí prípad, keď modul nie je spustený ako __main__, Teraz, keď iný modul obsahuje tento modul a jeho telo sa spúšťa, obal sa bude vykonávať tu namiesto __init__.py.