Dlaczego Python zmienia wolną funkcję w niezwiązaną metodę po przypisaniu do zmiennej klasy?

def make_func(s):
    def func(x):
        return '%s-%d' % (s, x)
    return func

class Foo(object):
    foofunc = make_func('foo')

Więc to działa zgodnie z oczekiwaniami: (zwraca "Dog-1")

make_func('dog')(1)

Ale to się nie powiedzie:

Foo.foofunc(1)

TypeError: unbound method func() must be called with Foo instance as first argument (got int instance instead)

Po bliższej inspekcji Python zmienił "wewnętrzna" funkcja func wewnątrz make_func do metody, ale ponieważ nie ma self, ta metoda nigdy nie zadziała. Dlaczego Python to robi?

>>> import inspect
>>> inspect.getmembers(Foo, inspect.ismethod)
[('foofunc', <unbound method Foo.func>)]
3
dividebyzero 16 sierpień 2014, 01:18

2 odpowiedzi

Najlepsza odpowiedź

Python nie może powiedzieć "jak" przypisywałeś metodę atrybutu klasy. Nie ma różnicy między tym:

class Foo(object):
    def meth():
        pass

I to

def func():
    pass

class Foo(object):
    meth = func

W obu przypadkach wynik jest taki, że obiekt funkcji jest przypisany do atrybutu klasy o nazwie 'meth'. Python nie może powiedzieć, czy przypisałeś go, definiując funkcję w klasie lub "ręcznie" przypisując go za pomocą meth = func. Może zobaczyć tylko "wynik końcowy", który jest atrybutem, którego wartość jest funkcją. Tak czy inaczej, gdy funkcja jest w klasie, jest ona konwertowana na metodę za pomocą normalnego procesu, który powiadamia funkcje w definicjach klas i czyni je metodami.

3
BrenBarn 15 sierpień 2014, 21:27
class Foo(object):
    foofunc = make_func('foo')

Foofunc jest zmienną klasową, a nie metodą (dla której potrzebujesz "def"). I zainicjuj go z wynikiem make_func (...), więc nie zmieni się ponownie.

Jeśli chcesz zadzwonić foo.foofon, musisz przypisać foofunc = make_func bez parametru.

-2
jcoppens 15 sierpień 2014, 21:30