[英]Injecting a callable object into a class as a method
可以像這樣將 function 注入 class 中:
class MainClass:
...
def simple_injected_func(self: MainClass, arg: str) -> None:
print(f"simple_injected_func({arg})")
MainClass.simple_injected_func = simple_injected_func
main_object = MainClass()
main_object.simple_injected_func("arg")
# outputs: simple_injected_func(arg)
此外,可以像這樣調用 object
class SimpleCallableClass:
def __call__(self, arg: str) -> None:
print(f"SimpleCallableClass()({arg})")
simple_callable_object = SimpleCallableClass()
simple_callable_object("arg")
# outputs: SimpleCallableClass()(arg)
我現在想將這兩件事結合起來,將一個可調用的類/對象作為 function 注入另一個 class,同時保持對 object 變量和CallableClass
的MainClass
方法的訪問。 (在內部我想用它來有效地實現方法 inheritance 並將這些方法從另一個文件注入到 class 中)
from inspect import signature
class CallableClass:
def __call__(self_, self: MainClass, arg: str) -> None:
print(f"CallableClass()({arg})")
callable_object = CallableClass()
MainClass.callable_object = callable_object
main_object = MainClass()
print(signature(simple_injected_func))
# outputs: (self: __main__.MainClass, arg: str) -> None
print(signature(callable_object))
# outputs: (self: __main__.MainClass, arg: str) -> None
print(signature(main_object.simple_injected_func))
# outputs: (arg: str) -> None
print(signature(main_object.callable_object))
# outputs: (self: __main__.MainClass, arg: str) -> None
main_object.simple_injected_func("my arg")
# outputs: simple_injected_func(my arg)
main_object.callable_object("my arg")
# Traceback (most recent call last):
# main_object.callable_object("my arg")
# TypeError: CallableClass.__call__() missing 1 required positional argument: 'arg'
在可調用的 object 的情況下,為什么第二個self
沒有被正確剝離? 有沒有辦法做到這一點?
當實例的方法被訪問時,Python 執行“綁定”,即創建綁定方法。 看這里:
>>> class Class:
... def method(self, x):
... return x
...
>>>
>>> instance = Class()
>>> Class.method
<function Class.method at 0x7fa688037158>
>>> instance.method
<bound method Class.method of <__main__.Class object at 0x7fa688036278>>
綁定已完成,因為方法是作為描述符實現的。
如果您想擁有這種行為,您還可以將您的可調用對象實現為描述符。
簡而言之,您必須使用至少一個__get__
方法來實現 class。 當評估Class.method
或instance.method
時,將調用該__get__
方法。 它應該返回可調用對象(根據是否存在實例,它應該是不同的)。
順便說一句,要將方法實際綁定到實例,使用functors.partial
是最簡單的:
bound_method = functors.partial(method, instance)
全部總結:
class Callable:
def __call__(self, instance, arg):
print(f"Callable()(arg)")
class Descriptor:
def __init__(self, callable):
self._callable = callable
def __get__(self, instance, owner):
if instance is None:
return self._callable
else:
return functools.partial(self._callable, instance)
class Class:
pass
Class.method = Descriptor(Callable())
接着:
>>> signature(Class.method)
<Signature (instance, arg)>
>>> signature(Class().method)
<Signature (arg)>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.