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

在Python中创建具有任意属性的对象的最短方法?

  •  24
  • Blixt  · 技术社区  · 15 年前

    嘿,我刚开始思考这个问题,因为我发现一个代码需要一个具有特定属性集的对象(但是没有指定该对象应该是什么类型)。

    一种解决方案是创建一个具有代码所期望的属性的新类,但是当我调用其他代码时,也需要具有(其他)属性的对象,我必须创建越来越多的类。

    object 而不是创建一个新的类,这将无法工作,因为 对象 实例不允许新属性)。

    我提出的最后一个最短的解决方案是创建一个具有构造函数的类,该构造函数接受关键字参数,就像 dict 构造函数,然后将它们设置为属性:

    class data:
        def __init__(self, **kw):
            for name in kw:
                setattr(self, name, kw[name])
    
    options = data(do_good_stuff=True, do_bad_stuff=False)
    

    11 回复  |  直到 15 年前
        1
  •  28
  •   Wesley Smith    5 年前

    原始代码可以通过使用 __dict__ :

    In [1]: class data:
       ...:     def __init__(self, **kwargs):
       ...:         self.__dict__.update(kwargs)
       ...: 
    
    In [2]: d = data(foo=1, bar=2)
    
    In [3]: d.foo
    Out[3]: 1
    
    In [4]: d.bar
    Out[4]: 2
    

    在Python3.3及更高版本中,此语法由 types.SimpleNamespace

        2
  •  49
  •   Bob Stein    4 年前

    type('', (), {})() 将创建一个可以具有任意属性的对象。

    例子:

    obj = type('', (), {})()
    obj.hello = "hello"
    obj.world = "world"
    print obj.hello, obj.world   # will print "hello world"
    

    type() 使用三个参数创建一个新类型。

    • ''

    • 第二个论点 () 是基类型的元组。在这里 object

    • 第三个参数是新对象的属性字典。我们一开始没有属性,所以它是空的 {}

    ()

        3
  •  21
  •   S.Lott    15 年前

    使用 collections.namedtuple .

    from collections import namedtuple
    Data = namedtuple( 'Data', [ 'do_good_stuff', 'do_bad_stuff' ] )
    options = Data( True, False )
    
        4
  •  17
  •   Tom Willis    15 年前

    这是我知道的最短的路

    >>> obj = type("myobj",(object,),dict(foo=1,bar=2))
    >>> obj.foo
    1
    >>> obj.bar
    2
    >>> 
    

    使用dict而不是{}可以确保属性名是有效的

    >>> obj = type("myobj",(object,),{"foo-attr":1,"bar-attr":2})
    >>> obj.foo-attr
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    AttributeError: type object 'myobj' has no attribute 'foo'
    >>>
    
        5
  •  13
  •   user609095 user609095    15 年前

    class Struct(object):
        pass
    
    something = Struct()
    something.awesome = abs
    
    result = something.awesome(-42)
    

    编辑: http://docs.python.org/tutorial/classes.html#odds-and-ends

    在结果中添加了赋值,因为我正在使用交互式口译员进行验证,而您可能没有。

        6
  •  10
  •   Boris Verkhovskiy Brian Clapper    5 年前

    函数是一个对象。所以你可以给一个函数分配属性。或者做一个。我认为,就代码行而言,这是最简单的方法。

    def hello():
        pass
    
    
    hello.chook = 123
    

    但是最简单和最优雅的方法(但是python3.3+)是使用标准库的 SimpleNamespace :

    >>> from types import SimpleNamespace
    >>> foo = SimpleNamespace()
    >>> foo.hello = "world"
    
        7
  •  7
  •   andrefsp    12 年前

    使用lambda和类型内建的组合,我认为是实现这一点的最小方法:

    obj = lambda **kwargs: type('obj', (object,), kwargs)()
    
    options = obj(do_good_stuff=True, do_bad_stuff=False)
    
    print options.do_good_stuff
    print options.do_bad_stuff
    
        8
  •  6
  •   abjennings    11 年前

    class data: pass
    
    data.foo = 1
    data.bar = 2
    

    使用类静态成员变量来保存数据。

        9
  •  0
  •   Olivier Verdier    15 年前

    如果我正确理解你的问题,你需要记录。Python类可以这样使用,这就是您要做的。

    字典

    你的班级榜样 data

    self.__setattr__(name, kw[name]) .)

        10
  •  0
  •   Mike Graham    15 年前

    这通常是您使用dict来实现的,而不是创建一个类。