2013-06-01 17 views
116

Jeśli chcę użyć wyników obiektu argparse.ArgumentParser(), który jest obiektem Namespace, metodą, która oczekuje słownika lub obiektu podobnego do odwzorowania (patrz collections.Mapping), jaki jest właściwy sposób?jaki jest właściwy sposób traktowania Pythona argparse.Namespace() jako słownika?

C:\>python 
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 
32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import argparse 
>>> args = argparse.Namespace() 
>>> args.foo = 1 
>>> args.bar = [1,2,3] 
>>> args.baz = 'yippee' 
>>> args['baz'] 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'Namespace' object has no attribute '__getitem__' 
>>> dir(args) 
['__class__', '__contains__', '__delattr__', '__dict__', '__doc__', '__eq__', '_ 
_format__', '__getattribute__', '__hash__', '__init__', '__module__', '__ne__', 
'__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__ 
', '__str__', '__subclasshook__', '__weakref__', '_get_args', '_get_kwargs', 'ba 
r', 'baz', 'foo'] 

Czy to właściwa „dotrzeć do” obiektu i użyć jej __dict__ nieruchomość?

byłoby Myślę, że odpowiedź nie jest: __dict__ pachnie konwencji do realizacji, ale nie dla interfejsu, sposobu __getattribute__ lub __setattr__ lub __contains__ wydają się być.

Odpowiedz

172

Można uzyskać dostęp do słownika przestrzeni nazw jest z vars():

>>> import argparse 
>>> args = argparse.Namespace() 
>>> args.foo = 1 
>>> args.bar = [1,2,3] 
>>> d = vars(args) 
>>> d 
{'foo': 1, 'bar': [1, 2, 3]} 

Można modyfikować słownika bezpośrednio, jeśli chcesz:

>>> d['baz'] = 'store me' 
>>> args.baz 
'store me' 

Tak, to jest w porządku, aby uzyskać dostęp do atrybutu __dict__. Jest to dobrze zdefiniowane, przetestowane i gwarantowane zachowanie.

+0

Docs powiedzieć: „Zwracany słownik nie powinien być modyfikowany: wpływ na odpowiedniej tablicy symboli są nieokreślone.” Które * może * odnosi się tylko do zachowania 'vars()' (które jest albo 'locals()' albo 'globals()'), ale nie jestem do końca pewien. – delnan

+1

hmm, Chyba naprawdę nie rozumiem różnicy między używaniem 'vars()' i '__dict__' –

+12

@delnan Ktoś dokonał niepoprawnej edycji do dokumentów i zrobił zbyt szerokie upomnienie. Dokumenty zostały następnie skorygowane. Zobacz http://docs.python.org/2.7/library/functions.html#vars Podczas gdy istnieją pewne specjalne przypadki, które mają słowniki tylko do odczytu (takie jak locale i słownik słowników klasowych), pozostałe przypadki można aktualizować. Wywołanie * vars (obj) * jest równoznaczne z obj .__ dict__. W przypadku przestrzeni nazw * argparse * * vars (args) * daje bezpośredni dostęp do aktualizowalnego słownika. –

0

Is it proper to "reach into" an object and use its dict property?

Ogólnie rzecz biorąc, powiedziałbym "nie". Jednak Namespace zaatakował mnie jako zbyt zaawansowany, prawdopodobnie od kiedy klasy nie mogły dziedziczyć z wbudowanych typów.

Z drugiej strony, przedstawia zorientowane na zadania podejście do argparse i nie mogę wymyślić sytuacji, która wymagałaby złapania __dict__, ale granice mojej wyobraźni nie są takie same jak twoje.

+5

Uzyskanie dostępu do atrybutu \ _ \ _ dict \ _ \ _ jest całkowicie w porządku. Introspekcja ma fundamentalne znaczenie dla języka. Atrybut został upubliczniony z jakiegoś powodu :-) –

+4

Ale wszystko w Pythonie jest "publiczne". Nie ma rozróżnień (z wyjątkiem wiodącej konwencji podkreślenia) między zmiennymi implementacyjnymi używanymi w instancji i interfejsem publicznym, który prezentuje. Zwłaszcza w obiekcie podobnym do słownika: linia między metodami instancji i wartościami słownikowymi, które są funkcjami, jest nieco zamazana. –

25

Straight from the horse's mouth:

If you prefer to have dict-like view of the attributes, you can use the standard Python idiom, vars() :

>>> parser = argparse.ArgumentParser() 
>>> parser.add_argument('--foo') 
>>> args = parser.parse_args(['--foo', 'BAR']) 
>>> vars(args) 
{'foo': 'BAR'} 

— The Python Standard Library, 16.4.4.6. The Namespace object

+1

Wciąż "foo" pomija "-". Masz pomysł? – user2678074

+0

@ user2678074 jest to zamierzone dopasowanie flag powłoki. Kreski są nieistotne w trakcie wykonywania python. – Erich

+0

'vars (args)' daje mi 'TypeError: 'dict' obiektu nie można wywołać' – user5359531

Powiązane problemy