Is there a way to grab a list of attributes that exist on instances of a class?
class new_class():
def 开发者_如何学Go__init__(self, number):
self.multi = int(number) * 2
self.str = str(number)
a = new_class(2)
print(', '.join(a.SOMETHING))
The desired result is that "multi, str" will be output. I want this to see the current attributes from various parts of a script.
>>> 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'])
You may also find pprint helpful.
dir(instance)
# or (same value)
instance.__dir__()
# or
instance.__dict__
Then you can test what type is with type()
or if is a method with callable()
.
All previous answers are correct, you have three options for what you are asking
dir()
vars()
__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'}
vars(obj)
returns the attributes of an object.
Inspect module:
The inspect module provides several useful functions to help get information about live objects such as modules, classes, methods, functions, tracebacks, frame objects, and code objects.
Using getmembers()
you can see all attributes of your class, along with their value. To exclude private or protected attributes use .startswith('_')
. To exclude methods or functions use inspect.ismethod()
or 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)
Note that ismethod()
is used on the second element of i
since the first is simply a string (its name).
Offtopic: Use CamelCase for class names.
>>> ', '.join(i for i in dir(a) if not i.startswith('__'))
'multi, str'
This of course will print any methods or attributes in the class definition. You can exclude "private" methods by changing i.startwith('__')
to i.startwith('_')
You can use dir(your_object)
to get the attributes and getattr(your_object, your_object_attr)
to get the values
usage :
for att in dir(your_object):
print (att, getattr(your_object,att))
This is particularly useful if your object have no __dict__. If that is not the case you can try var(your_object) also
It's often mentioned that to list a complete list of attributes you should use dir()
. Note however that contrary to popular belief dir()
does not bring out all attributes. For example you might notice that __name__
might be missing from a class's dir()
listing even though you can access it from the class itself. From the doc on dir()
(Python 2, Python 3):
Because dir() is supplied primarily as a convenience for use at an interactive prompt, it tries to supply an interesting set of names more than it tries to supply a rigorously or consistently defined set of names, and its detailed behavior may change across releases. For example, metaclass attributes are not in the result list when the argument is a class.
A function like the following tends to be more complete, although there's no guarantee of completeness since the list returned by dir()
can be affected by many factors including implementing the __dir__()
method, or customizing __getattr__()
or __getattribute__()
on the class or one of its parents. See provided links for more details.
def dirmore(instance):
visible = dir(instance)
visible += [a for a in set(dir(type)).difference(visible)
if hasattr(instance, a)]
return sorted(visible)
There is more than one way to do it:
#! /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) )
When run, this code produces:
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$
What do you want this for? It may be hard to get you the best answer without knowing your exact intent.
It is almost always better to do this manually if you want to display an instance of your class in a specific way. This will include exactly what you want and not include what you don't want, and the order will be predictable.
If you are looking for a way to display the content of a class, manually format the attributes you care about and provide this as the
__str__
or__repr__
method for your class.If you want to learn about what methods and such exist for an object to understand how it works, use
help
.help(a)
will show you a formatted output about the object's class based on its docstrings.dir
exists for programatically getting all the attributes of an object. (Accessing__dict__
does something I would group as the same but that I wouldn't use myself.) However, this may not include things you want and it may include things you do not want. It is unreliable and people think they want it a lot more often than they do.On a somewhat orthogonal note, there is very little support for Python 3 at the current time. If you are interested in writing real software you are going to want third-party stuff like numpy, lxml, Twisted, PIL, or any number of web frameworks that do not yet support Python 3 and do not have plans to any time too soon. The differences between 2.6 and the 3.x branch are small, but the difference in library support is huge.
Please see the python shell script which has been executed in sequence, here you will get the attributes of a class in string format separated by comma.
>>> 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/>
I am using python 3.4
In addition to these answers, I'll include a function (python 3) for spewing out virtually the entire structure of any value. It uses dir
to establish the full list of property names, then uses getattr
with each name. It displays the type of every member of the value, and when possible also displays the entire member:
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
Now any of the following should give insight:
get_info(None)
get_info('hello')
import numpy
get_info(numpy)
# ... etc.
Get attributes of an 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)
Output
['__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
As written before using obj.__dict__
can handle common cases but some classes do not have the __dict__
attribute and use __slots__
(mostly for memory efficiency).
example for a more resilient way of doing this:
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))
this code's output:
{'x': 1, 'y': 2}
{'x': 1, 'y': 2}
Note1:
Python is a dynamic language and it is always better knowing the classes you trying to get the attributes from as even this code can miss some cases.
Note2:
this code outputs only instance variables meaning class variables are not provided. for example:
class A(object):
url = 'http://stackoverflow.com'
def __init__(self, path):
self.path = path
print(A('/questions').__dict__)
code outputs:
{'path': '/questions'}
This code does not print the url
class attribute and might omit wanted class attributes.
Sometimes we might think an attribute is an instance member but it is not and won't be shown using this example.
- Using
__dict__
orvars
does not work because it misses out__slots__
. - Using
__dict__
and__slots__
does not work because it misses out__slots__
from base classes. - Using
dir
does not work because it includes class attributes, such as methods or properties, as well as the object attributes. - Using
vars
is equivalent to using__dict__
.
This is the best I have:
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
Please see the following Python shell scripting execution in sequence, it will give the solution from creation of class to extracting the field names of instances.
>>> 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']
>>>
attributes_list = [attribute for attribute in dir(obj) if attribute[0].islower()]
__attrs__
gives the list of attributes of an instance.
>>> 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/'
>>>
精彩评论