Tôi có một lớp học cần thực hiện một số phép thuật với mọi toán tử, như __add__
, __sub__
v.v.Tra cứu toán tử đánh chặn trên metaclass
Thay vì tạo mỗi hàm trong lớp, tôi có một metaclass xác định mọi toán tử trong môđun toán tử.
import operator
class MetaFuncBuilder(type):
def __init__(self, *args, **kw):
super().__init__(*args, **kw)
attr = '__{0}{1}__'
for op in (x for x in dir(operator) if not x.startswith('__')):
oper = getattr(operator, op)
# ... I have my magic replacement functions here
# `func` for `__operators__` and `__ioperators__`
# and `rfunc` for `__roperators__`
setattr(self, attr.format('', op), func)
setattr(self, attr.format('r', op), rfunc)
Phương pháp này hoạt động tốt, nhưng tôi nghĩ Sẽ tốt hơn nếu tôi chỉ tạo toán tử thay thế khi cần.
Lookup các nhà khai thác nên được trên metaclass vì x + 1
được thực hiện như type(x).__add__(x,1)
thay vì x.__add__(x,1)
, nhưng nó không nhận được đánh bắt bởi __getattr__
cũng không __getattribute__
phương pháp.
Điều đó không làm việc:
class Meta(type):
def __getattr__(self, name):
if name in ['__add__', '__sub__', '__mul__', ...]:
func = lambda:... #generate magic function
return func
Ngoài ra, kết quả là "chức năng" phải là một phương pháp liên kết với các trường hợp sử dụng.
Bất kỳ ý tưởng nào về cách tôi có thể đánh chặn tra cứu này? Tôi không biết liệu tôi có muốn làm gì không.
Đối với những câu hỏi tại sao tôi cần phải loại điều này, hãy kiểm tra mã đầy đủ here. Đó là công cụ để tạo các chức năng (chỉ để cho vui) có thể hoạt động thay thế cho lambda
s.
Ví dụ:
>>> f = FuncBuilder()
>>> g = f ** 2
>>> g(10)
100
>>> g
<var [('pow', 2)]>
Chỉ cần cho các hồ sơ, tôi không muốn biết một cách khác để làm điều tương tự (Tôi sẽ không tuyên bố tất cả các nhà khai thác duy nhất trên lớp ... đó sẽ là nhàm chán và cách tiếp cận tôi đã làm việc khá tốt :). Tôi muốn biết cách đánh chặn tra cứu thuộc tính từ toán tử.
"Tôi có một lớp học cần thực hiện một số phép thuật với mọi nhà điều hành" - Tại sao? Có vẻ như bạn đang sủa một cây rất phức tạp ... –
@LennartRegebro Tôi đang viết một trình tạo hàm bằng cách sử dụng toán tử trên một số đối tượng. 'f = FuncBuilder(); g = f ** 2 + 1; g (10) == 101'. Nó không phải là một cái gì đó rất hữu ích (rất nhiều các cuộc gọi chức năng), nhưng có phần thú vị để sử dụng: D – JBernardo
@LennartRegebro Tôi đã đăng toàn bộ mã. – JBernardo