2017-06-16 71 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}