Python的“Namespace”对象是什么?

11

我知道命名空间是什么。但是在运行时

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('bar')
parser.parse_args(['XXX']) # outputs:  Namespace(bar='XXX')

Namespace(bar='XXX') 是什么类型的对象?我觉得这完全令人困惑。

阅读 argparse 文档,它说:“大多数 ArgumentParser 操作将某些值作为 parse_args() 返回的对象的属性添加”。那么在运行 globals() 时,这个对象不应该出现吗?或者我该如何对其进行内省?


据我所知,它是一个类似于字典的对象,其类被称为“命名空间”。它与全局或局部命名空间无关。 - ForceBru
这只是parse_args返回的东西。大多数情况下,您只需访问它设置的实例属性。除了一些细节之外,您基本上可以将其定义为class Namespace: pass - chepner
1
它不会出现在globals()中,因为您没有将parser.parse_args的返回值分配给全局变量。如果您编写args = parser.parse_args(['XXX']),那么globals()['args']就是Namespace对象。 - chepner
1
通常情况下,函数不会向任何作用域注入名称;只有赋值语句才会这样做。 - chepner
1
Namespace 类提供的其中一件事情是 __repr__ 函数,该函数生成漂亮的表示形式。您可以查看 源代码。 (请注意,__repr__ 是从 _AttributeHolder 继承的,它充当了 argparse 中定义的几个类的基类。) - chepner
显示剩余3条评论
3个回答

12

塞姆怀斯的回答非常好,但让我来回答问题的另一部分。

或者说如何自省它?

在任何语言中都能自省对象是一项有价值的技能,所以让我们将其视为完全未知类型来处理。

>>> obj = parser.parse_args(['XXX']) # outputs:  Namespace(bar='XXX')

你的第一反应很好。看看全局范围内是否有一个命名空间,但实际上并没有。
>>> Namespace
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'Namespace' is not defined

因此,让我们看一下实际的东西类型。"Namespace(bar='XXX')" 的打印语法来自某个地方的__str__或者__repr__方法,所以让我们看一下这个类型实际上是什么。
>>> type(obj)
<class 'argparse.Namespace'>

以及它的模块

>>> type(obj).__module__
'argparse'

现在我们可以放心地使用 from argparse import Namespace 来获取类型。此外,我们还可以执行:

>>> help(argparse.Namespace)

在交互式解释器中获取 Namespace 类的详细文档,而无需连接互联网。

1
哦,这真的很好,正是我所了解的水平:)。+1 - user7088941

5

这只是用于存储 parse_args 生成数据的容器。

https://docs.python.org/3/library/argparse.html#argparse.Namespace

此类故意保持简单,只是一个带有可读字符串表示形式的对象子类。

只需运行parser.parse_args(...).bar以获取您的 bar 参数的值。这就是该对象的全部内容。根据文档,您也可以通过 vars() 将其转换为字典。

Namespace 符号不会出现在 globals() 运行时,因为您没有单独导入它。(如果您想访问它,可以将其视为 argparse.Namespace。) 不需要自己实例化 Namespace,因此完全不必接触它。 我已经多次使用过 argparse,在看到这个问题之前从未注意到它返回的对象类型的名称——对于 argparse 的实际应用来说这是完全不重要的。


太好了,回答得很好!我同意我不需要去碰它,只是有一些新的“行为”让我感到困扰,我不理解。实际上,我仍然对argparse.Namespace的含义感到困惑。如果我有一个对象,用点号我可以访问属性或方法。如果我有一个模块,用一个属性我可以访问该模块中的内容,这意味着Namespace是在那里定义的(我确实检查过了)。但现在我很困惑:如果它已经在那个模块中定义了,那么parse_args如何修改它呢? - user7088941
parse_args 创建并返回 Namespace 类的一个实例;它不会修改中央的 Namespace 对象。 - Samwise

3

Namespace基本上只是一个最基本的类,它的实例可以定义属性,并带有一些方便的功能:

  • 一个不错的 __repr__
  • 只能使用关键字参数来实例化,防止“匿名”属性。
  • 一个方便的方法来检查属性是否存在(foo in Namespace(bar=3)计算结果为False
  • 与其他Namespace实例相等,基于具有相同属性和属性值。(例如:Namespace(foo=3, bar=5) == Namespace(bar=5, foo=3)

parse_args返回Namespace的实例:

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('bar')
args = parser.parse_args(['XXX'])

assert args.bar == 'XXX'

谢谢,这也非常有见地 +1 :) - user7088941

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接