Creazione dell'oggetto metodo nel modello dati Python

4

Ho letto l'articolo sul modello di dati di Python sul suo sito web di riferimento , e sono stato confuso da questa parte:

When the attribute is a user-defined method object, a new method object is only created if the class from which it is being retrieved is the same as, or a derived class of, the class stored in the original method object; otherwise, the original method object is used as it is.

Essenzialmente, non posso davvero evocare due scenari in cui in uno il metodo è l'oggetto è lo stesso dell'oggetto del metodo originale e nell'altro viene creato un nuovo metodo. Ecco il più vicino possibile:

class TestClass:
    def TestFunc():
        pass

class TestClass2:
    x_attr = TestClass().TestFunc
    y_attr = TestClass.TestFunc
    def __init__(self):
        print "x's class is " + repr(TestClass2.x_attr.__class__)
        print "y's class is " + repr(TestClass2.y_attr.__class__)

if __name__ == '__main__':
    tc = TestClass()
    tc2 = TestClass2()

    print "tc.TestFunc: ".ljust(20) + str(id(tc.TestFunc))              # retrieved from TestClass
    print "TestClass.TestFunc: ".ljust(20) + str(id(TestClass.TestFunc))# retrieved from TestClass
    print "tc2.x_attr: ".ljust(20) + str(id(tc2.x_attr))                # retrieved from TestClass2
    print "tc2.y_attr: ".ljust(20) + str(id(tc2.y_attr))                # retrieved from TestClass2

Tuttavia, l'output dei diversi test case non è come mi aspetterei leggendo il passaggio dal Reference:

x's class is <type 'instancemethod'>
y's class is <type 'instancemethod'>
tc.TestFunc:        140591510137584
TestClass.TestFunc: 140591510137584
tc2.x_attr:         140591509970288
tc2.y_attr:         140591510137424

In particolare, mi aspettavo che TestClass.TestFunc e tc2.y_attr (cioè TestClass2.y_attr ) fossero gli stessi in base a quanto citato dal riferimento.

Inoltre, mi aspettavo di vedere lo stesso risultato per < tc.TestFunc , TestClass.TestFunc > coppia di confronto e il < tc2.x_attr , tc2.y_attr > coppia di confronto (vale a dire ogni coppia uguale o uguale).

Potresti per favore chiarire perché questo è e cosa sta cercando di dire esattamente il Reference?

Grazie!

P.S. Utilizzo di Python 2.7.6 su Ubuntu 14.04.

    
posta Sia 16.03.2015 - 06:55
fonte

2 risposte

0

Se ho capito bene, penso che tu stia considerando l'ereditarietà, i metodi di compostaggio da un'altra classe. A volte è necessario sovrascrivere il metodo esistente se il metodo sed non sta utilizzando l'ambito completo di alcune classi.

Tieni presente che a volte questo tipo di sovrascrittura, ereditarietà e compostaggio può essere diverso dalla versione alla versione di python.

Penso che l'esempio sarebbe il modo migliore per spiegarlo. quindi abbiamo le classi test e test2:

class test(object):
    def testF(self):pass

eredità: >

class test2(test):pass #> inherited testF() function from test
>>> test().testF() is test().testF()
True
>>> test2().testF() == test().testF()
True
>>> #but is test2 the same as test ? 
>>> test2() is test()
False
>>> id( test2() ) == id( test() )
True

Che è logico, se ci pensi. Poiché potrebbero avere lo stesso codice, ma hanno nomi diversi, quindi in globals() hanno identità diverse e hanno lo stesso ID anche in memoria poiché sono uguali, alias ereditarietà . Ma nel momento in cui inizi ad aggiungere altri metodi a test2 smetteranno di essere gli stessi, e test2 avrà il puntatore a tutti i metodi di test . In breve, ereditarietà viene utilizzato per specializzare alcune classi. Se hai un'auto di classe e una classe Yugo, la classe Yugo è solo una classe di auto specializzata.
Ora ecco che viene l'override, dal momento che le classi possono essere ereditate, è possibile sovrascrivere i metodi dalla classe padre e quei metodi diventano metodi definiti dall'utente. Se hai:

class car(object):
   maxGear = 5
   def getSpeed(self,gearValue):
       if self.maxGear < gearValue: raise WrongCarDudeError
       else: return gearValue*30 # km/h

E ora hai una Yugo che è un'auto molto lenta (costruita per le spese non per la velocità) 30 km all'ora è un grande cambiamento per la Yugo, cosa dovremmo fare ora? Fai un'altra classe di Yugo? Quindi abbiamo 2 classi in 2 indirizzi di memoria nel computer (perdita di spazio prezioso nel computer e tempo di esecuzione). Ma cosa possiamo fare, possiamo sovrascrivere il metodo getSpeed e non copiare l'intera classe.

class Yugo(car):
   def getSpeed(self,gearValue):
       if self.maxGear < gearValue: raise WrongCarDudeError
       else: return gearValue*20 # km/h

Quindi ora la classe di auto Yugo ha maxGear come l'altra classe di auto, ma il metodo getSpeed non è lo stesso.

Detto questo, il link che hai fornito è per sovrascrivere i metodi di sistema __add__,__doc__,__bool__ ecc. Quindi se la tua classe eredita da class int e cambi il metodo __add__ (il metodo +). Il metodo della tua classe non essere uguale al metodo __add__ nella classe int.

Se non hai ancora imparato l'ereditarietà e il compostaggio suggerirei qualche ricerca. Poiché hai compostato il test.testFunc() nell'attributo globale class test2 . Pensaci in questo modo, se l'attributo ha self e viene dichiarato all'interno di __init__ function è privato (è univoco per ogni nuova istanza di quella classe) se è dichiarato all'interno della classe ma fuori dai metodi è globale, quindi è < strong> si accumulerà o sarà sovrascritto o utilizzerà solo memoria mentre crei nuove istanze.
Quindi non dichiararlo all'interno della classe e al di fuori dei metodi a meno che tu non ne abbia davvero bisogno. La dichiarazione degli attributi globali viene spesso utilizzata quando si memorizzano gli ID di istanze specifiche come il numero di telaio dell'auto (o il codice a barre di una barra di cioccolato). Quindi avresti yugoCar = Yugo(chassisNumber) e chevyCar = car(chassisNumber) e car.chassisNumbers elencherebbe tutti i numeri di telaio di tutte le tue istanze di Yugo e Car.

Spero che questo sia stato di aiuto.

    
risposta data 30.12.2016 - 18:47
fonte
0

Specifically, I was expecting TestClass.TestFunc and tc2.y_attr (i.e. TestClass2.y_attr) to be the same based on what is cited from the Reference.

Hai due aspetti diversi dell'espressione: "TestClass.TestFunc" uno nel tuo __main__ e uno nel tuo class . Ciascuna di queste espressioni valuta una diversa istanza dell'oggetto metodo, quindi non sono uguali. Tuttavia, troverai che TestClass2.y_attr è lo stesso oggetto di tc2.y_attr, come specificato dal riferimento.

Furthermore, I was expecting to see the same outcome for the comparison pair and the comparison pair (i.e. each pair the same or neither the same).

La prima coppia appare solo la stessa. In realtà, la prima linea di stampa costruisce e quindi getta via un oggetto metodo. La seconda linea di stampa crea un nuovo oggetto metodo usando la stessa identica memoria, e quindi ottiene lo stesso id. Ma in realtà non sono lo stesso oggetto.

    
risposta data 27.09.2017 - 02:09
fonte

Leggi altre domande sui tag