我想获取一个类的属性,说:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
使用MyClass.__dict__
给了我一系列属性和函数,甚至还有像__module__
和的函数__doc__
。而MyClass().__dict__
除非我显式设置该实例的属性值,否则会给我一个空的字典。
我只想要属性,在上面的示例中,这些属性是:a
和b
我想获取一个类的属性,说:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
使用MyClass.__dict__
给了我一系列属性和函数,甚至还有像__module__
和的函数__doc__
。而MyClass().__dict__
除非我显式设置该实例的属性值,否则会给我一个空的字典。
我只想要属性,在上面的示例中,这些属性是:a
和b
Answers:
尝试检查模块。getmembers
并且各种测试应该会有所帮助。
编辑:
例如,
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> import inspect
>>> inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
[('__class__', type),
('__dict__',
<dictproxy {'__dict__': <attribute '__dict__' of 'MyClass' objects>,
'__doc__': None,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'MyClass' objects>,
'a': '34',
'b': '12',
'myfunc': <function __main__.myfunc>}>),
('__doc__', None),
('__module__', '__main__'),
('__weakref__', <attribute '__weakref__' of 'MyClass' objects>),
('a', '34'),
('b', '12')]
现在,特殊的方法和属性引起了我的共鸣-可以通过多种方式处理这些方法和属性,其中最简单的方法就是根据名称进行过滤。
>>> attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
>>> [a for a in attributes if not(a[0].startswith('__') and a[0].endswith('__'))]
[('a', '34'), ('b', '12')]
...,其中更复杂的可以包括特殊的属性名称检查甚至元类;)
attributes = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a)))
print [a[0] for a in attributes if '_' not in a[0]]
like_this
!它还将避免您可能故意使用的“私有”属性。
inspect.getmembers(MyClass, ...
,MyClass
可以用类或对象替换,如果需要对象值列表,则必须用MyClass
对象变量替换(或者self
如果放这种表达def __repr__()
方式就像我一样)。
i = inspect.getmembers(MyClass, lambda a:not(inspect.isroutine(a))); z = [_[1] for _ in i if _[0] in '__dict__'][0]
然后这只是从z获取键的问题。
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)
if not i.startswith('_')
而不是if i[:1] != '_'
?
.__dict__.keys()
则将不包括父类的属性。
myfunc
是的属性MyClass
。这是在运行时发现的方式:
myinstance = MyClass()
myinstance.myfunc()
它在myinstance
named myfunc
上寻找一个属性,找不到一个,发现它myinstance
是的一个实例,MyClass
并在那里查找。
因此,属性的完整列表MyClass
为:
>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']
(请注意,我使用dir只是列出类成员的一种快速简便的方法:它只能以探索的方式使用,而不能在生产代码中使用)
如果您只想要特定的属性,则需要使用一些条件来过滤此列表,因为__doc__
,__module__
和myfunc
没有特殊的以任何方式,他们的属性完全相同的方式a
和b
是。
我从未使用过Matt和Borealid提到的inspect模块,但是从一个简短的链接来看,它似乎具有测试可以帮助您完成此任务,但是您需要编写自己的谓词函数,因为这似乎是您想要的大概是 不通过的isroutine
测试且不会以两个下划线开头和结尾。
另请注意:通过class MyClass():
在python 2.7中使用,您正在使用过时的老式类。除非您是为了与极老的库兼容而故意这样做,否则应将您的类定义为class MyClass(object):
。在Python 3中,没有“旧式”类,并且此行为是默认行为。然而,使用newstyle班会帮你很多更多的自动定义的属性:
>>> class MyClass(object):
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> dir(MyClass)
['__class__', '__delattr__', '__dict__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'a', 'b', 'myfunc']
仅获取实例属性很容易。
但是还要获取类属性没有函数的情况下比较棘手。
如果您只需要列出实例属性,请使用
for attribute, value in my_instance
。__dict__
。items()
>>> from __future__ import (absolute_import, division, print_function)
>>> class MyClass(object):
... def __init__(self):
... self.a = 2
... self.b = 3
... def print_instance_attributes(self):
... for attribute, value in self.__dict__.items():
... print(attribute, '=', value)
...
>>> my_instance = MyClass()
>>> my_instance.print_instance_attributes()
a = 2
b = 3
>>> for attribute, value in my_instance.__dict__.items():
... print(attribute, '=', value)
...
a = 2
b = 3
要获得没有功能的类属性,诀窍是使用callable()
。
因此,不要使用callable(value)
use
callable
(getattr
(MyClass, attribute))
from __future__ import (absolute_import, division, print_function)
class MyClass(object):
a = "12"
b = "34" # class attributes
def __init__(self, c, d):
self.c = c
self.d = d # instance attributes
@staticmethod
def mystatic(): # static method
return MyClass.b
def myfunc(self): # non-static method
return self.a
def print_instance_attributes(self):
print('[instance attributes]')
for attribute, value in self.__dict__.items():
print(attribute, '=', value)
def print_class_attributes(self):
print('[class attributes]')
for attribute in self.__dict__.keys():
if attribute[:2] != '__':
value = getattr(self, attribute)
if not callable(value):
print(attribute, '=', value)
v = MyClass(4,2)
v.print_class_attributes()
v.print_instance_attributes()
注意: print_class_attributes()
应该
但不是这个愚蠢和简单@staticmethod
示例中,。
$ python2 ./print_attributes.py
[class attributes]
a = 12
b = 34
[instance attributes]
c = 4
d = 2
$ python3 ./print_attributes.py
[class attributes]
b = 34
a = 12
[instance attributes]
c = 4
d = 2
MyClass().__class__.__dict__
但是,这样做的“正确”是通过检查模块。
MyClass().__class__.__dict__
==MyClass.__dict__
MyClass().__class__.__dict__ != MyClass().__dict__
,但牛不包括右侧的括号(如果该括号是正确的话)
import re
class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
attributes = [a for a, v in MyClass.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
对于MyClass的实例,例如
mc = MyClass()
用于type(mc)
代替MyClass
列表理解。但是,如果将一个属性动态添加到mc
,例如mc.c = "42"
,则type(mc)
在此策略中使用该属性时将不会显示该属性。它仅提供原始类的属性。
要获得类实例的完整字典,您需要将type(mc).__dict__
和的字典合并mc.__dict__
。
mc = MyClass()
mc.c = "42"
# Python 3.5
combined_dict = {**type(mc).__dict__, **mc.__dict__}
# Or Python < 3.5
def dict_union(d1, d2):
z = d1.copy()
z.update(d2)
return z
combined_dict = dict_union(type(mc).__dict__, mc.__dict__)
attributes = [a for a, v in combined_dict.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
我不知道是否已经做过类似的事情,但是我使用vars()做了一个不错的属性搜索功能。vars()创建您通过其传递的类的属性的字典。
class Player():
def __init__(self):
self.name = 'Bob'
self.age = 36
self.gender = 'Male'
s = vars(Player())
#From this point if you want to print all the attributes, just do print(s)
#If the class has a lot of attributes and you want to be able to pick 1 to see
#run this function
def play():
ask = input("What Attribute?>: ")
for key, value in s.items():
if key == ask:
print("self.{} = {}".format(key, value))
break
else:
print("Couldn't find an attribute for self.{}".format(ask))
我正在用Python开发大量的Text Adventure,到目前为止,我的Player类具有100多个属性。我用它来搜索需要查看的特定属性。
我想这可以在没有检查的情况下完成。
参加以下课程:
class Test:
a = 1
b = 2
def __init__(self):
self.c = 42
@staticmethod
def toto():
return "toto"
def test(self):
return "test"
查看成员及其类型:
t = Test()
l = [ (x, eval('type(x.%s).__name__' % x)) for x in dir(a) ]
...给出:
[('__doc__', 'NoneType'),
('__init__', 'instancemethod'),
('__module__', 'str'),
('a', 'int'),
('b', 'int'),
('c', 'int'),
('test', 'instancemethod'),
('toto', 'function')]
因此,仅输出变量,您只需按类型过滤结果,并且名称不能以“ __”开头。例如
filter(lambda x: x[1] not in ['instancemethod', 'function'] and not x[0].startswith('__'), l)
[('a', 'int'), ('b', 'int'), ('c', 'int')] # actual result
而已。
注意:如果您使用的是Python 3,请将迭代器转换为列表。
如果您想要一种更强大的方法,请使用inspect。
返回dict {attribute_name:attribute_value},对象已过滤。即{'a': 1, 'b': (2, 2), 'c': [3, 3]}
{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}
返回列表[attribute_names],对象已过滤。即['a', 'b', 'c', 'd']
[k for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]
返回列表[attribute_values],对象已过滤。即[1, (2, 2), [3, 3], {4: 4}]
[val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)]
消除if
条件。返回{'a': 1, 'c': [3, 3], 'b': (2, 2), 'e': <function <lambda> at 0x7fc8a870fd70>, 'd': {4: 4}, 'f': <object object at 0x7fc8abe130e0>}
{k: val for k, val in self.__dict__.items()}
只要的默认实现__repr__
不被覆盖的if
语句将返回True
如果位置在记忆的十六进制表示val
是在__repr__
返回的字符串。
关于默认实现,__repr__
您可以找到此答案有用。简而言之:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
Wich返回类似以下的字符串:
<__main__.Bar object at 0x7f3373be5998>
通过该id()
方法可以获取每个元素在内存中的位置。
Python文档对id()说:
返回对象的“身份”。这是一个整数,可以保证在此对象的生存期内唯一且恒定。具有不重叠生存期的两个对象可能具有相同的id()值。
CPython实现细节:这是对象在内存中的地址。
class Bar:
def __init__(self):
self.a = 1
self.b = (2, 2)
self.c = [3, 3]
self.d = {4: 4}
self.e = lambda: "5"
self.f = object()
#__str__ or __repr__ as you prefer
def __str__(self):
return "{}".format(
# Solution in Short Number 1
{k: val for k, val in self.__dict__.items() if not str(hex(id(val))) in str(val)}
)
# Main
print(Bar())
输出:
{'a': 1, 'c': [3, 3], 'b': (2, 2), 'd': {4: 4}}
注意事项:
经过Python 2.7.13
和Python 测试3.5.3
在Python 2.x .iteritems()
中,优先于.items()
我最近需要弄清楚与该问题类似的内容,因此我想发布一些背景信息,这些信息可能会对将来面对相同问题的其他人有所帮助。
以下是它在Python中的工作方式(来自https://docs.python.org/3.5/reference/datamodel.html#the-standard-type-hierarchy):
MyClass
是类对象,MyClass()
是类对象的实例。实例__dict__
仅具有特定于该实例的属性和方法(例如self.somethings
)。如果属性或方法是类的一部分,则它在类的中__dict__
。当您执行时MyClass().__dict__
,会建立的实例,MyClass
除了类别属性外,没有其他属性或方法,因此为空__dict__
因此,如果您说的话print(MyClass().b)
,Python首先检查新实例的字典MyClass().__dict__['b']
,但找不到b
。然后,它检查该类MyClass.__dict__['b']
并找到b
。
这就是为什么您需要该inspect
模块来模拟相同的搜索过程。
如果要“获取”属性,则有一个非常简单的答案,该答案应该很明显:getattr
class MyClass(object):
a = '12'
b = '34'
def myfunc(self):
return self.a
>>> getattr(MyClass, 'a')
'12'
>>> getattr(MyClass, 'myfunc')
<function MyClass.myfunc at 0x10de45378>
它在python 2.7和python 3.x中都很好用。
如果要列出这些项目,则仍然需要使用inspect。
两个功能:
def get_class_attr(Cls) -> []:
import re
return [a for a, v in Cls.__dict__.items()
if not re.match('<function.*?>', str(v))
and not (a.startswith('__') and a.endswith('__'))]
def get_class_attr_val(cls):
attr = get_class_attr(type(cls))
attr_dict = {}
for a in attr:
attr_dict[a] = getattr(cls, a)
return attr_dict
用:
>>> class MyClass:
a = "12"
b = "34"
def myfunc(self):
return self.a
>>> m = MyClass()
>>> get_class_attr_val(m)
{'a': '12', 'b': '34'}
以下是我想要的。
class Base:
b = 'b'
class MyClass(Base):
a = '12'
def __init__(self, name):
self.name = name
@classmethod
def c(cls):
...
@property
def p(self):
return self.a
def my_fun(self):
return self.name
print([name for name, val in inspect.getmembers(MyClass) if not name.startswith('_') and not callable(val)]) # need `import inspect`
print([_ for _ in dir(MyClass) if not _.startswith('_') and not callable(getattr(MyClass, _))])
# both are equ: ['a', 'b', 'p']
my_instance = MyClass('c')
print([_ for _ in dir(my_instance) if not _.startswith('_') and not callable(getattr(my_instance, _))])
# ['a', 'b', 'name', 'p']