2011-08-11 14 views
30

Wpadłem na to zachowanie, starając się, aby dekoratorzy klas i dekoratorzy metod ładnie ze sobą współpracowali. Zasadniczo, dekoratory metod oznaczałyby niektóre z metod jako specjalne z pewną wartością fikcyjną, a dekorator klasy przychodziłby po znaku i wprowadzał wartość później. Jest to uproszczony przykładDodawanie atrybutów do instancemethods w Pythonie

>>> 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 

Czy ktoś wie dlaczego cow.moo.thing = 5 nie działa, chociaż cow.moo.thing dość wyraźnie daje mi 10? I dlaczego działa cow.moo.__func__.thing = 5? Nie mam pojęcia, dlaczego tak jest, ale w przypadkowym manipulowaniu materiałem na liście dir(cow.moo) próbując dostać coś do roboty, zrobiło to nagle i nie mam pojęcia dlaczego.

Odpowiedz

33

Do wyszukiwania atrybutów, Python automatycznie używa rzeczywistej funkcji dołączonej do metody instancji.

Dla ustawienia atrybutu nie jest.

Są to dwie oddzielne operacje w zależności od tego, po której stronie wyciągu znajduje się użytkownik, mimo że oba używają operatora ..

Po uzyskaniu dostępu do metody metody __func__ uzyskujesz dostęp do rzeczywistej funkcji, która ma atrybut moo.

W Pythonie 3 będzie to działać tak, jak byś chciał/oczekiwał, ponieważ metody są po prostu funkcjami.

+0

Ah ok, nigdy nie wiedziałem. Dzięki! –

+0

Przepraszamy za ponowne wczytanie starego posta, ale w Python3 'cow(). Moo.thing = 5' zwraca" AttributeError: 'obiekt' method 'nie ma atrybutu "thing". Wiesz dlaczego ? –

+0

@JacquesGaudin W instancji ('krowa(). Moo') funkcja jest zawijana w obiekcie metody w dowolnej wersji Pythona - różnica jest na klasie (' cow.moo'), nie jest opakowana w Pythonie 3. Owijanie jest konieczne, aby 'self' został automatycznie przekazany do funkcji. – agf

3

Jeśli chcesz zmodyfikować atrybuty funkcji obu funkcji i metod instancji z C, musisz sprawdzić typ dostępnej opcji wywoływania.

Więc zakładając, że masz PyObject pewnego rodzaju wywoływalnym można sprawdzić to w ten sposób:

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"); 
    } 
    } 

Teraz AGF Kod wskazał prace od wewnątrz Python dla metody instancji. Jeśli po prostu spróbuję ustawić atrybut metody instancji, to nie znajdę atrybutu bez względu na to, jak próbowałem uzyskać do niego dostęp z Pythona.

Wpadłem na ten problem, a pytanie Li Haoyiego z odpowiedzią agfa pomogło mi zrozumieć, co należy zmienić. Pomyślałem ktoś znajdzie na to pytanie i odpowiedz ponownie patrząc na jak rozwiązać ten problem przez C.

Edit: Uwaga: To jest dla Pythona 2.7.x. Python 3.x używa różnych wywołań funkcji.

Powiązane problemy