Come fai a sapere quando si guarda all'elenco di attributi e metodi elencati in un dir che sono attributi e quali sono metodi?

StackOverflow https://stackoverflow.com/questions/880160

Domanda

Sto lavorando a cercare di imparare a programmare a Python e mi sono concentrato sull'ottenimento di come utilizzare i moduli standard e altri moduli. La funzione Dir sembra davvero potente nell'interprete, ma mi chiedo se mi manca qualcosa a causa della mia mancanza di sfondo OOP. Usando il libro di S.Lotts ho deciso di utilizzare la sua classe DE per saperne di più sulla sintassi e sull'uso di classi e istanze.

Ecco il codice originale:

class Die(object):
''' simulate a six-sided die '''
def roll(self):
    self.value=random.randrange(1,7)
    return self.value
def getValue(self):
    return self.value

Lo stavo guardando e dopo aver creato alcune istanze mi chiedevo se il valore della parola fosse in qualche modo una parola chiave e cosa facesse l'uso della parola oggetto nell'istruzione di classe e così ho deciso di scoprire cambiando la definizione della classe su quanto segue:

class Die():
''' simulate a six-sided die '''
def roll(self):
    self.ban=random.randrange(1,7)
    return self.ban
def getValue(self):
    return self.ban

Quel cambiamento mi ha mostrato che ho ottenuto lo stesso comportamento dalle mie istanze, ma i seguenti metodi/attributi mancavano dai casi in cui ho fatto dir:

'__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
 '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__',
_repr__', '__setattr__', '__str__', '__weakref__'

Ho anche capito che quando ho fatto un Dir su un'istanza avevo una parola chiave aggiuntiva-bandire Che finalmente ho capito era un attributo della mia istanza. Questo mi ha aiutato a capire che potrei usare D1.Ban per accedere al valore della mia istanza. L'unico motivo per cui ho potuto capire che questo era un attributo era digitato D1.Happy e ho ottenuto un Attributeerror L'ho capito D1.GetValue era un metodo allegato a morire perché è quello che mi ha detto l'interprete.

Quindi, quando sto cercando di usare un modulo complicato ma utile come BeautifulSoup, come posso sapere quali delle cose elencate sono attributi della mia istanza o metodi della mia istanza dopo la digitazione dir (istanza). Avrei bisogno di saperlo perché questo mi ha insegnato che con gli attributi sto chiamando il risultato di un metodo e con metodi invocando una funzione sulla mia istanza.

Questa domanda è probabilmente troppo prolissa, ma sicuramente mi ha aiutato a capire meglio la differenza tra attributi e metodi. In particolare, quando guardo il risultato di chiamare Dir su un'istanza della mia classe Die vedo questo

['__doc__', '__module__', 'ban', 'getValue', 'roll']

Quindi sembrerebbe utile saperlo guardando quell'elenco che sono attributi e che sono metodi senza dover ricorrere a prove ed errori o risultati alla digitazione Hasattr (myinstance, sospetto attributename).

Dopo aver pubblicato la domanda che ho provato

for each in dir(d1):
    print hasattr(d1,each)

Il che mi dice a rigor di termini che tutti i metodi sono attributi. Ma non posso chiamare un metodo senza il () Quindi mi sembra che Hasattr () sia fuorviante.

È stato utile?

Soluzione

Invece di: "print hasattr(d1,each)", Tentativo: "print each, type(getattr(d1,each))". Dovresti trovare i risultati informativi.

Inoltre, al posto di dir() Tentativo help(), che penso che tu stia davvero cercando.

Altri suggerimenti

Prendi in considerazione l'utilizzo della libreria standard inspect Modulo-È spesso l'approccio più pratico all'introspezione, imballando sostanziali pezzi di funzionalità (potresti implementarlo da zero, ma riutilizzare un codice ben testato e ben progettato è una buona cosa). Vedere http://docs.python.org/library/inspect.html Per tutti i dettagli, ma per esempio inspect.getmembers(foo, inspect.ismethod) è un modo eccellente per ottenere tutti i metodi di foo (otterrai (name, value) coppie ordinate per nome).

Il che mi dice a rigor di termini che tutti i metodi sono attributi. Ma non posso chiamare un metodo senza (), quindi mi sembra che Hasattr () sia fuorviante.

Perché è fuorviante? Se obj.ban() è un metodo, quindi obj.ban è l'attributo corrispondente. Puoi avere un codice come questo:

print obj.getValue()

o

get = obj.getValue
print get()

Se vuoi ottenere un elenco di metodi su un oggetto, puoi provare questa funzione. Non è perfetto, dal momento che attiverà anche attributi richiamabili che non sono metodi, ma per il 99% dei casi dovrebbe essere abbastanza buono:

def methods(obj):
    attrs = (getattr(obj, n) for n in dir(obj))
    return [a for a in attrs if a.hasattr("__call__")]

Questo info Il modulo ispirato all'immersione in Python serve allo scopo.

def info(obj, spacing=20, collapse=1, variables=False):
    '''Print methods and their doc Strings

    Takes any object'''
    if variables:
    methodList = [method for method in dir(obj)]
    else:
    methodList = [method for method in dir(obj) if callable(getattr(obj,method))]

    #print methodList


    print '\n'.join(['%s %s' %
            (method.ljust(spacing),
             " ".join(str(getattr(obj,method).__doc__).split()))
            for method in methodList])


if __name__=='__main__':
    info(list)

C'è un metodo incorporato chiamato Callable. Puoi applicarlo a qualsiasi oggetto e restituirà vero/falso a seconda se può essere chiamato. per esempio

>>> def foo():
...   print "This is the only function now"
...
>>> localDictionary = dir()
>>> for item in localDictionary:
...   print repr(item) + "is callable: " + str(callable(locals()[item]))
'__builtins__'is callable: False
'__doc__'is callable: False
'__name__'is callable: False
'foo'is callable: True

Nota che la chiamata locali () restituirà un dizionario contenente tutto definito nell'ambito corrente. L'ho fatto perché gli elementi fuori dal dizionario sono solo stringhe e dobbiamo eseguire richiamabili sull'oggetto reale.

Idealmente, quando si utilizza una biblioteca complicata come Beautifulsoup, è necessario consultare la sua documentazione per vedere quali metodi fornisce ogni classe. Tuttavia, nel raro caso in cui non si dispone di una documentazione facilmente accessibile, è possibile verificare la presenza di metodi utilizzando quanto segue.

Tutti i metodi, che stessi sono oggetti, implementano il __call__ metodo e può essere controllato utilizzando il metodo Callable () che restituisce True, se il valore controllato ha il __call__ metodo.

Il seguente codice dovrebbe funzionare.

x = Die()
x.roll()

for attribute in dir(x) :
    print attribute, callable(getattr(x, attribute))

Il codice di cui sopra ritornerebbe vero per tutti i metodi e False per tutti gli attributi non richiamabili (come i membri dei dati come Ban). Tuttavia, questo metodo ritorna anche True per qualsiasi oggetto richiamabile (come le classi interne). Puoi anche verificare se il tipo di attributo è instancemethod

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top