代码之家  ›  专栏  ›  技术社区  ›  mhagger

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

  •  9
  • mhagger  · 技术社区  · 17 年前

    options = ??????
    options.VERBOSE = True
    options.IGNORE_WARNINGS = False
    
    # Then, elsewhere in the code...
    if options.VERBOSE:
        ...
    

    我当然可以用字典,但是 options.VERBOSE options['VERBOSE'] .

    想法 我应该能做到的

    options = object()
    

    自从 object object() __dict__

    options.VERBOSE = True
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: 'object' object has no attribute 'VERBOSE'
    

    创建一个对象的最简单的“pythonic”方法是什么,最好不用创建额外的helper类?

    11 回复  |  直到 17 年前
        1
  •  15
  •   gimel    17 年前

    collections module 已经成长为 命名双倍 2.6中的功能:

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

    A. 是不可变的,因此只能在创建字段时指定字段值。

    在早些时候 版本,则可以创建空类:

    class options(object):
        pass
    
    myoptions=options()
    myoptions.VERBOSE=True
    myoptions.IGNORE_WARNINGS=False
    >>> myoptions.IGNORE_WARNINGS,myoptions.VERBOSE
    (False, True)
    
        2
  •  9
  •   David Eyk    17 年前

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

    class options(object):
        VERBOSE = True
        IGNORE_WARNINGS = True
    
    if options.VERBOSE:
        # ...
    

    完整地说,另一种方法是使用单独的模块,即。 options.py

    options.py

    VERBOSE = True
    IGNORE_WARNINGS = True
    

    然后,在 main.py :

    import options
    
    if options.VERBOSE:
        # ...
    

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

        3
  •  7
  •   Jouni K. Seppänen    17 年前

    如果坚持不必定义类,则可能会滥用某些现有类。大多数对象属于“新型”类,这些类没有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>
    

    一个问题是函数已经有一些属性,因此dir(x)有点混乱:

    >>> dir(x)
    ['__call__', '__class__', '__delattr__', '__dict__', '__doc__',
    '__get__', '__getattribute__', '__hash__', '__init__',
    '__module__', '__name__', '__new__', '__reduce__',
    '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'foo',
    'func_closure', 'func_code', 'func_defaults', 'func_dict',
    'func_doc', 'func_globals', 'func_name', 'xyzzy']
    
        4
  •  7
  •   alif    17 年前

    optparse :

    from optparse import OptionParser
    [...]
    parser = OptionParser()
    parser.add_option("-f", "--file", dest="filename",
                  help="write report to FILE", metavar="FILE")
    parser.add_option("-q", "--quiet",
                  action="store_false", dest="verbose", default=True,
                  help="don't print status messages to stdout")
    
    (options, args) = parser.parse_args()
    
    file = options.filename
    if options.quiet == True:
        [...]
    
        5
  •  5
  •   davidavr    17 年前

    我用 attrdict

    class attrdict(dict):
        def __init__(self, *args, **kwargs):
            dict.__init__(self, *args, **kwargs)
            self.__dict__ = self
    

    根据你的观点,你可能认为这要么是一个大难题,要么是相当聪明。但不管您怎么想,它确实可以生成好看的代码,并且与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
    
        6
  •  4
  •   Community Mohan Dere    9 年前

    David Eyk's answer .

    type 功能:

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

    请注意,您可以提供初始字典,也可以将其保留为空。

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

        7
  •  3
  •   Alex Coventry    17 年前

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

        8
  •  2
  •   Community Mohan Dere    9 年前

    davraamides's suggestion ,可采用以下方法:

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

    哪一个

    1. 这可不是什么稀奇古怪的事。

    2. 不会使用的标准方法污染每个对象的命名空间 dict ; 例如 ad.has_key 未为类型为的对象定义 attrdict2 .

    顺便说一下,初始化的实例更容易 attrdict 属性2 :

    >>> ad = attrdict2(foo = 100, bar = 200)
    

    属性2 不兼容于 .

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

    class attrdict3(object):
        pass
    
    ad = attrdict3()
    ad.foo = 100
    ad.bar = 200
    

    但我仍然希望找到一个不需要辅助类的解决方案。

        9
  •  1
  •   mhagger    17 年前

    可以使用

    class options(object):
        VERBOSE = True
        IGNORE_WARNINGS = False
    
    options.VERBOSE = False
    
    if options.VERBOSE:
        ...
    

    ,使用类对象本身(不是类的实例!)作为存储单个选项的位置。这是简洁的,满足了所有的需求,但它似乎是对类概念的滥用。如果用户实例化了 options

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

        10
  •  1
  •   Eli Bendersky    17 年前

    完成此任务的最简单类是:

    class Struct:
        def __init__(self, **entries): 
            self.__dict__.update(entries)
    

    它以后可以用作:

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

    namedtuple (正如另一个评论所建议的)是一个更高级的类,它为您提供了更多的功能。如果您仍然使用Python2.5,那么实现2.6 命名双倍 是基于的,请访问 http://code.activestate.com/recipes/500261/

        11
  •  -2
  •   Philippe Ombredanne    14 年前