Một câu trả lời ngắn gọn: sử dụng proxy_tools
Các proxy_tools
gói nỗ lực để cung cấp @module_property
chức năng.
Nó cài đặt với
pip install proxy_tools
Sử dụng một chút sửa đổi ví dụ của @ Marein, the_module.py
chúng tôi đưa
from proxy_tools import module_property
@module_property
def thing():
print(". ", end='') # Prints ". " on each invocation
return 'hello'
Bây giờ từ một tập lệnh khác, tôi có thể làm
import the_module
print(the_module.thing)
# . hello
Hành vi không mong muốn
Giải pháp này không phải là không có cảnh báo. Cụ thể, the_module.thing
là không phải là một chuỗi ! Nó là một proxy_tools.Proxy
đối tượng có các phương thức đặc biệt đã được ghi đè để nó bắt chước một chuỗi. Dưới đây là một số bài kiểm tra cơ bản minh họa quan điểm:
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']
Trong nội bộ, chức năng gốc được lưu trữ để the_module.thing._Proxy__local
:
print(res._Proxy__local)
# <function thing at 0x7f729c3bf680>
Suy nghĩ thêm
Thành thật mà nói, tôi bối rối về lý do tại sao các mô-đun không được tích hợp sẵn chức năng này. Tôi nghĩ mấu chốt của vấn đề là đó the_module
là một phiên bản của types.ModuleType
lớp. Đặt một "thuộc tính mô-đun" tương đương với việc đặt một thuộc tính trên một thể hiện của lớp này, chứ không phải trên types.ModuleType
chính lớp đó. Để biết thêm chi tiết, hãy xem câu trả lời này .
Chúng tôi thực sự có thể triển khai các thuộc tính trên types.ModuleType
như sau, mặc dù kết quả không lớn. Chúng tôi không thể sửa đổi trực tiếp các loại tích hợp sẵn, nhưng chúng tôi có thể nguyền rủa chúng:
# 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__}'))
Điều này cung cấp cho chúng tôi một thuộc tính tồn tại trên tất cả các mô-đun. Nó hơi khó sử dụng, vì chúng tôi phá vỡ hành vi cài đặt trên tất cả các mô-đun:
import sys
print(sys.thing2)
# hi from sys
sys.thing2 = 5
# AttributeError: can't set attribute
__getattr__
trên một mô-đun để biết giải pháp hiện đại hơn.