如何在 python 中创建一个代理对象作为底层对象

Dav*_*aub 6 python design-patterns python-typing

我有一个带有底层对象的代理类。我希望将代理对象传递给需要底层对象类型的函数。如何使代理类型与底层对象匹配?

class Proxy:
    def __init__(self, obj):
        self.obj = obj

    def __getattribute__(self, name):
        return getattr(self.obj, name)

    def __setattr__(self, name, value):
        setattr(self.obj, name, value)

def foo(bar: MyClass):
    ...

foo(Proxy(MyClass())) # Warning: expected 'MyClass', got 'Proxy' instead
Run Code Online (Sandbox Code Playgroud)

Glo*_*eye 4

感谢@SUTerliakov 在问题评论中实际提供了这个答案的本质。该代码应类似于以下内容:

from typing import TYPE_CHECKING
from my_module import MyClass

if TYPE_CHECKING:
    base = MyClass
else:
    base = object


class Proxy(base):
    def __init__(self, obj):
        self.obj = obj

    def __getattribute__(self, name):
        return getattr(self.obj, name)

    def __setattr__(self, name, value):
        setattr(self.obj, name, value)


def foo(bar: MyClass):
    ...

foo(Proxy(MyClass())) # Works!
Run Code Online (Sandbox Code Playgroud)

请注意,您的课程可能并不总是可用 - 但这不是真正的问题。这个技巧与 TypeVars 配合得非常好。

# proxy.py
from typing import TYPE_CHECKING, TypeVar


Proxied = TypeVar('Proxied')
if TYPE_CHECKING:
    base = Proxied
else:
    base = object


class Proxy(base):
    def __init__(self, obj: Proxied):
        self.obj = obj

    def __getattribute__(self, name):
        return getattr(self.obj, name)

    def __setattr__(self, name, value):
        setattr(self.obj, name, value)
Run Code Online (Sandbox Code Playgroud)

在使用它的文件中:

from proxy import Proxy


def foo(bar: MyClass):
    ...

foo(Proxy(MyClass())) # Works!
Run Code Online (Sandbox Code Playgroud)