Why does setattr fail on a bound method

后端 未结 2 1653
臣服心动
臣服心动 2020-12-03 03:48

In the following, setattr succeeds in the first invocation, but fails in the second, with:

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


        
2条回答
  •  执笔经年
    2020-12-03 04:15

    The short answer: There is no way of adding custom attributes to bound methods.

    The long answer follows.

    In Python, there are function objects and method objects. When you define a class, the def statement creates a function object that lives within the class' namespace:

    >>> class c:
    ...     def m(self):
    ...         pass
    ...
    >>> c.m
    
    

    Function objects have a special __dict__ attribute that can hold user-defined attributes:

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

    Method objects are different beasts. They are tiny objects just holding a reference to the corresponding function object (__func__) and one to its host object (__self__):

    >>> c().m
    >
    >>> c().m.__self__
    <__main__.c object at 0x02625070>
    >>> c().m.__func__
    
    >>> c().m.__func__ is c.m
    True
    

    Method objects provide a special __getattr__ that forwards attribute access to the function object:

    >>> c().m.i
    0
    

    This is also true for the __dict__ property:

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

    Setting attributes follows the default rules, though, and since they don't have their own __dict__, there is no way to set arbitrary attributes.

    This is similar to user-defined classes defining __slots__ and no __dict__ slot, when trying to set a non-existing slot raises an AttributeError (see the docs on __slots__ for more information):

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

提交回复
热议问题