2017-06-16 75 views
1

定義兩個類時,一個使用__dict__實現(A),另一個使用__slots__實現(B)。如何在Python中使用__slots__獲取實例屬性名稱值

有沒有一種巧妙的方法來獲取__slots__類的實例屬性名稱和值,就像我在__dict__類中使用vars()函數一樣?

class A(object): 
    def __init__(self, x, y, z): 
     self.x = x 
     self.y = y 
     self.z = z 


class B(object): 
    __slots__ = ('x', 'y', 'z') 
    def __init__(self, x, y, z): 
     self.x = x 
     self.y = y 
     self.z = z 


vars(A(1, 2, 3)) # {'y': 2, 'x': 1, 'z': 3} 
vars(B(1, 2, 3)) # TypeError: vars() argument must have __dict__ attribute 

使用與檢查.__ slots__中或目錄()將只返回屬性的名稱,而不值

B(1, 2, 3).__slots__ # ('x', 'y', 'z') 
+0

您可以使用'getattr'通過屬性的名稱獲取屬性的值作爲字符串。 – user2357112

回答

2

這裏是我以前使用的功能:

def vars2(obj): 
    try: 
     return vars(obj) 
    except TypeError: 
     return {k: getattr(obj, k) for k in obj.__slots__} 
+0

這似乎夠聰明,謝謝! – Yonderin

+0

請注意'__slots__'也可以被分配一個字符串,因此直接對它進行迭代可能一直不正確。 –

+0

添加到@AshwiniChaudhary中,類可以有'__slots__'定義的一些東西,而其他東西定義在'__dict__'中(這可以通過使'__slots__'成爲'__dict __''或者意外地發生,一個繼承層次定義'__slots__',而其他的則不);在這種情況下,'vars'和這個hack都不會獲得完整的實例屬性集。 – ShadowRanger

0
In [2]: x = B(1,2,3) 

In [3]: {a: x.__getattribute__(a) for a in dir(x)} 
Out[3]: 
{'__class__': __main__.B, 
'__delattr__': <method-wrapper '__delattr__' of B object at 0x7f3bb2b48e18>, 
'__doc__': None, 
'__format__': <function __format__>, 
'__getattribute__': <method-wrapper '__getattribute__' of B object at 0x7f3bb2b48e18>, 
'__hash__': <method-wrapper '__hash__' of B object at 0x7f3bb2b48e18>, 
'__init__': <bound method B.__init__ of <__main__.B object at 0x7f3bb2b48e18>>, 
'__module__': '__main__', 
'__new__': <function __new__>, 
'__reduce__': <function __reduce__>, 
'__reduce_ex__': <function __reduce_ex__>, 
'__repr__': <method-wrapper '__repr__' of B object at 0x7f3bb2b48e18>, 
'__setattr__': <method-wrapper '__setattr__' of B object at 0x7f3bb2b48e18>, 
'__sizeof__': <function __sizeof__>, 
'__slots__': ('x', 'y', 'z'), 
'__str__': <method-wrapper '__str__' of B object at 0x7f3bb2b48e18>, 
'__subclasshook__': <function __subclasshook__>, 
'x': 1, 
'y': 2, 
'z': 3} 
如果你不想看到神奇的方法:
In [4]: {a: x.__getattribute__(a) for a in dir(x) if not a.startswith('__')} 
Out[4]: {'x': 1, 'y': 2, 'z': 3}