2012-07-20 16 views

回答

10

我喜歡用特殊的方法制作一個dict的子類,我發現here。它看起來像:

class Struct(dict): 
    """Python Objects that act like Javascript Objects""" 
    def __init__(self, *args, **kwargs): 
     super(Struct, self).__init__(*args, **kwargs) 
     self.__dict__ = self 

這個對象可以這樣使用:

o = Struct(x=10) 
o.y = 20 
o['z'] = 30 
print o.x, o['y'], o.z 

不同類型的接入可以在一個可更換的方式使用。

+3

優雅!這在我的「snippets」目錄中消失了。謝謝! +1 – 2012-07-20 11:21:20

+0

真的很好。保存爲片段 – 2012-07-20 11:38:31

+0

太棒了!這正是我需要的。 – 2012-07-20 12:12:35

2

我使用字典這樣的事情。 Dics有很多好處,比如列出所有按鍵等。

3

聽起來像是你想有一個namedtuple(但它有效地只讀):

from collections import namedtuple 

XYTuple = namedtuple('XYTuple', 'x y') 
nt = XYTuple._make((10, 20)) 

print nt.x, nt.y 
1

第二種解決方案不起作用:

>>> o = object() 
>>> o.x = 10 
AttributeError: 'object' object has no attribute 'x' 

這是因爲對象的實例沒有__dict__

我同意使用方括號來訪問屬性並不優雅。返回一個值對象,我的團隊使用這個(這些代碼肯定可以改善):

class Struct(object): 
    """ 
    An object whose attributes are initialized from an optional positional 
    argument or from a set of keyword arguments (the constructor accepts the 
    same arguments than the dict constructor). 
    """ 

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

    def __repr__(self): 
     klass = self.__class__ 
     attributes = ', '.join('{0}={1!r}'.format(k, v) for k, v in self.__dict__.iteritems()) 
     return '{0}.{1}({2})'.format(klass.__module__, klass.__name__, attributes) 

使用Struct,你的例子可以改寫爲是:

def func(): 
    return Struct(x = 10, y = 20) 

Struct超過namedtuple優勢是你不必事先定義你的類型。例如,它與JavaScript等語言中使用的內容更接近。 namedtuple的優點是效率更高,同時可以通過索引或名稱訪問屬性。

+0

如果某些屬性名稱不是字符集[_a-zA-Z0-9]中的有效標識符,我也喜歡@glglgl的優雅實現。 – 2012-07-20 11:18:49

1

然而,從[現在是當前]版本的jsobect派生出的另一方式,也在@ glglgl的answer使用(但有很大的不同):

class Struct(dict): 
    def __getattr__(self, k): 
     try: 
      return self[k] 
     except KeyError: 
      return self.__getitem__(k) 

    def __setattr__(self, k, v): 
     if isinstance(v, dict): 
      self[k] = self.__class__(v) 
     else: 
      self[k] = v 


o = Struct(x=10) 
o.y = 20 
o['z'] = 30 
print(o.x, o['y'], o.z) # -> (10, 20, 30) 
print(o['not_there']) # -> KeyError: 'not_there' 
print(o.not_there)  # -> KeyError: 'not_there'