如何使用Python伪造类型

发布于 2021-01-29 17:40:49

我最近DocumentWrapper在Python中开发了一个围绕某些ORM文档对象命名的类,以透明地向其中添加一些功能,而不用任何方式更改其接口。

我对此只有一个问题。假设我User包裹了一些物体。呼叫isinstance(some_var, User)将返回,False因为some_var确实是的一个实例DocumentWrapper

有没有办法伪造Python中的对象类型以具有相同的调用返回True

关注者
0
被浏览
51
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    测试对象的 类型 通常是python中的反模式。在某些情况下,测试对象的 “鸭子类型” 是有意义的,例如:

    hasattr(some_var, "username")
    

    但是,即使这是不希望的,例如,即使包装器使用某种魔术__getattribute__来正确地代理属性,该表达式也可能返回false的原因也是有原因的。

    通常最好允许变量仅采用一种抽象类型,并且可能只采用一种None。应通过将可选输入的数据传递到不同变量中来实现基于不同输入的不同行为。您想做这样的事情:

    def dosomething(some_user=None, some_otherthing=None):
        if some_user is not None:
            #do the "User" type action
        elif some_otherthing is not None:
            #etc...
        else:
             raise ValueError("not enough arguments")
    

    当然,所有这些都假定您对执行类型检查的代码具有某种程度的控制。假设不是。为了使“
    isinstance()”返回true,该类必须出现在实例的基址中,或者该类必须具有__instancecheck__。由于您无法控制该类中的任何一个,因此您必须在实例上使用一些假名。做这样的事情:

    def wrap_user(instance):
        class wrapped_user(type(instance)):
            __metaclass__ = type
            def __init__(self):
                pass
            def __getattribute__(self, attr):
                self_dict = object.__getattribute__(type(self), '__dict__')
                if attr in self_dict:
                    return self_dict[attr]
                return getattr(instance, attr)
            def extra_feature(self, foo):
                return instance.username + foo # or whatever
        return wrapped_user()
    

    我们正在做的是在需要包装实例时动态创建一个新类,并实际上从包装对象的继承__class____metaclass__如果原始对象有一些我们实际上不希望遇到的额外行为(例如,查找具有特定类名的数据库表),那么我们也将覆写额外的麻烦。这种样式的一个很好的方便之处在于,我们不必在包装类上创建任何实例属性self.wrapped_object,因为它在
    类创建时 就存在,所以不需要。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看