当前位置: 首页 > 面试题库 >

在运行时覆盖__setattr__

汪玮
2023-03-14
问题内容

我试图覆盖__setattr__Python类的方法,因为我想每次实例属性更改其值时都调用另一个函数。但是,我不希望该__init__方法出现此行为,因为在此初始化期间,我设置了一些稍后将要使用的属性:

到目前为止,我有此解决方案,而不必__setattr__在运行时重写:

class Foo(object):
    def __init__(self, a, host):
        object.__setattr__(self, 'a', a)
        object.__setattr__(self, 'b', b)
        result = self.process(a)
        for key, value in result.items():
            object.__setattr__(self, key, value)

    def __setattr__(self, name, value):
        print(self.b) # Call to a function using self.b
        object.__setattr__(self, name, value)

但是,我想避免这些,object.__setattr__(...)__setattr____init__方法末尾进行覆盖:

class Foo(object):
    def __init__(self, a, b):
        self.a = a
        self.b = b
        result = self.process(a)
        for key, value in result.items():
            setattr(self, key, value)
        # override self.__setattr__ here

    def aux(self, name, value):
        print(self.b)
        object.__setattr__(self, name, value)

我尝试了self.__dict__['__setitem__'] = self.auxobject.__setitem__['__setitem__'] = self.aux,但是这些尝试都没有效果。我已经阅读了数据模型参考的这一部分,但是看起来自己的分配__setattr__有些棘手。

如何可能__setattr__在的末尾进行覆盖__init__,或者至少有一个pythonic解决方案,其中__setattr__仅在构造函数中以常规方式调用?


问题答案:

不幸的是,没有办法“在初始化之后重写” python特殊方法。作为该查询工作方式的副作用。问题的症结在于python实际上并没有查看实例。除了要上课
在开始查找特殊方法之前;因此无法获取对象的状态来影响查找哪个方法。

如果您不喜欢中的特殊行为__init__,则可以重构代码以放入特殊知识__setattr__。就像是:

class Foo(object):
    __initialized = False
    def __init__(self, a, b):
        try:
            self.a = a
            self.b = b
            # ...
        finally:
            self.__initialized = True

    def __setattr__(self, attr, value):
        if self.__initialzed:
            print(self.b)
        super(Foo, self).__setattr__(attr, value)

编辑:实际上,有一种方法可以更改查找的特殊方法,只要在初始化后 更改其类即可
。这种方法将使您深入了解元类的杂草,因此,在不做进一步解释的情况下,其外观如下:

class AssignableSetattr(type):
    def __new__(mcls, name, bases, attrs):
        def __setattr__(self, attr, value):
            object.__setattr__(self, attr, value)

        init_attrs = dict(attrs)
        init_attrs['__setattr__'] = __setattr__

        init_cls = super(AssignableSetattr, mcls).__new__(mcls, name, bases, init_attrs)

        real_cls = super(AssignableSetattr, mcls).__new__(mcls, name, (init_cls,), attrs)
        init_cls.__real_cls = real_cls

        return init_cls

    def __call__(cls, *args, **kwargs):
        self = super(AssignableSetattr, cls).__call__(*args, **kwargs)
        print "Created", self
        real_cls = cls.__real_cls
        self.__class__ = real_cls
        return self


class Foo(object):
    __metaclass__ = AssignableSetattr

    def __init__(self, a, b):
        self.a = a
        self.b = b
        for key, value in process(a).items():
            setattr(self, key, value)

    def __setattr__(self, attr, value):
        frob(self.b)
        super(Foo, self).__setattr__(attr, value)


def process(a):
    print "processing"
    return {'c': 3 * a}


def frob(x):
    print "frobbing", x


myfoo = Foo(1, 2)
myfoo.d = myfoo.c + 1


 类似资料:
  • 但是当我运行test时,两个浏览器实例都打开了(Chrome首先打开并开始执行,延迟后Firefox打开)。在这种情况下,驱动程序对象被Firefox驱动程序覆盖,chrome停止执行。测试继续在Firefox上执行并成功完成。 项目的结构是这样的: 创建了一个DriverBase.class来加载与浏览器对应的驱动程序,该浏览器具有my@beforeSuite. crteated页面的单个类。(

  • 使用JPA EntityManager和JPA查询对象,我如何覆盖在查询中惰性获取注释@OneToMany(fetch=FetchType.EAGER)的内容? 如果我有hibernate查询对象,我可以让它创建一个criteria对象,并使用它将fetch类型设置为lazy。但我必须使用JPA查询对象。这个问题有什么解决办法吗?

  • Net:“junitreport”似乎没有提供一种方法来设置它在执行转换时使用的临时文件夹,而且似乎也没有提供更新“java”的方法。io。报告任务的tmpdir。在这种情况下,请设置“user”。主页或java。io。调用ant时从命令行调用tmpdir不是一个可以使用的解决方案。 详细介绍:我在ant/mantis中使用junit任务,语法如下: 这似乎是一种非常标准的用法,添加了“echo”

  • 我正在探索在运行时为JavaWeb应用程序执行Cobertura代码覆盖,我遇到了一篇文章http://www.mojohaus.org/cobertura-maven-plugin/instrumentingDeploymentArtifact.html 我遵循这些步骤,在一个小型maven web应用程序上获得了覆盖率报告,我在JBoss服务器上部署了一个war文件(包含一个模块),并手动浏览

  • 我正在使用Jacoco插件计算Spring启动应用程序的代码覆盖率。build.gradle的Jacoco配置如下: } 和 } } 有人能帮我吗?