创建一个简单的一次性Python对象的简单方法是什么?

创建一个简单的一次性Python对象的简单方法是什么?,python,Python,我想创建一个简单的一次性Python对象来保存一些命令行选项。我想这样做: options = ?????? options.VERBOSE = True options.IGNORE_WARNINGS = False # Then, elsewhere in the code... if options.VERBOSE: ... 当然,我可以使用字典,但是options.VERBOSE比options['VERBOSE']更可读,更容易键入 我想我应该能做到 options = o

我想创建一个简单的一次性Python对象来保存一些命令行选项。我想这样做:

options = ??????
options.VERBOSE = True
options.IGNORE_WARNINGS = False

# Then, elsewhere in the code...
if options.VERBOSE:
    ...
当然,我可以使用字典,但是
options.VERBOSE
options['VERBOSE']
更可读,更容易键入

我想我应该能做到

options = object()
,因为
object
是所有类对象的基本类型,因此应该类似于没有属性的类。但它不起作用,因为使用
object()
创建的对象没有
\uuu dict\uuu
成员,因此无法向其添加属性:

options.VERBOSE = True
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'object' object has no attribute 'VERBOSE'
options.VERBOSE=True
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
AttributeError:“object”对象没有属性“VERBOSE”
创建对象的最简单的“pythonic”方法是什么,最好不必创建额外的helper类就可以这样使用?

在2.6中增加了namedtuple函数:

import collections
opt=collections.namedtuple('options','VERBOSE IGNORE_WARNINGS')
myoptions=opt(True, False)

>>> myoptions
options(VERBOSE=True, IGNORE_WARNINGS=False)
>>> myoptions.VERBOSE
True
namedtuple是不可变的,因此您只能在创建它时分配字段值

在早期的Python版本中,可以创建空类:

class options(object):
    pass

myoptions=options()
myoptions.VERBOSE=True
myoptions.IGNORE_WARNINGS=False
>>> myoptions.IGNORE_WARNINGS,myoptions.VERBOSE
(False, True)
我使用:

根据你的观点,你可能认为这要么是一个大难题,要么是相当聪明。但不管您怎么想,它确实可以生成好看的代码,并且与dict兼容:

>>> ad = attrdict({'foo': 100, 'bar': 200})
>>> ad.foo
100
>>> ad.bar
200
>>> ad.baz = 'hello'
>>> ad.baz
'hello'
>>> ad
{'baz': 'hello', 'foo': 100, 'bar': 200}
>>> isinstance(ad, dict)
True
为了简化,可以使用以下方法:

class attrdict2(object):
    def __init__(self, *args, **kwargs):
        self.__dict__.update(*args, **kwargs)
哪个

  • 这可不是什么稀奇古怪的事

  • 不会用标准方法
    dict
    污染每个对象的名称空间;例如,
    ad.has\u key
    不是为类型为
    attrdict2
    的对象定义的

  • 顺便说一下,初始化
    attrdict
    attrdict2
    的实例更容易:

    >>> ad = attrdict2(foo = 100, bar = 200)
    
    当然,
    attrdict2
    dict
    不兼容

    如果不需要神奇的初始化行为,甚至可以使用

    class attrdict3(object):
        pass
    
    ad = attrdict3()
    ad.foo = 100
    ad.bar = 200
    
    但我仍然希望找到一种不需要辅助类的解决方案。

    可以使用

    class options(object):
        VERBOSE = True
        IGNORE_WARNINGS = False
    
    options.VERBOSE = False
    
    if options.VERBOSE:
        ...
    
    ,使用类对象本身(不是类的实例!)作为存储单个选项的位置。这是简洁的,满足了所有的需求,但它似乎是对类概念的滥用。如果用户实例化了
    选项
    类,也会导致混淆


    (如果需要保存对象的选项的多个实例,这将是一个非常好的解决方案——类定义提供默认值,可以在单个实例中重写。)

    执行此任务的绝对最简单的类是:

    class Struct:
        def __init__(self, **entries): 
            self.__dict__.update(entries)
    
    它以后可以用作:

    john = Struct(name='john doe', salary=34000)
    print john.salary
    

    namedtuple
    (另一个评论建议)是一个更高级的类,它为您提供了更多功能。如果您仍在使用Python 2.5,那么可以在

    上找到实现2.6的
    命名双工的基础。如果您坚持不必定义类,则可以滥用某些现有类。大多数对象属于“新型”类,这些类没有dict,但函数可以具有任意属性:

    >>> x = lambda: 0   # any function will do
    >>> x.foo = 'bar'
    >>> x.bar = 0
    >>> x.xyzzy = x
    >>> x.foo
    'bar'
    >>> x.bar
    0
    >>> x.xyzzy
    <function <lambda> at 0x6cf30>
    

    根据您的要求,我认为定制类是您的最佳选择:

    class options(object):
        VERBOSE = True
        IGNORE_WARNINGS = True
    
    if options.VERBOSE:
        # ...
    
    完整地说,另一种方法是使用单独的模块,即
    options.py
    封装您的选项默认值

    options.py

    VERBOSE = True
    IGNORE_WARNINGS = True
    
    import options
    
    if options.VERBOSE:
        # ...
    
    然后,在
    main.py
    中:

    VERBOSE = True
    IGNORE_WARNINGS = True
    
    import options
    
    if options.VERBOSE:
        # ...
    
    这具有从脚本中删除一些杂乱内容的功能。默认值很容易找到和更改,因为它们在自己的模块中被隔离。如果以后应用程序有所增长,则可以轻松地从其他模块访问选项


    这是我经常使用的一种模式,如果您不介意您的应用程序变得比单个模块更大,我将衷心推荐这种模式。或者,从一个自定义类开始,如果你的应用程序扩展到多个模块,那么以后再扩展到一个模块。

    只需创建一个名为Options.py的模块,然后导入它即可。将默认选项值作为全局变量放入其中。

    为什么不使用:


    随着最佳实践的发展,使用中的一个选项,您的生活会变得更好

    但是,要回答您的问题,您可以使用
    type
    功能创建一个一次性类:

    options = type('Options', (object,), { 'VERBOSE': True })()
    options.IGNORE_WARNINGS = False
    
    请注意,您可以提供初始字典,也可以将其保留为空

    Options = type('Options', (object,), {})
    options = Options()
    options.VERBOSE = True
    options.IGNORE_WARNINGS = False
    

    不是很pythonic。

    简单对象和命名元组是可行的方法

    我不知道
    命名元组
    类,所以感谢您的参考。但是我想要一个可变对象(例如,在命令行处理期间很有用)。此外,当用于此目的时,
    namedtuple
    实例的初始化实际上并不那么可读。如果您查看namedtuple文档,您将看到一个更清晰的初始化选项(仍然是不可变的,对不起),例如:“opt(VERBOSE=True,IGNORE_WARNINGS=False)”命名元组非常酷。如果您不在Python2.6上,请参阅这篇文章和这个食谱,试试这个:ad['foo-bar']='oopsy'@Jeremy-不确定问题出在哪里:>>>ad['foo-bar']='oopsy'>>>ad{'baz':'hello','foo':100,'bar':200,'foo-bar':'oopsy'}这看起来确实是OP想要的。这似乎是最接近我要求的,但不是非常不和谐。而且
    选项
    类没有任何其他可能会让人困惑的属性。我认为在类定义中像这样使用VERBOSE是没有意义的,因为它实际上将它创建为类变量(而不是实例变量),这就是重点。这个类只是被用作一个名称空间,这样你就不必实例化任何东西来获取这些值。你能详细说明一下或者给出一个例子吗?
    Options = type('Options', (object,), {})
    options = Options()
    options.VERBOSE = True
    options.IGNORE_WARNINGS = False