如何创建 Python 命名空间(argparse.parse_args 值)?

How do I create a Python namespace (argparse.parse_args value)?

为了交互式测试我的 python 脚本,我想创建一个 Namespace 对象,类似于 argparse.parse_args() 返回的对象。 显而易见的方法,

>>> import argparse
>>> parser = argparse.ArgumentParser()
>>> parser.parse_args()
Namespace()
>>> parser.parse_args("-a")
usage: [-h]
: error: unrecognized arguments: - a

Process Python exited abnormally with code 2

可能会导致 Python repl 因愚蠢的错误而退出(如上所述)。

那么,创建具有给定属性集的 Python 命名空间的最简单方法是什么?

例如,我可以即时创建 dict (dict([("a",1),("b","c")])),但我不能将其用作 Namespace:

AttributeError: 'dict' object has no attribute 'a'

您可以创建一个简单的 class:

class Namespace:
    def __init__(self, **kwargs):
        self.__dict__.update(kwargs)

在属性方面,它的工作方式与 argparse Namespace class 完全相同:

>>> args = Namespace(a=1, b='c')
>>> args.a
1
>>> args.b
'c'

或者,只需 导入 class;它可以从 argparse 模块获得:

from argparse import Namespace

args = Namespace(a=1, b='c')

从 Python 3.3 开始,还有 types.SimpleNamespace,它基本上做同样的事情:

>>> from types import SimpleNamespace
>>> args = SimpleNamespace(a=1, b='c')
>>> args.a
1
>>> args.b
'c'

这两种类型是不同的; SimpleNamespace 主要用于 sys.implementation 属性和 time.get_clock_info() 的 return 值。

进一步比较:

  • 两个classes都支持相等性测试;对于相同 class 的两个实例,如果它们具有具有相同值的相同属性,则 instance_a == instance_b 为真。
  • 两个 classes 都有一个有用的 __repr__ 来显示它们具有的属性。
  • Namespace() 个对象支持包含测试; 'attrname' in instance 如果命名空间实例具有属性 namend attrname,则为真。 SimpleNamespace 没有。
  • Namespace() 对象有一个未记录的 ._get_kwargs() 方法,该方法 return 是该实例的 (name, value) 属性的排序列表。您可以使用 sorted(vars(instance).items()).
  • 获得相同的 class
  • 虽然 SimpleNamespace() 在 C 中实现,Namespace() 在 Python 中实现,但属性访问速度并不快,因为两者使用相同的 __dict__ 存储属性。 SimpleNamespace() 个实例的相等性测试和生成表示的速度稍快一些。

argparse documentation 显示您正在尝试执行的操作的各种示例:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument("-a")
parser.parse_args(['-a 12'])
>>> Namespace(a=' 12')

现在建议使用类型模块中的 SimpleNamespace。它与接受的答案做同样的事情,除了它会更快并且有更多的内置函数,例如 equals 和 repr。

from types import SimpleNamespace

sn = SimpleNamespace()
sn.a = 'test'
sn.a

# output
'test'

先创建一个dict,然后使用dict创建一个命名空间:

from argparse import Namespace
x = {'a': 1, 'b': 2}
ns = Namespace(**x)
print(ns.a) #output 1