Oto kod

class MyTest: 
    def __init__(self):
         pass

    def __getattr__(self, attr):
        pass
t = MyTest()
print 'my test object: %r' %t

Więc wydrukuj wyzwala TypeError: 'NoneType' object is not callable, gdy chcę tylko sprawdzić, czy obiekt istnieje. Przyznane ten kod nie jest bardzo przydatny. Ale miałem taką jak klasa stub w dużej bazie kodu, więc zrobiłem

if module and module.class and module.class.propery:
   # do something with that property
 ...

I dostałem Type Error: 'NoneType' object is not callable, ale linia nic nie nazywa! Domyślam się, że python nazywa niektóre funkcje domyślnie za kulisami.

Ciekawie tak się nie stało, jeśli klasa dziedziczy z Object

Co się dzieje?

2
anverx 1 marzec 2019, 19:57

2 odpowiedzi

Najlepsza odpowiedź

W starym stylu klasie __getattr__ jest używany do większego odmiany atrybutu dostępu, w tym magicznych metod. Operator % próbuje zadzwonić t.__repr__(), aby wypełnić symbol zastępczy %r, ale t.__repr__ jest oceniany przez t.__getattr__('__repr__'), który zwraca {{x6} }.

W przypadku if przywołuje się inna magiczna metoda, ale pojawia się ten sam problem.

>>> class Foo:
...   def __getattr__(self, attr):
...     print(attr)
...
>>> f = Foo():
>>> if f:
...   pass
__nonzero__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'NoneType' object is not callable

Użyj klas nowej stylu, __getattr__ jest wywoływany tylko wtedy, gdy atrybut nie można znaleźć za pomocą normalnej metody (sprawdzenie atrybutu __dict__} lub dowolnej klasy w instancji Mro).

>>> class Foo(object):
...     def __init__(self):
...         self.x = 3
...     def __getattr__(self, attr):
...         print(attr)
...
>>> f = Foo()
>>> if f:
...   pass
...
>>> f.x
3
>>> f.y
y

W przypadku if f sama f nie implementuje __nonzero__ lub __len__ i ani jej rodzic object, ale w takim przypadku nie ma atrybutu. używany; Fakt, że f jest w rzeczywistości używany obiekt. W f.x x znajduje się w dyktatorze atrybutu instancji, więc jego wartość jest zwracana bezpośrednio. Tylko y, który nie jest inaczej zdefiniowany przez f, {{x10}}, {{x11}}, lub {{x11}}, wywołuje połączenie do {{x12}}.

3
chepner 1 marzec 2019, 17:44

W Pythonie 2, z lekcjami w starym stylu, gdy próbujesz zadzwonić __repr__ (podczas drukowania) na obiekcie, masz __getattr__.

Ponieważ gwałtownie stubiesz tę metodę, zwraca None i Python próbuje zadzwonić None (ponieważ oczekuje się, że metoda zostanie zwrócona)

Spróbuj zadzwonić object.__getattr__, to działa:

class MyTest:
    def __init__(self):
         pass

    def __getattr__(self, attr):
        print(attr)   # so we see why getattr is called
        return object.__getattr__(self,attr)  # so it doesn't crash (neither it is useful...)

t = MyTest()
print ('my test object: %r' %t)

Wydruki:

__repr__
my test object: <__main__.MyTest instance at 0x00000000031B3808>

Jest to specyficzny problem z obiektem Python 2 / Old-Style. Python 3 lub obiekty w nowym stylu nie zachowują się tak samo

2
Jean-François Fabre 1 marzec 2019, 17:04