Python 我可以将名称空间对象从可变转换为不可变吗?
我从命令行参数接收名称空间对象。 我不想修改它。 我可以这样做吗?或者你有什么想法Python 我可以将名称空间对象从可变转换为不可变吗?,python,python-3.x,argparse,Python,Python 3.x,Argparse,我从命令行参数接收名称空间对象。 我不想修改它。 我可以这样做吗?或者你有什么想法 # -*- 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_
# -*- 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"
您可以在可变名称空间中重新定义
\uuuuu setattr\uuuu
:
class NotMutableException(Exception):pass
class SomeObject(object):
def init(self):
self.x = 10
self.y = 20
some_obj = SomeObject()
some_obj.z = 30
def not_setattr(self, name, value):
raise NotMutableException
type(some_obj).__setattr__ = not_setattr
some_obj.a = 1000
您可以在可变名称空间中重新定义
\uuuuu setattr\uuuu
:
class NotMutableException(Exception):pass
class SomeObject(object):
def init(self):
self.x = 10
self.y = 20
some_obj = SomeObject()
some_obj.z = 30
def not_setattr(self, name, value):
raise NotMutableException
type(some_obj).__setattr__ = not_setattr
some_obj.a = 1000
我最初提出了自定义名称空间类,但我喜欢将
args
复制到更好的NamedTuple
命名双倍
另一个选项是将值从args
复制到不可变的对象/类。命名元组可以很好地完成这项工作
创建名称空间
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
In [1161]: from collections import namedtuple
In [1163]: Foo = namedtuple('Foo',dest)
您还可以从名称空间本身获取元组名称(解析后)
使用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)
会产生相同的错误
完成这一切的一种干净方法是将其全部封装在一个函数中:
def do_parse():
parser = ....
Foo = namedtuple(...)
args = parser.parse_args()
foo = Foo(**vars(args))
return foo
调用代码从不看到可变的args
,只看到不可变的foo
自定义命名空间类
要基于Ingaz
answer,argparse
可以使用您自己的命名空间
类
类MyNamespace(argparse.Namespace):
通过
anamespace=MyNamespace()
args=parser.parse_args(名称空间=anamespace)
现在args
和anamespace
引用相同的MyNamespace
对象。只要getattr(anamespace,adest)
和setattr(anamespace,adest,avalue)
起作用,argparse
就可以使用这个名称空间对象
现在,您可以允许setattr(anamespace,'string','value')
,但不允许anamespace.string=value
?我想你可以,但这需要你很好地理解后一种表达方式是如何工作的。它可能只需要定制。\uuuu setattr\uuuu
,但我已经有一段时间没有研究Python的这一方面了
通过设计,将
argparse
名称空间与这样一个自定义类“猴子补丁”是可能的,甚至是可以接受的。我最初提出了自定义名称空间类,但我更喜欢将args
复制到一个NamedTuple
命名双倍
另一个选项是将值从args
复制到不可变的对象/类。命名元组可以很好地完成这项工作
创建名称空间
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
In [1161]: from collections import namedtuple
In [1163]: Foo = namedtuple('Foo',dest)
您还可以从名称空间本身获取元组名称(解析后)
使用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)
会产生相同的错误
完成这一切的一种干净方法是将其全部封装在一个函数中:
def do_parse():
parser = ....
Foo = namedtuple(...)
args = parser.parse_args()
foo = Foo(**vars(args))
return foo
调用代码从不看到可变的args
,只看到不可变的foo
自定义命名空间类
要基于Ingaz
answer,argparse
可以使用您自己的命名空间
类
类MyNamespace(argparse.Namespace):
通过
anamespace=MyNamespace()
args=parser.parse_args(名称空间=anamespace)
现在args
和anamespace
引用相同的MyNamespace
对象。只要getattr(anamespace,adest)
和setattr(anamespace,adest,avalue)
起作用,argparse
就可以使用这个名称空间对象
现在,您可以允许setattr(anamespace,'string','value')
,但不允许anamespace.string=value
?我想你可以,但这需要你很好地理解后一种表达方式是如何工作的。它可能只需要定制。\uuuu setattr\uuuu
,但我已经有一段时间没有研究Python的这一方面了
通过设计,它是可能的,甚至可以接受“monkey patch”的
argparse
名称空间-使用这样的自定义类。在Python中锁定变量?只要。。。不要修改它?Python中没有什么比const更像const
。通常的哲学是,如果你不想做某件事,你就不去做。这就是为什么我们也没有私人的。谢谢你的告别。我明白了,我的想法在Python中是不合适的。我很明白。我要改道。非常感谢。相关:在Python中锁定变量?只是。。。不要修改它?Python中没有什么比const更像const
。通常的哲学是,如果你不想做某件事,你就不去做。这就是为什么我们也没有私人的。谢谢你的告别。我明白了,我的想法在Python中是不合适的。我很明白。我要改道。非常感谢。相关:如果您对argparse
的命名空间
执行此操作,那么您就破坏了argparse
,以获取将来可能使用它的代码中的任何其他内容。我想我会提醒你的。Monkeypatching核心类来禁用它们是一个很大的禁忌。@ShadowRanger:OP的想法从一开始就很奇怪。所以它也有同样奇怪的答案。这不是一个奇怪的想法。您可以定义自己的命名空间
类。只要允许解析器使用getattr
和setattr
获取和设置属性,它就应该可以工作。如果您对argparse
的命名空间
执行此操作,您只需断开argparse
中将来可能使用它的任何其他代码。我想我会提醒你的。Monkeypatching核心类来禁用它们是一个很大的禁忌。@ShadowRanger:OP的想法从一开始就很奇怪。所以它也有同样奇怪的答案。这不是一个奇怪的想法。您可以定义自己的命名空间
类。只要允许解析器使用getattr
和setattr
获取和设置属性,它就应该可以工作