我可以将名称空间对象从可变对象转换为不可变对象吗? [英] Can I convert a namespace object from mutable to immutable?
问题描述
我从命令行参数接收一个名称空间对象. 而且我不想修改它. 我可以这样做还是您有一些想法?
I receive a namespace object from command line arguments. And I don't want to modify it. Can I do that or do you have some ideas?
# -*- coding: utf-8 -*-
import argparse
def parse_args():
parser = argparse.ArgumentParser(description='This script is ...')
parser.add_argument('--confdir', type=str, required=True)
parser.add_argument('--outdir', type=str, required=True)
return parser.parse_args()
if __name__ == '__main__':
mutable_namespace = parse_args()
# I want to prevent overwrite like that.
mutable_namespace.confdir = "xxx"
推荐答案
我最初提出了自定义命名空间类,但我喜欢将args
更好地复制到NamedTuple的想法.
I initially proposed the custom Namespace class, but I like this idea of copying args
to a NamedTuple better.
另一个选择是将值从args
复制到不可变的对象/类.一个命名的元组可能会做得很好.
Another option is to copy the values from args
to an immutable object/class. A named tuple might do the job nicely.
创建名称空间
In [1157]: dest=['x','y']
In [1158]: args=argparse.Namespace()
In [1159]: for name in dest:
......: setattr(args, name, 23)
......:
In [1160]: args
Out[1160]: Namespace(x=23, y=23)
现在定义一个namedtuple
now define a namedtuple
In [1161]: from collections import namedtuple
In [1163]: Foo = namedtuple('Foo',dest)
您还可以从命名空间本身获取元组名称(解析后)
You could also get the tuple names from the Namespace itself (after parsing)
Foo = namedtuple('Foo',vars(args).keys())
使用args
中的值创建这样的元组:
create such a tuple with values from args
:
In [1165]: foo=Foo(**vars(args))
In [1166]: foo
Out[1166]: Foo(x=23, y=23)
In [1167]: foo.x
Out[1167]: 23
它是不可变的:
In [1168]: foo.x=34
...
AttributeError: can't set attribute
这样的namedtuple不能用作命名空间,因为setattr(foo,'x',34)
会产生相同的错误.
Such a namedtuple cannot be used as a Namespace, since setattr(foo,'x',34)
produces the same error.
完成所有这些操作的一种干净方法是将其全部包装在一个函数中:
A clean way to do all of this is to wrap it all in a function:
def do_parse():
parser = ....
Foo = namedtuple(...)
args = parser.parse_args()
foo = Foo(**vars(args))
return foo
调用代码从不会看到可变的args
,而只有不变的foo
.
The calling code never sees the mutable args
, just the immutable foo
.
要基于Ingaz
答案,argparse
可以使用您自己的Namespace
类.
To build on Ingaz
answer, argparse
can use your own Namespace
class.
https://docs.python.org/3/library/argparse.html#the-namespace-object
class MyNamespace(argparse.Namespace):
pass
<customize one or more methods>
anamespace = MyNamespace()
args = parser.parse_args(namespace=anamespace)
现在args
和anamespace
引用相同的MyNamespace
对象.只要getattr(anamespace, adest)
和setattr(anamespace, adest, avalue)
起作用,argparse
都可以使用此命名空间对象.
Now args
and anamespace
reference the same MyNamespace
object. As long as getattr(anamespace, adest)
and setattr(anamespace, adest, avalue)
work, argparse
can use this namespace object.
现在,您可以允许setattr(anamespace, 'string', 'value')
,但不允许anamespace.string = value
吗?我认为可以,但是将需要对后一种表达的工作原理有一个很好的了解.它可能只需要自定义.__setattr__
,但是我已经有一段时间没有研究Python的这一方面了.
Now, can you allow setattr(anamespace, 'string', 'value')
, but disallow anamespace.string = value
? I think you can, but it will require a good understanding of how the latter expression works. It may just require customizing .__setattr__
, but I haven't studied this aspect of Python in a while.
通过设计,可以像这样的自定义类来猴子补丁" argparse
名称空间,甚至是可以接受的.
By design it is possible, and even acceptable to 'monkey patch' the argparse
namespace - with a custom class like this.
这篇关于我可以将名称空间对象从可变对象转换为不可变对象吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!