在下面的示例中,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中有function objectsmethod objects.定义类时,def语句会创建一个function object,它位于类的命名空间中:

>>> 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__和no __dict__插槽的用户定义类,当try 设置不存在的插槽时,会引发AttributeError(有关更多信息,请参阅docs on __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'

Python-3.x相关问答推荐

如何获得大Pandas 的常见时间间隔

为什么我的Selenium脚本在密码元素上失败?

如何将多个字典合并到一个列中,并为不同的行使用相同的键

我不能使用拆分来分隔数据

Django在POST到外部URL时如何进行CSRF保护? 更新

从列表的元素和python中的多个多索引数据帧执行方程

使用 GEKKO 使用代码解决最佳时间控制问题时出现 IndexError

Jupyter Notebook 拒绝打印一些字符串

Python ** 用于负数

判断 gekko 中的表达式

避免重复连续字符但不包括一个特定字符的正则表达式

使用正确的数据类型时,使用 Cerberus 验证 JSON 架构会引发错误

错误:预期语句,发现 py:Dedent

理解 Keras 的 ImageDataGenerator 类中的 `width_shift_range` 和 `height_shift_range` 参数

Python中的依赖倒置

TypeError:列表索引必须是整数或切片,而不是列表

使用 python2 和 python3 创建一个 virtualenv

如何正确创建自定义文本编解码器?

Python:如何在 Windows 资源管理器中打开文件夹(Python 3.6.2、Windows 10)

TypeError:无法将系列转换为