我想获得一个类的属性,比如说:
class MyClass():
a = "12"
b = "34"
def myfunc(self):
return self.a
使用MyClass.__dict__
为我提供了属性和函数列表,甚至是__module__
和__doc__
等函数。虽然MyClass().__dict__
给了我一个空的dict,除非我明确设置了该实例的属性值。
我只想要上面示例中的属性:a
和b
答案 0 :(得分:85)
尝试inspect模块。 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')]
...其中更复杂的可以包括特殊属性名称检查甚至元类;)
答案 1 :(得分:28)
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)
答案 2 :(得分:17)
myfunc
属性为MyClass
。这就是你跑步时的表现:
myinstance = MyClass()
myinstance.myfunc()
它会在名为myinstance
的{{1}}上找到一个属性,找不到一个,看到myfunc
是myinstance
的一个实例并在那里查找。< / p>
因此MyClass
的完整属性列表是:
MyClass
(请注意,我正在使用dir作为列出类成员的快捷方式:它应该只以探索方式使用,而不是在生产代码中使用)
如果您只想要特定属性,则需要使用某些条件过滤此列表,因为>>> dir(MyClass)
['__doc__', '__module__', 'a', 'b', 'myfunc']
,__doc__
和__module__
在任何方面都不特殊, “属性与myfunc
和a
完全相同。
我从未使用过Matt和Borealid所引用的inspect模块,但是从一个简短的链接看起来它有测试可以帮助你做到这一点,但你需要编写自己的谓词函数,因为它似乎您想要的大致是不通过b
测试的属性,并且不以两个下划线开头和结尾。
另请注意:在Python 2.7中使用isroutine
,您使用的是过时的旧式类。除非您故意这样做以便与极其旧的库兼容,否则您应该将您的类定义为class MyClass():
。在Python 3中没有“旧式”类,这种行为是默认的。但是,使用newstyle类将为您提供 lot 更自动定义的属性:
class MyClass(object):
答案 3 :(得分:6)
MyClass().__class__.__dict__
但是,“正确”是通过inspect module来实现的。
答案 4 :(得分:2)
我获取类的所有属性(而不是方法)的解决方案(如果类具有正确编写的文档字符串,其中明确说明了属性):
def get_class_attrs(cls):
return re.findall(r'\w+(?=[,\)])', cls.__dict__['__doc__'])
这篇文章cls.__dict__['__doc__']
提取了该类的文档字符串。
答案 5 :(得分:2)
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('__'))]
答案 6 :(得分:2)
只获取实例属性非常简单 但是在没有函数的情况下获得类属性也有点棘手。
如果您只需列出实例属性,只需使用
的 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()
。
但static methods为not always callable
!
因此,而不是使用callable(value)
使用
的 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 MyClass.__dict__.keys():
if attribute[:2] != '__':
value = getattr(MyClass, 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
答案 7 :(得分:2)
我不知道现在是否有类似的东西,但我使用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个属性。我用它来搜索我需要查看的特定属性。
答案 8 :(得分:1)
我最近需要找出类似于这个问题的内容,所以我想发布一些背景信息,这些信息可能对将来面临同样问题的人有所帮助。
以下是它在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首先会检查新实例的dict MyClass().__dict__['b']
并找不到b
。然后,它会检查班级MyClass.__dict__['b']
并找到b
。
这就是为什么你需要inspect
模块来模仿相同的搜索过程。
答案 9 :(得分:1)
您可以在列表理解中使用dir()
来获取属性名称:
names = [p for p in dir(myobj) if not p.startswith('_')]
使用getattr()
自行获取属性:
attrs = [getattr(myobj, p) for p in dir(myobj) if not p.startswith('_')]
答案 10 :(得分:1)
我想这可以在没有检查的情况下完成。
参加以下课程:
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。
答案 11 :(得分:1)
为什么需要列出属性?从语义上看,您的课程是一个集合。在这种情况下,我建议使用enum:
import enum
class myClass(enum.Enum):
a = "12"
b = "34"
列出您的属性?没有比这更简单的了:
for attr in myClass:
print("Name / Value:", attr.name, attr.value)
答案 12 :(得分:1)
返回 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
{1}}在val
返回字符串中。
关于__repr__
的默认实现,您会发现有用的this answer。简而言之:
__repr__
Wich返回一个字符串,如:
def __repr__(self):
return '<{0}.{1} object at {2}>'.format(
self.__module__, type(self).__name__, hex(id(self)))
每个元素在内存中的位置都是通过<__main__.Bar object at 0x7f3373be5998>
方法获得的。
Python Docs说说id():
返回对象的“身份”。这是一个整数,可以保证在此对象的生存期内唯一且恒定。具有不重叠生存期的两个对象可能具有相同的id()值。
CPython实现细节:这是对象的地址 记忆。
id()
输出:
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())
注意:
经过Python {'a': 1, 'c': [3, 3], 'b': (2, 2), 'd': {4: 4}}
和Python 2.7.13
在Python 2.x中,3.5.3
胜过.iteritems()
答案 13 :(得分:0)
另一个简单的解决方案:
class Color(const):
BLUE = 0
RED = 1
GREEN = 2
@classmethod
def get_all(cls):
return [cls.BLUE, cls.RED, cls.GREEN]
用法: Color.get_all()
答案 14 :(得分:0)
以下是我想要的。
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']
答案 15 :(得分:0)
您可以使用MyClass.__attrs__
。它只是给出了该类的所有属性。没什么。
答案 16 :(得分:0)
两个功能:
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'}
答案 17 :(得分:0)
有一个非常简单的答案,这应该是显而易见的: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。
答案 18 :(得分:-3)
我知道这是三年前的事,但是对于那些将来会遇到这个问题的人,对我来说:
class_name.attribute
工作正常。