Domanda Differenza tra dir (...) e vars (...) .keys () in Python?


C'è una differenza tra dir(…) e vars(…).keys() in Python?

(Spero ci sia una differenza, perché altrimenti ciò spezzerebbe il principio del "one way to do it" ... :)


44
2018-06-11 09:46


origine


risposte:


Gli oggetti Python memorizzano le loro variabili di istanza in un dizionario che appartiene all'oggetto. vars(x) restituisce questo dizionario (come fa x.__dict__). dir(x), d'altra parte, restituisce un dizionario di x"s", gli attributi della sua classe e ricorsivamente gli attributi delle classi base della sua classe. "

Quando si accede all'attributo di un oggetto usando l'operatore punto, python fa molto di più che cercare l'attributo in quel dizionario oggetti. Un caso comune è quando x è un oggetto di classe C e tu chiami un metodo m su di essa.

class C(object):
    def m(self):
        print "m"

x = C()
x.m()

Il metodo m non è memorizzato in x.__dict__. È un attributo della classe C. Quando chiami x.m(), python inizierà cercando m in x.__dict__, ma non lo troverà. Tuttavia, lo sa x è un'istanza di C, quindi guarderà in seguito C.__dict__, trovalo lì e chiama m con x come il primo argomento.

Quindi la differenza tra vars(x) e dir(x) è questo dir(x) fa il lavoro extra di guardare dentro xLa classe (e le sue basi) per gli attributi accessibili da esso, non solo gli attributi in cui sono memorizzati xla propria tabella dei simboli. Nell'esempio sopra, vars(x) restituisce un dizionario vuoto, perché x non ha variabili di istanza. Però, dir(x) ritorna

['__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__',
'__hash__', '__init__', '__module__', '__new__', '__reduce__',
'__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', 'm']

72
2018-06-11 14:57



La documentazione ha da dire su questo dir:

Senza argomenti, restituire l'elenco di nomi nell'ambito locale corrente. Con un argomento, tenta di restituire un elenco di attributi validi per quell'oggetto.

E questo circa vars:

Senza argomenti, restituisce un dizionario corrispondente alla tabella dei simboli locali corrente. Con un modulo, classe o oggetto istanza di classe come argomento (o qualsiasi altra cosa che ha un __dict__ attributo), restituisce un dizionario corrispondente alla tabella dei simboli dell'oggetto.

Se non vedi la differenza, forse questo ti mostrerà di più:

>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delsli
ce__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getit
em__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__',
 '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__r
educe__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__'
, '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'a
ppend', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort'
]
>>> vars(list).keys()
['__getslice__', '__getattribute__', 'pop', 'remove', '__rmul__', '__lt__', '__s
izeof__', '__init__', 'count', 'index', '__delslice__', '__new__', '__contains__
', 'append', '__doc__', '__len__', '__mul__', 'sort', '__ne__', '__getitem__', '
insert', '__setitem__', '__add__', '__gt__', '__eq__', 'reverse', 'extend', '__d
elitem__', '__reversed__', '__imul__', '__setslice__', '__iter__', '__iadd__', '
__le__', '__repr__', '__hash__', '__ge__']

Se non hai voglia di leggerlo, dir include questi attributi while vars non:

>>> set(dir(list)).difference(vars(list).keys())
set(['__str__', '__reduce__', '__subclasshook__', '__setattr__', '__reduce_ex__'
, '__format__', '__class__', '__delattr__'])

24
2018-06-11 09:53



A parte le risposte fornite, vorrei aggiungere che, usando vars () con i tipi di istanze incorporate daranno un errore, poiché i tipi di istanza incorporati non hanno __dict__ attributo.

per esempio.

In [96]: vars([])
---------------------------------------------------------------------------

TypeError Traceback (most recent call last)
<ipython-input-96-a6cdd8d17b23> in <module>()
      ----> 1 vars([])
TypeError: vars() argument must have __dict__ attribute

3
2017-09-13 06:54