【问题标题】:How to create inline objects with properties?如何创建具有属性的内联对象?
【发布时间】:2010-12-04 11:26:01
【问题描述】:

在 Javascript 中是:

var newObject = { 'propertyName' : 'propertyValue' };
newObject.propertyName;  // returns "propertyValue"

但是 Python 中的相同语法会创建一个字典,这不是我想要的

new_object = {'propertyName': 'propertyValue'}
new_object.propertyName  # raises an AttributeError

【问题讨论】:

    标签: python instantiation dynamic-languages


    【解决方案1】:
    obj = type('obj', (object,), {'propertyName' : 'propertyValue'})
    

    two kinds of type function uses

    【讨论】:

    • 这是怎么混淆的?这是一个适当的记录行为。
    • 记录在案但晦涩难懂的行为。我很确定 99.9% 的 Python 程序员在实际代码中看到这一点的最初反应是“WTF!?”。
    • 实际上,@Laurence,我的反应是,“哇,我敢打赌,它会创建一个由 'obj' 组成的类的新实例,该类继承自 object'propertyName' 成员设置为'propertyValue'。”你知道什么?我是对的!我不认为这太不直观。
    • 像这样灵活、简洁且易读的代码让我选择了 python。
    • 为了完整起见,要创建类型的实际 instance 而不仅仅是类型对象,这需要尾随 (): obj = type('obj', (object,), {'propertyName' : 'propertyValue'})()
    【解决方案2】:

    Python 3.3 为此添加了 SimpleNamespace 类:

    >>> from types import SimpleNamespace
    
    >>> obj = SimpleNamespace(propertyName='propertyValue')
    >>> obj
    namespace(propertyName='propertyValue')
    
    >>> obj.propertyName
    'propertyValue'
    

    除了构建对象的适当构造函数之外,SimpleNamespace 还定义了 __repr____eq__ (documented in 3.4) 以按预期运行。

    【讨论】:

    • 这应该是公认的答案。比创建一个新的type 更具可读性和直观性。
    【解决方案3】:

    彼得的回答

    obj = lambda: None
    obj.propertyName = 'propertyValue'
    

    【讨论】:

    • @ManelClos 他正在创建一个函数对象,它不返回任何你可以用 obj() 看到的函数对象。函数对象可以有属性。
    • @jeremyjjbrown 你想说什么?
    【解决方案4】:

    我不知道是否有内置的方法可以做到这一点,但你总是可以这样定义一个类:

    class InlineClass(object):
        def __init__(self, dict):
            self.__dict__ = dict
    
    obj = InlineClass({'propertyName' : 'propertyValue'})
    

    【讨论】:

      【解决方案5】:

      我喜欢 Smashery's 的想法,但 Python 似乎满足于让您自己修改类:

      >>> class Inline(object):
      ...     pass
      ...
      >>> obj = Inline()
      >>> obj.test = 1
      >>> obj.test
      1
      >>>
      

      对我来说在 Python 2.5 中工作得很好。请注意,您必须对派生自 object 的类执行此操作 - 如果将行更改为 obj = object,它将不起作用。

      【讨论】:

      • 是的,你可以这样做——但出于某种奇怪的原因,你不能使用 object()——你必须创建自己的类。
      • 如果你想要一个内联类,你可以使用obj = lambda: None,这很奇怪,但会执行必要的任务......
      • @Peter - 我不知道。但是,现在我看到了,我更喜欢 SilentGhost 的回答。
      • 我删除了构造函数以显示实现它的最短方法
      • @Jader - 很公平。没有它看起来会更好。
      【解决方案6】:

      SilentGhost 有一个很好的答案,但他的代码实际上创建了一个元类类型的新对象,换句话说,它创建了一个类。而类是 Python 中的对象!

      obj = type('obj', (object,), {'propertyName' : 'propertyValue'})
      type(obj) 
      

      给了

      <class 'type'>
      

      要在一行中创建具有 dict 属性(又名属性)的自定义或内置类的新对象,我建议只调用它:

      new_object = type('Foo', (object,), {'name': 'new object'})()
      

      现在

      type(new_object) 
      

      <class '__main__.Foo'>
      

      表示它是 Foo 类的对象

      希望对 Python 新手有所帮助。

      【讨论】:

        【解决方案7】:

        在 Python 中很容易声明一个带有 __init__() 函数的类,该函数可以为您设置实例,并带有可选参数。如果您不指定参数,您将获得一个空白实例,如果您指定部分或全部参数,您将初始化该实例。

        我解释了它here(我迄今为止评价最高的答案),所以我不会重新输入解释。但是,如果您有任何问题,请提出,我会回答。

        如果你只想要一个类并不重要的通用对象,你可以这样做:

        class Generic(object):
            pass
        
        x = Generic()
        x.foo = 1
        x.bar = 2
        x.baz = 3
        

        一个明显的扩展是添加一个__str__() 函数来打印一些有用的东西。

        当你想要一个更方便的字典时,这个技巧有时很好。我发现输入x.foo 比输入x["foo"] 更容易。

        【讨论】:

          【解决方案8】:

          另一个可行的选择是使用namedtuple:

          from collections import namedtuple
          
          message = namedtuple('Message', ['propertyName'], verbose=True)
          messages = [
              message('propertyValueOne'),
              message('propertyValueTwo')
          ]
          

          【讨论】:

            【解决方案9】:
            class test:
                def __setattr__(self,key,value):
                    return value
            
            
            myObj = test()
            myObj.mykey = 'abc' # set your property and value
            

            【讨论】:

            • 不需要定义setattr,见Chris回复
            猜你喜欢
            • 1970-01-01
            • 2019-12-28
            • 1970-01-01
            • 2015-08-28
            • 2016-12-28
            • 1970-01-01
            • 2023-01-12
            相关资源
            最近更新 更多