Jawaban singkatnya: gunakan proxy_tools
The proxy_tools
paket mencoba untuk memberikan @module_property
fungsionalitas.
Ini menginstal dengan
pip install proxy_tools
Menggunakan sedikit modifikasi dari contoh @ Marein, the_module.py
kami masukkan
from proxy_tools import module_property
@module_property
def thing():
print(". ", end='') # Prints ". " on each invocation
return 'hello'
Sekarang dari skrip lain, saya bisa melakukannya
import the_module
print(the_module.thing)
# . hello
Perilaku tidak terduga
Solusi ini bukannya tanpa peringatan. Yaitu, the_module.thing
adalah tidak string ! Ini adalah proxy_tools.Proxy
objek yang metode khususnya telah diganti sehingga meniru string. Berikut adalah beberapa tes dasar yang menggambarkan hal tersebut:
res = the_module.thing
# [No output!!! Evaluation doesn't occur yet.]
print(type(res))
# <class 'proxy_tools.Proxy'>
print(isinstance(res, str))
# False
print(res)
# . hello
print(res + " there")
# . hello there
print(isinstance(res + "", str))
# . True
print(res.split('e'))
# . ['h', 'llo']
Secara internal, fungsi asli disimpan ke the_module.thing._Proxy__local
:
print(res._Proxy__local)
# <function thing at 0x7f729c3bf680>
Pikiran lebih lanjut
Sejujurnya, saya bingung tentang mengapa modul tidak memiliki fungsi bawaan ini. Saya pikir inti masalahnya adalah itu the_module
adalah turunan dari types.ModuleType
kelas. Menyetel "properti modul" berarti menyetel properti pada instance kelas ini, bukan pada types.ModuleType
kelas itu sendiri. Untuk lebih jelasnya, lihat jawaban ini .
Kami sebenarnya dapat mengimplementasikan properti pada types.ModuleType
sebagai berikut, meskipun hasilnya tidak bagus. Kami tidak dapat langsung mengubah tipe bawaan, tetapi kami dapat mengutuknya :
# python -m pip install forbiddenfruit
from forbiddenfruit import curse
from types import ModuleType
# curse has the same signature as setattr.
curse(ModuleType, "thing2", property(lambda module: f'hi from {module.__name__}'))
Ini memberi kita properti yang ada di semua modul. Ini agak sulit, karena kami merusak perilaku pengaturan di semua modul:
import sys
print(sys.thing2)
# hi from sys
sys.thing2 = 5
# AttributeError: can't set attribute
__getattr__
modul untuk solusi yang lebih modern.