列出对象的属性

是否有一种方法可以获取类实例上存在的属性列表?

class new_class():
def __init__(self, number):
self.multi = int(number) * 2
self.str = str(number)


a = new_class(2)
print(', '.join(a.SOMETHING))

期望的结果是输出"multi, str"。我希望它能看到脚本各个部分的当前属性。

1002018 次浏览
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'

这当然会打印类定义中的任何方法或属性。你可以通过将i.startwith('__')改为i.startwith('_')来排除“私有”方法

>>> class new_class():
...   def __init__(self, number):
...     self.multi = int(number) * 2
...     self.str = str(number)
...
>>> a = new_class(2)
>>> a.__dict__
{'multi': 4, 'str': '2'}
>>> a.__dict__.keys()
dict_keys(['multi', 'str'])

你可能也会发现pprint很有用。

你要这个干什么?如果不知道你的确切意图,可能很难得到最好的答案。

  • 如果您想以特定的方式显示类的实例,那么手动执行此操作几乎总是更好的。这将包括你想要的,不包括你不想要的,并且顺序将是可预测的。

    如果你正在寻找一种方法来显示类的内容,手动格式化你关心的属性,并为你的类提供__str____repr__方法

  • 如果你想了解一个对象存在哪些方法,以了解它是如何工作的,请使用helphelp(a)将根据对象的文档字符串显示关于该对象的类的格式化输出。

  • dir的存在是为了通过编程方式获取对象的所有属性。(访问__dict__所做的事情,我将分组为相同,但我自己不会使用。)然而,这可能不包括你想要的东西,也可能包括你不想要的东西。它是不可靠的,人们认为他们想要它的次数比他们想要的多得多。

  • 从某种程度上讲,目前对Python 3的支持非常少。如果你对编写真正的软件感兴趣,你会想要一些第三方的东西,比如numpy, lxml, Twisted, PIL,或者任何数量的web框架,这些框架还不支持Python 3,也不打算很快支持。2.6和3之间的差异。X分支都很小,但是库支持的差异是巨大的。

dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__

然后你可以用type()测试类型,或者用callable()测试方法。

vars(obj)返回对象的属性。

做这件事的方法不止一种:

#! /usr/bin/env python3
#
# This demonstrates how to pick the attiributes of an object


class C(object) :


def __init__ (self, name="q" ):
self.q = name
self.m = "y?"


c = C()


print ( dir(c) )

当运行时,这段代码产生:

jeffs@jeff-desktop:~/skyset$ python3 attributes.py
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__',      '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'm', 'q']


jeffs@jeff-desktop:~/skyset$
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]

经常提到,要列出一个完整的属性列表,你应该使用dir()。但是请注意,与流行的观点相反,dir()并没有带出所有属性。例如,你可能会注意到__name__可能在类的dir()列表中缺失,尽管你可以从类本身访问它。来自dir() (Python 2Python 3)上的文档:

因为dir()主要是为了方便在 交互式提示符,它试图提供一组有趣的名称 它不仅仅是试图提供一个严格或一致定义的集合 的名称,其详细行为可能在不同版本之间更改。为 属性时,元类属性不在结果列表中 参数是一个类

像下面这样的函数往往更完整,尽管不能保证完整性,因为dir()返回的列表可能受到许多因素的影响,包括实现__dir__()方法,或在类或其父类之一上自定义__getattr__()__getattribute__()。详情请参阅所提供的链接。

def dirmore(instance):
visible = dir(instance)
visible += [a for a in set(dir(type)).difference(visible)
if hasattr(instance, a)]
return sorted(visible)

请参见以下Python shell脚本执行顺序,它将给出从创建类到提取实例字段名的解决方案。

>>> class Details:
...       def __init__(self,name,age):
...           self.name=name
...           self.age =age
...       def show_details(self):
...           if self.name:
...              print "Name : ",self.name
...           else:
...              print "Name : ","_"
...           if self.age:
...              if self.age>0:
...                 print "Age  : ",self.age
...              else:
...                 print "Age can't be -ve"
...           else:
...              print "Age  : ","_"
...
>>> my_details = Details("Rishikesh",24)
>>>
>>> print my_details
<__main__.Details instance at 0x10e2e77e8>
>>>
>>> print my_details.name
Rishikesh
>>> print my_details.age
24
>>>
>>> my_details.show_details()
Name :  Rishikesh
Age  :  24
>>>
>>> person1 = Details("",34)
>>> person1.name
''
>>> person1.age
34
>>> person1.show_details
<bound method Details.show_details of <__main__.Details instance at 0x10e2e7758>>
>>>
>>> person1.show_details()
Name :  _
Age  :  34
>>>
>>> person2 = Details("Rob Pike",0)
>>> person2.name
'Rob Pike'
>>>
>>> person2.age
0
>>>
>>> person2.show_details()
Name :  Rob Pike
Age  :  _
>>>
>>> person3 = Details("Rob Pike",-45)
>>>
>>> person3.name
'Rob Pike'
>>>
>>> person3.age
-45
>>>
>>> person3.show_details()
Name :  Rob Pike
Age can't be -ve
>>>
>>> person3.__dict__
{'age': -45, 'name': 'Rob Pike'}
>>>
>>> person3.__dict__.keys()
['age', 'name']
>>>
>>> person3.__dict__.values()
[-45, 'Rob Pike']
>>>

如前所述,使用obj.__dict__可以处理常见情况,但有些类没有__dict__属性而使用__slots__(主要是为了提高内存效率)。

举个更有弹性的例子:

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




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




def get_object_attrs(obj):
try:
return obj.__dict__
except AttributeError:
return {attr: getattr(obj, attr) for attr in obj.__slots__}




a = A(1,2)
b = B(1,2)
assert not hasattr(a, '__dict__')


print(get_object_attrs(a))
print(get_object_attrs(b))

这段代码的输出:

{'x': 1, 'y': 2}
{'x': 1, 'y': 2}
< p > 注一: < br > Python是一种动态语言,它总是更好地了解你试图从中获取属性的类,因为即使这段代码也可能错过一些情况 < p > 注2: < br > 这段代码只输出实例变量,这意味着不提供类变量。例如:< / p >
class A(object):
url = 'http://stackoverflow.com'
def __init__(self, path):
self.path = path


print(A('/questions').__dict__)

代码输出:

{'path': '/questions'}

此代码不打印url类属性,可能会省略想要的类属性 有时候,我们可能认为某个属性是实例成员,但它不是,本例中也不会显示

检查模块:

inspect模块提供了几个有用的函数来帮助get 有关活动对象的信息,如模块、类、方法、 函数,回溯,帧对象和代码对象

使用getmembers(),你可以看到类的所有属性及其值。要排除私有或受保护属性,请使用.startswith('_')。要排除方法或函数,请使用inspect.ismethod()inspect.isfunction()

import inspect




class NewClass(object):
def __init__(self, number):
self.multi = int(number) * 2
self.str = str(number)


def func_1(self):
pass




inst = NewClass(2)


for i in inspect.getmembers(inst):
# Ignores anything starting with underscore
# (that is, private and protected attributes)
if not i[0].startswith('_'):
# Ignores methods
if not inspect.ismethod(i[1]):
print(i)

注意,ismethod()用于i的第二个元素,因为第一个元素只是一个字符串(它的名字)。

跑题:使用CamelCase作为类名。

请参阅已按顺序执行的python shell脚本,在这里您将获得以逗号分隔的字符串格式的类属性。

>>> class new_class():
...     def __init__(self, number):
...         self.multi = int(number)*2
...         self.str = str(number)
...
>>> a = new_class(4)
>>> ",".join(a.__dict__.keys())
'str,multi'<br/>

我使用的是python 3.4

__attrs__给出了一个实例的属性列表。

>>> import requests
>>> r=requests.get('http://www.google.com')
>>> r.__attrs__
['_content', 'status_code', 'headers', 'url', 'history', 'encoding', 'reason', 'cookies', 'elapsed', 'request']
>>> r.url
'http://www.google.com/'
>>>

上面所有的答案都是正确的,你有三个选项可以选择

  1. vars()

  2. __dict__

>>> dir(a)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']
>>> vars(a)
{'multi': 4, 'str': '2'}
>>> a.__dict__
{'multi': 4, 'str': '2'}

你可以使用dir(your_object)来获取属性,使用getattr(your_object, your_object_attr)来获取值

用法:

for att in dir(your_object):
print (att, getattr(your_object,att))

如果你的对象没有__dict__,这特别有用。如果不是这样,你也可以尝试var(your_object)

获取对象的属性

class new_class():
def __init__(self, number):
self.multi = int(number) * 2
self.str = str(number)


new_object = new_class(2)
print(dir(new_object))                   #total list attributes of new_object
attr_value = new_object.__dict__
print(attr_value)                        #Dictionary of attribute and value for new_class


for attr in attr_value:                  #attributes on  new_class
print(attr)


输出

['__class__', '__delattr__', '__dict__', '__dir__', '__doc__','__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'multi', 'str']


{'multi': 4, 'str': '2'}


multi
str

除了这些答案之外,我还将包括一个函数(python 3),用于输出任何值的几乎整个结构。它使用dir来建立属性名的完整列表,然后对每个名称使用getattr。它会显示值的每个成员的类型,如果可能的话还会显示整个成员:

import json


def get_info(obj):


type_name = type(obj).__name__
print('Value is of type {}!'.format(type_name))
prop_names = dir(obj)


for prop_name in prop_names:
prop_val = getattr(obj, prop_name)
prop_val_type_name = type(prop_val).__name__
print('{} has property "{}" of type "{}"'.format(type_name, prop_name, prop_val_type_name))


try:
val_as_str = json.dumps([ prop_val ], indent=2)[1:-1]
print('  Here\'s the {} value: {}'.format(prop_name, val_as_str))
except:
pass

现在,以下任何一项都应该让你有所了解:

get_info(None)
get_info('hello')


import numpy
get_info(numpy)
# ... etc.
  • 使用__dict__vars 不起作用,因为它遗漏了__slots__
  • 使用__dict____slots__ 不起作用,因为它从基类中漏掉了__slots__
  • 使用dir 不起作用,因为它包括类属性,如方法或属性,以及对象属性。
  • 使用vars相当于使用__dict__

这是我最好的:

from typing import Dict


def get_attrs( x : object ) -> Dict[str, object]:
mro      = type( x ).mro()
attrs    = { }
has_dict = False
sentinel = object()


for klass in mro:
for slot in getattr( klass, "__slots__", () ):
v = getattr( x, slot, sentinel )


if v is sentinel:
continue


if slot == "__dict__":
assert not has_dict, "Multiple __dicts__?"
attrs.update( v )
has_dict = True
else:
attrs[slot] = v


if not has_dict:
attrs.update( getattr( x, "__dict__", { } ) )


return attrs