cách đúng đắn để coi Python argparse.Namespace () là một từ điển?


228

Nếu tôi muốn sử dụng các kết quả của argparse.ArgumentParser(), đó là một Namespaceđối tượng, với một phương thức mong đợi một từ điển hoặc đối tượng giống như ánh xạ (xem bộ sưu tập . Đánh dấu), cách đúng đắn để làm điều đó là gì?

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']

Có đúng không khi "tiếp cận" một đối tượng và sử dụng __dict__tài sản của nó ?

Tôi nghĩ rằng câu trả lời là không có: __dict__có mùi giống như một quy ước để thực hiện, nhưng không phải cho một giao diện, cách __getattribute__hay __setattr__hoặc __contains__có vẻ được.

Câu trả lời:


385

Bạn có thể truy cập từ điển của không gian tên bằng vars () :

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

Bạn có thể sửa đổi từ điển trực tiếp nếu bạn muốn:

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

Có, bạn có thể truy cập thuộc tính __dict__. Đó là một hành vi được xác định rõ, thử nghiệm và được đảm bảo.


1
Các tài liệu nói: "Không nên sửa đổi từ điển trả về: các hiệu ứng trên bảng ký hiệu tương ứng không được xác định." Mà chỉ có thể đề cập đến hành vi của vars()(đó là locals()hoặc globals()), nhưng tôi không thực sự chắc chắn.

2
hmm, tôi đoán tôi không thực sự hiểu sự khác biệt giữa việc sử dụng vars()__dict__
Jason S

21
@delnan Ai đó đã thực hiện một chỉnh sửa không chính xác cho các tài liệu và đưa ra một lời khuyên quá rộng. Các tài liệu sau đó đã được sửa chữa. Xem docs.python.org/2.7/l Library / fiances.html # volt Trong khi có một số trường hợp đặc biệt có từ điển chỉ đọc (như địa phương và proxy từ điển lớp), phần còn lại của các trường hợp có thể cập nhật được. Cuộc gọi vars (obj) đồng nghĩa với obj .__ dict__. Trong trường hợp không gian tên argparse , vars (args) cho phép truy cập trực tiếp vào một từ điển có thể cập nhật.
Raymond Hettinger

1
@RaymondHettinger Được rồi, gọn gàng. Tôi đã nhận được ghi chú đó từ /3/phiên bản của các tài liệu (khi kiểm tra kỹ hơn, bao gồm 3,1 đến 3,4), vì vậy sự điều chỉnh rõ ràng là thiếu ở đó.

8
@delnan Tôi vừa cập nhật tài liệu 3.3 và 3.3. Nó sẽ được nhìn thấy vào ngày mai. Cảm ơn đã chỉ ra điều đó.
Raymond Hettinger

64

Thẳng từ miệng ngựa :

Nếu bạn muốn có chế độ xem giống như chính tả của các thuộc tính, bạn có thể sử dụng thành ngữ Python tiêu chuẩn , vars():

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

- Thư viện chuẩn Python, 16.4.4.6. Đối tượng không gian tên


1
Vẫn 'foo' nhớ '-'. Có ý kiến ​​gì không?
dùng2678074

1
@ user2678074 đây là cố ý để phù hợp với cờ shell. Các dấu gạch ngang là bên ngoài thực hiện trăn.
Erich

vars(args)cho tôiTypeError: 'dict' object is not callable
user5359531

6
@ user5359531 bạn có thể ghi đè toàn cầu varsbằng một biến. Bạn có thể sử dụng __builtins__.varsđể truy cập trực tiếp hoặc del varsdừng tạo bóng.
Nick T

@NickT Hiệu chỉnh nhỏ: Các hàm Python nằm trong phạm vi tĩnh, vì vậy nếu bạn phủ bóng một biến toàn cục trong một hàm, số nhận dạng đó sẽ luôn tham chiếu đến biến cục bộ trong hàm đó, ngay cả trước khi nó được gán hoặc sau del. Ở phạm vi mô-đun del sẽ làm việc với các nội trang "không bóng".
tám

-1

Là nó thích hợp để "tầm thành" một đối tượng và sử dụng nó dict bất động sản?

Nói chung, tôi sẽ nói "không". Tuy nhiên, điều Namespaceđó khiến tôi cảm thấy quá sức, có thể là từ khi các lớp không thể kế thừa từ các kiểu dựng sẵn.

Mặt khác, Namespacetrình bày một cách tiếp cận theo hướng nhiệm vụ đối với argparse và tôi không thể nghĩ ra một tình huống sẽ đòi lấy __dict__, nhưng giới hạn của trí tưởng tượng của tôi không giống với bạn.


11
Hoàn toàn ổn khi truy cập thuộc tính __dict__. Hướng nội là nền tảng cho ngôn ngữ. Thuộc tính được công khai vì một lý do :-)
Raymond Hettinger

8
Nhưng mọi thứ trong Python là "công khai". Không có sự khác biệt (ngoại trừ quy ước gạch dưới hàng đầu) giữa các biến thực hiện được sử dụng trong một thể hiện và giao diện công khai mà nó thể hiện. Đặc biệt là trong một đối tượng giống như từ điển: dòng giữa các phương thức cá thể và các giá trị từ điển là các hàm, hơi mờ.
Jason S

Nếu bạn đang truyền các đối số như các tham số được đặt tên? do_something(**args.__dict__)
OrangeDog
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.