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

为什么setattr在绑定方法上失败

俞博涛
2023-03-14
问题内容

在以下情况中,使用以下命令setattr在第一次调用中成功,但是在第二次调用中失败:

AttributeError: 'method' object has no attribute 'i'

为什么会这样,并且有一种方法可以在方法上设置属性,使其仅存在于一个实例上,而不是针对类的每个实例?

class c:

    def m(self):

        print(type(c.m))
        setattr(c.m, 'i', 0)

        print(type(self.m))
        setattr(self.m, 'i', 0)

Python 3.2.2


问题答案:

简短的答案:无法将自定义属性添加到绑定方法。

长答案如下。

在Python中,有 函数对象方法对象 。当定义一个类时,该def语句创建一个 函数对象 ,该 对象 位于该类的名称空间中:

>>> class c:
...     def m(self):
...         pass
...
>>> c.m
<function m at 0x025FAE88>

函数对象具有特殊的__dict__属性,可以保存用户定义的属性:

>>> c.m.i = 0
>>> c.m.__dict__
{'i': 0}

方法对象是不同的野兽。它们是微小的对象,仅持有对相应功能对象(__func__)的引用,并对其宿主对象(__self__)的引用:

>>> c().m
<bound method c.m of <__main__.c object at 0x025206D0>>
>>> c().m.__self__
<__main__.c object at 0x02625070>
>>> c().m.__func__
<function m at 0x025FAE88>
>>> c().m.__func__ is c.m
True

方法对象提供了一种特殊__getattr__的功能,可将属性访问转发给功能对象:

>>> c().m.i
0

对于该__dict__属性也是如此:

>>> c().m.__dict__['a'] = 42
>>> c.m.a
42
>>> c().m.__dict__ is c.m.__dict__
True

但是,设置属性遵循默认规则,并且由于它们没有自己的__dict__属性,因此无法设置任意属性。

这类似于定义__slots__且没有__dict__插槽的用户定义类,当尝试设置一个不存在的插槽时会引发一个AttributeError(请参阅文档,__slots__以获取更多信息):

>>> class c:
...     __slots__ = ('a', 'b')
...
>>> x = c()
>>> x.a = 1
>>> x.b = 2
>>> x.c = 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'c' object has no attribute 'c'


 类似资料:
  • 问题内容: 我有一个项目,我试图在回调中使用weakrefs,但我不明白我在做什么错。我创建了简化的测试,以显示我困惑的确切行为。 为什么在此测试中test_a可以正常工作,但是self.MyCallbackB的weakref在类初始化和调用test_b之间消失了?我以为只要实例(a)存在,对self.MyCallbackB的引用就应该存在,但是不存在。 问题答案: 您需要一个WeakMethod

  • 问题内容: 我之所以问这个问题,是因为对该答案的评论主题进行了讨论。我有90%的方法可以解决问题。 存在三种不同形式: 绑定方法 , 未绑定方法 和 函数 对象之间的区别是什么,所有这些都由f1描述?一个人怎么称呼这三个物体?它们如何相互转化?关于这些东西的文档很难理解。 问题答案: 一个 功能 是创建由声明,或通过。在Python 2下,当函数出现在语句主体中(或传递给类构造调用)时,它将转换为

  • setAttr(String, Object) 转调了 HttpServletRequest.setAttribute(String, Object),该方法可以将各种数据传递给View并在View中显示出来。 通过查看 jfinal 源码 Controller 可知 setAttr(String, Object) 方法在底层仅仅转调了底层的 HttpServletRequest 方法: priv

  • 请巨佬们给我看一个问题第一次写小程序,进入页面调了一个getUserInfo获取信息接口然后框里的数据全部正确显示出来了,但是我编辑完表单之后formData里还是没有变请问有啥问题吗

  • 问题内容: 当我实现接口方法时,Eclipse将添加@Override批注。Eclipse似乎对此没有任何问题。而且,来自Cruise Control的自动化构建过程似乎对此没有问题。但是,当我从命令行构建并运行Javac的ant时,出现以下错误: Eclipse在Java 1.6下运行。Cruise Control正在运行Java 1.5。无论我使用哪个Java版本,我的蚂蚁构建都会失败。 问题

  • 这应该很简单,但我在这里错过了一些东西。我有两个玩具类:(a)一个需要连接并提供文件的服务器;和 (b) 请求文件并将其打印在标准输出上的客户端。 服务器代码: 客户代码: 我试图在同一台机器上同时运行服务器和客户机,但是每次我试图运行客户机时,总是从服务器得到这条消息: !!!ERRO:地址已在使用中(绑定失败) 要运行这段代码而不出错,我还需要做什么不同于上面的事情吗? 谢谢。