簡體   English   中英

將可調用的 object 作為方法注入 class

[英]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 變量和CallableClassMainClass方法的訪問。 (在內部我想用它來有效地實現方法 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.methodinstance.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM