>> class A(object): ... def foo(self): ... """ This is o-6ren">
gpt4 book ai didi

python - 创建类后在方法上设置属性会引发 "' instancemethod' object has no attribute“但属性显然存在

转载 作者:太空宇宙 更新时间:2023-11-03 11:47:06 24 4
gpt4 key购买 nike

在 Python(2 和 3)中,我们可以将属性分配给函数:

>>> class A(object):
... def foo(self):
... """ This is obviously just an example """
... return "FOO{}!!".format(self.foo.bar)
... foo.bar = 123
...
>>> a = A()
>>> a.foo()
'FOO123!!'

这很酷。

但是为什么我们不能稍后更改 foo.bar 呢?例如,在构造函数中,像这样:

>>> class A(object):
... def __init__(self, *args, **kwargs):
... super(A, self).__init__(*args, **kwargs)
... print(self.foo.bar)
... self.foo.bar = 456 # KABOOM!
... def foo(self):
... """ This is obviously just an example """
... return "FOO{}!!".format(self.foo.bar)
... foo.bar = 123
...
>>> a = A()
123
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __init__
AttributeError: 'instancemethod' object has no attribute 'bar'

Python 声称没有 bar,即使它在前一行打印得很好。

如果我们尝试直接在类上更改它,则会发生同样的错误:

>>> A.foo.bar
123
>>> A.foo.bar = 345 # KABOOM!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'instancemethod' object has no attribute 'bar'

这里发生了什么,即为什么我们会看到这种行为?

有没有办法在创建类后设置函数的属性?

(我知道有多种选择,但我很想知道这里方法的属性,或者可能是更广泛的问题。)


动机:Django 利用了在方法上设置属性的可能性,例如:

class MyModelAdmin(ModelAdmin):
...

def custom_admin_column(self, obj):
return obj.something()
custom_admin_column.admin_order_field ='relation__field__span'
custom_admin_column.allow_tags = True

最佳答案

在类体内设置 foo.bar 是可行的,因为 foo 是实际的 foo 函数。但是,当您这样做时

self.foo.bar = 456

self.foo 不是那个函数。 self.foo 是一个实例方法对象,在您访问它时按需创建。由于多种原因,您无法为其设置属性:

  1. 如果这些属性存储在 foo 函数中,那么分配给 a.foo.bar 会对 b.foo.bar 产生意想不到的影响,这与对属性分配的所有常见预期相反。
  2. 如果这些属性存储在 self.foo 实例方法对象中,它们将不会在您下次访问 self.foo 时显示,因为下次您将获得一个新的实例方法对象。
  3. 如果这些属性存储在 self.foo 实例方法对象上,并且您更改规则,使 self.foo 始终是同一个对象,那么这会使 Python 中的每个对象大量膨胀以存储一堆您几乎不需要的实例方法对象。<
  4. 如果这些属性存储在 self.__dict__ 中,那么没有 __dict__ 的对象呢?此外,您需要想出某种名称修改规则,或将非字符串键存储在 self.__dict__ 中,这两者都有各自的问题。

如果你想在类定义完成后在 foo 函数上设置属性,你可以使用 A.__dict__['foo'].bar = 456 来实现。 (我已经使用 A.__dict__ 来绕过 A.foo 是函数还是未绑定(bind)方法对象的问题,这取决于您的 Python 版本。如果 A 继承了 foo ,您将不得不处理该问题或访问它继承 foo 的类。)

关于python - 创建类后在方法上设置属性会引发 "' instancemethod' object has no attribute“但属性显然存在,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36749310/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com