如何在 Python 中枚举对象的属性?[重复]

2025-03-13 09:05:00
admin
原创
68
摘要:问题描述:IC# 我们通过反射来实现。在 Javascript 中很简单:for(var propertyName in objectName) var currentPropertyValue = objectName[propertyName]; 如何用 Python 来实现?解决方案 1:for...

问题描述:

IC# 我们通过反射来实现。在 Javascript 中很简单:

for(var propertyName in objectName)
    var currentPropertyValue = objectName[propertyName];

如何用 Python 来实现?


解决方案 1:

for property, value in vars(theObject).items():
    print(property, ":", value)

请注意,在某些罕见情况下存在__slots__属性,此类通常没有__dict__

解决方案 2:

dir()是简单的方法。请参见此处:

Python 自省指南

解决方案 3:

inspect.getmembers(object[, predicate])

按名称排序,以 (名称,值) 对列表的形式返回对象的所有成员。如果提供了可选谓词参数,则仅包括谓词返回真值的成员。

>>> [name for name,thing in inspect.getmembers([])]
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', 
'__delslice__',    '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', 
'__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', 
'__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__','__reduce_ex__', 
'__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', 
'__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 
'insert', 'pop', 'remove', 'reverse', 'sort']
>>> 

解决方案 4:

对象的属性__dict__是其所有其他已定义属性的字典。请注意,Python 类可以覆盖getattr
并创建看起来像属性但不存在于 中的东西__dict__。还有内置函数vars()和 ,dir()它们在细微方面有所不同。 和__slots__可以在一些不寻常的类中替换__dict__

Python 中的对象很复杂。__dict__是开始进行反射式编程的正确地方。dir()如果您在交互式 shell 中进行破解,那么这里就是您的起点。

解决方案 5:

对于单行代码:

print vars(theObject)

解决方案 6:

如果您正在寻找所有属性的反射,上面的答案就很棒。

如果你只是想获取字典的键(与 Python 中的“对象”不同),请使用

my_dict.keys()

my_dict = {'abc': {}, 'def': 12, 'ghi': 'string' }
my_dict.keys() 
> ['abc', 'def', 'ghi']

解决方案 7:

其他答案完全涵盖了这一点,但我会明确说明。一个对象可能具有类属性以及静态和动态实例属性。

class foo:
    classy = 1
    @property
    def dyno(self):
        return 1
    def __init__(self):
        self.stasis = 2

    def fx(self):
        return 3

stasis是静态的,dyno是动态的(参见属性装饰器),classy是类属性。如果我们简单地执行__dict__或,vars我们只会得到静态的。

o = foo()
print(o.__dict__) #{'stasis': 2}
print(vars(o)) #{'stasis': 2}

因此,如果我们想要,其他人__dict__将获得一切(甚至更多)。这包括魔术方法和属性以及正常绑定方法。因此,让我们避免这些:

d = {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}
print(d) #{'stasis': 2, 'classy': 1, 'dyno': 1}

调用type带有属性修饰的方法(动态属性)将为您提供返回值的类型,而不是method。为了证明这一点,让我们对其进行 JSON 字符串化:

import json
print(json.dumps(d)) #{"stasis": 2, "classy": 1, "dyno": 1}

如果这是一种方法,它就会崩溃。

TL;DR。尝试调用extravar = lambda o: {k: getattr(o, k, '') for k in o.__dir__() if k[:2] != '__' and type(getattr(o, k, '')).__name__ != 'method'}所有这三个,但不是方法也不是魔法。

解决方案 8:

我认为值得展示一下上述各种选项之间的差异——通常一张图片胜过千言万语。

>>> from pprint import pprint
>>> import inspect
>>>
>>> class a():
    x = 1               # static class member
    def __init__(self):
        self.y = 2      # static instance member
    @property
    def dyn_prop(self): # dynamic property
        print('DYNPROP WAS HERE')
        return 3
    def test(self):     # function member
        pass
    @classmethod
    def myclassmethod(cls): # class method; static methods behave the same
        pass

>>> i = a()
>>> pprint(i.__dict__)
{'y': 2}
>>> pprint(vars(i))
{'y': 2}
>>> pprint(dir(i))
['__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__',
 'dyn_prop',
 'myclassmethod',
 'test',
 'x',
 'y']
>>> pprint(inspect.getmembers(i))
DYNPROP WAS HERE
[('__class__', <class '__main__.a'>),
 ('__delattr__',
  <method-wrapper '__delattr__' of a object at 0x000001CB891BC7F0>),
 ('__dict__', {'y': 2}),
 ('__dir__', <built-in method __dir__ of a object at 0x000001CB891BC7F0>),
 ('__doc__', None),
 ('__eq__', <method-wrapper '__eq__' of a object at 0x000001CB891BC7F0>),
 ('__format__', <built-in method __format__ of a object at 0x000001CB891BC7F0>),
 ('__ge__', <method-wrapper '__ge__' of a object at 0x000001CB891BC7F0>),
 ('__getattribute__',
  <method-wrapper '__getattribute__' of a object at 0x000001CB891BC7F0>),
 ('__gt__', <method-wrapper '__gt__' of a object at 0x000001CB891BC7F0>),
 ('__hash__', <method-wrapper '__hash__' of a object at 0x000001CB891BC7F0>),
 ('__init__',
  <bound method a.__init__ of <__main__.a object at 0x000001CB891BC7F0>>),
 ('__init_subclass__',
  <built-in method __init_subclass__ of type object at 0x000001CB87CA6A70>),
 ('__le__', <method-wrapper '__le__' of a object at 0x000001CB891BC7F0>),
 ('__lt__', <method-wrapper '__lt__' of a object at 0x000001CB891BC7F0>),
 ('__module__', '__main__'),
 ('__ne__', <method-wrapper '__ne__' of a object at 0x000001CB891BC7F0>),
 ('__new__', <built-in method __new__ of type object at 0x00007FFCA630AB50>),
 ('__reduce__', <built-in method __reduce__ of a object at 0x000001CB891BC7F0>),
 ('__reduce_ex__',
  <built-in method __reduce_ex__ of a object at 0x000001CB891BC7F0>),
 ('__repr__', <method-wrapper '__repr__' of a object at 0x000001CB891BC7F0>),
 ('__setattr__',
  <method-wrapper '__setattr__' of a object at 0x000001CB891BC7F0>),
 ('__sizeof__', <built-in method __sizeof__ of a object at 0x000001CB891BC7F0>),
 ('__str__', <method-wrapper '__str__' of a object at 0x000001CB891BC7F0>),
 ('__subclasshook__',
  <built-in method __subclasshook__ of type object at 0x000001CB87CA6A70>),
 ('__weakref__', None),
 ('dyn_prop', 3),
 ('myclassmethod', <bound method a.myclassmethod of <class '__main__.a'>>),
 ('test', <bound method a.test of <__main__.a object at 0x000001CB891BC7F0>>),
 ('x', 1),
 ('y', 2)]

总结一下:

  • vars()并且__dict__仅返回实例本地属性;

  • dir()返回所有内容,但仅作为字符串成员名称的列表;不调用动态属性;

  • inspect.getmembers()将所有内容作为元组列表返回(name, value);它实际上运行动态属性,并接受一个可以按值predicate过滤掉成员的可选参数。

因此,我的常识性方法通常是dir()在命令行和getmembers()程序中使用,除非有特定的性能考虑。

请注意,为了保持简洁,我没有包括__slots__- 如果存在,它被明确地放在那里以供查询,并且应该直接使用。我也没有介绍元类,这可能会有点棘手(大多数人无论如何都不会使用它们)。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   4046  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   2770  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Freshdesk、ClickUp、nTask、Hubstaff、Plutio、Productive、Targa、Bonsai、Wrike。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在项目管理过程中面临着诸多痛点,如任务分配不...
项目管理系统   90  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Monday、TeamGantt、Filestage、Chanty、Visor、Smartsheet、Productive、Quire、Planview。在当今快速变化的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多项目经理和团队在管理复杂项目时,常...
开源项目管理工具   105  
  本文介绍了以下10款项目管理软件工具:禅道项目管理软件、Smartsheet、GanttPRO、Backlog、Visor、ResourceGuru、Productive、Xebrio、Hive、Quire。在当今快节奏的商业环境中,项目管理已成为企业成功的关键因素之一。然而,许多企业在选择项目管理工具时常常面临困惑:...
项目管理系统   93  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用