Miért nem hívódik meg a __getattr__ metódus (python3.6)?
Tegyük fel, hogy van egy osztály:
>>> class MyClass:
... var = 42
... def __getattrib__(self, name):
... print(name)
Ezt példányosítom:
>>> mc = MyClass()
És ebben az esetben:
>>> mc.whatever
whatever
Mivel whatever nevű attribútum első körben nem található, ezért meghívódik a __getattr__ metódus, ami simán csak kiírja az attribútum nevét.
Amit nem értek, hogy ez példányosítás nélkül nem működik, pedig a dir(MyClass) kilistázza a __getattrib__ függvényt, és ha így használom:
>>> MyClass.__getattrib__(MyClass, "whatever")
Akkor működik, viszont ha azt írom, hogy:
>>> MyClass.whatever
Akkor nem, AttributeError-t dob, mintha nem is lenne megírva a __getattr__ metódus.
Lehet valamit tenni, hogy ilyen módon is működjön?
Úgy mellesleg _ jellel kezdődő objektum referenciát "nem illik" közvetlen használni csak belső használat esetében. Persze a lehetőséget nem vették el, mondván hogy úgy használd, hogy tudod mit csinálsz.
Magyarázatok:
Nem kitérő válasz csak egy összefoglalás a teljesség igénye nélkül, hogy mi történik.
def __getattrib__(self, name) esetében a self az a hívás közben önmagára mutató referencia, kötelező paraméter bármelyik metódusnál kötelező. A változó neve igazából nem lenne kötelező hogy self legyen, ez csak konvenció.
Nem használtad semmire ezt a referenciát, csak az utána lévő name paramétert. Ezért igazából a MyClass.__getattr__(MyClass,"whatever") helyett lehetne
MyClass.__getattr__(0,"whatever") is.
Lekérdezhetjük hogy milyen típusú maga a __getattr__ példányosításkor meg a nélkül.
type(MyClass.__getattr__) function lesz, hoppá.
type(mc.__getattr__) pedig method lesz.
Ha példányosítás nélkül hívod akkor sima függvények lesznek melyek def valami(self ...) -ként szerepelnek a class-odba. Példányosításkor van az a feature a python-ba hogy akkor is dinamikusan képes visszaadni valamit ha nincs is olyan adattagja vagy metódusa.
Sőt maguk a metódusok is alapból is dinamikusan generált objektumok( az osztályhoz tartozó példányosítás nélküli függvény megfelelőjük alapján).
Például legyen egy Foo osztályunk:
>>>class Foo:
...def f(self,a):
......self.a = a
Példányosítjuk:
foo = Foo()
foo.a
AttributeError: 'Foo' object has no attribute 'a' kivételt dob, nem meglepő módon.
foo.f hívható így is, ekkor kapunk egy method objektumot.
Ezt akár ki is menthetjük változóba pl. x = foo.f.
Ezen az x változón keresztül is használhatjuk pl. x(10)
Ekkor foo.a -ra kifogja adni a 10-et, mintha foo.f(10)-et hívtuk volna meg. Össze is hasonlíthatjuk hogy foo.f == x True lesz. foo.f == foo.f is True. Azt jelenti hogy ugyanazt az értéket veszi fel, de ha azt nézzük meg hogy ugyanarra az objektumra mutat e foo.f is x False , sőt foo.f is foo.f False mert dinamikusan mindig új method objektum keletkezik, de ugyanakkor amit kimentettünk x-et x is x True lesz vagyis nem csak egyenlő hanem pontosan ugyanaz a method objektum lesz.
Itt is igaz lesz hogy type(foo.f) vagy type(x) method type(Foo.f) pedig function. Vagyis ha történik egy metódus hívás foo.f(10) akkor keletkezik egy új method típusú objektum a Foo osztály alapján mely meg lesz hívva a 10 paraméterrel mely csinál valamit.
Vagyis oszály példányosítással kapott objektum esetében annak minden egyes metódus hívássakkor dinamikusan keletkeznek maguk a metódusok, ha nem létező metódus vagy adattag név lesz akkor még van lehetőség ilyen callback __getattr__ hívásra mely még így is visszaadhat valamit.
Menjünk tovább, az osztályok is objektumok pythonba.
csináljunk egy sima függvényt
>>>def a(b):
...b.a = b.a + 1
Foo.g = a
Hívjuk meg foo.g()
Nézd meg, hogy mit ad vissza foo.a-ra és miért! Mi történt?
Nem vagyok benne biztos, hogy az utolsó példával mire akarsz rávezetni.
A leírtak alapján a(b) függvény nem változik, amíg Foo.g-ként hivatkozunk rá. foo.g()-ként viszont azért működik paraméter nélkül, mert itt már példányosítás után methodként viselkedik, és a foo.g() megfelel a g(foo) hívásnak. foo.a értéke nő eggyel.
Kapcsolódó kérdések:
Minden jog fenntartva © 2024, www.gyakorikerdesek.hu
GYIK | Szabályzat | Jogi nyilatkozat | Adatvédelem | Cookie beállítások | WebMinute Kft. | Facebook | Kapcsolat: info(kukac)gyakorikerdesek.hu
Ha kifogással szeretne élni valamely tartalommal kapcsolatban, kérjük jelezze e-mailes elérhetőségünkön!