Подтвердить что ты не робот

Добавление атрибутов к instancemethods в Python

Я столкнулся с этим поведением, пытаясь заставить класс-декораторов и декораторов-декораторов хорошо играть вместе. По сути, декодеры методов будут отмечать некоторые из методов как специальные с некоторым фиктивным значением, а декоратор класса будет появляться после и заполнить значение позже. Это упрощенный пример

>>> class cow:
>>>     def moo(self):
>>>         print 'mooo'
>>>     moo.thing = 10
>>>
>>> cow.moo.thing
10
>>> cow().moo.thing
10
>>> cow.moo.thing = 5
AttributeError: 'instancemethod' object has no attribute 'thing'
>>> cow().moo.thing = 5
AttributeError: 'instancemethod' object has no attribute 'thing'
>>> cow.moo.__func__.thing = 5
>>> cow.moo.thing 
5

Кто-нибудь знает, почему cow.moo.thing = 5 не работает, хотя cow.moo.thing довольно ясно дает мне 10? И почему работает cow.moo.__func__.thing = 5? Я понятия не имею, почему это происходит, но в случайном порядке перебирает вещи в списке dir(cow.moo), пытаясь заставить что-то работать, это внезапно, и я понятия не имею, почему.

4b9b3361

Ответ 1

Для поиска атрибутов Python автоматически использует реальную функцию, прикрепленную к вашему экземпляру.

Для настройки атрибута это не так.

Это две отдельные операции в зависимости от того, с какой стороны вы находитесь, хотя оба они используют оператор ..

Когда вы обращаетесь к методу экземпляра __func__, вы вручную обращаетесь к реальной функции, которая на самом деле имеет атрибут moo.

В Python 3 это будет работать так, как вам хотелось бы/ожидать, поскольку методы в основном являются просто функциями.

Ответ 2

Если вы хотите изменить атрибуты функций обеих функций и методы экземпляра из C, вам необходимо проверить тип вызываемого вами вызова.

Итак, если у вас есть PyObject какого-либо типа вызываемого, вы можете его проверить следующим образом:

PyObject *callable;  // set to something callable
PyObject *setting;  // set to something
if(PyMethod_Check(callable)){
    PyObject_SetAttrString(PyMethod_Function(callable),"attribute",setting);
}else{
    PyObject_SetAttrString(callable,"attribute",setting);
}
...
// and the inverse
if(PyMethod_Check(callable){         
     if(PyObject_HasAttrString(PyMethod_Function(callable),"attribute")){
        PyObject_DelAttrString(PyMethod_Function(callable),"attribute");
     }
  }else{
     if(PyObject_HasAttrString(callable,"attribute")){
        PyObject_DelAttrString(callable,"attribute");
     }
  }  

Теперь код agf указал, что работает из методов Python, например. Если я просто попытаюсь установить атрибут метода экземпляра, он не найдет атрибут независимо от того, как я пытался получить доступ к нему из Python.

Я столкнулся с этой проблемой, и вопрос Ли Хаойи с ответом agf помог мне понять, что нужно изменить. Я решил, что кто-то найдет этот вопрос и ответит снова, ища, как решить эту проблему с помощью C.

Edit: Примечание: это для Python 2.7.x. Python 3.x использует разные вызовы функций.