Try the inspect module. getmembers and the various tests should be helpful.
EDIT:
For example,
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')]
Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.
>>> 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')]
...and the more complicated of which can include special attribute name checks or even metaclasses ;)
Answer from Matt Luongo on Stack OverflowAccessing attributes of a class
Inspect python class attributes - Stack Overflow
Any way to get ALL attributes of an object in python?
How to access attributes of a class in a list that was made my iteration?
Videos
Try the inspect module. getmembers and the various tests should be helpful.
EDIT:
For example,
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')]
Now, the special methods and attributes get on my nerves- those can be dealt with in a number of ways, the easiest of which is just to filter based on name.
>>> 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')]
...and the more complicated of which can include special attribute name checks or even metaclasses ;)
def props(cls):
return [i for i in cls.__dict__.keys() if i[:1] != '_']
properties = props(MyClass)
Below is the hard way. Here's the easy way. Don't know why it didn't occur to me sooner.
import inspect
def get_user_attributes(cls):
boring = dir(type('dummy', (object,), {}))
return [item
for item in inspect.getmembers(cls)
if item[0] not in boring]
Here's a start
def get_user_attributes(cls):
boring = dir(type('dummy', (object,), {}))
attrs = {}
bases = reversed(inspect.getmro(cls))
for base in bases:
if hasattr(base, '__dict__'):
attrs.update(base.__dict__)
elif hasattr(base, '__slots__'):
if hasattr(base, base.__slots__[0]):
# We're dealing with a non-string sequence or one char string
for item in base.__slots__:
attrs[item] = getattr(base, item)
else:
# We're dealing with a single identifier as a string
attrs[base.__slots__] = getattr(base, base.__slots__)
for key in boring:
del attrs['key'] # we can be sure it will be present so no need to guard this
return attrs
This should be fairly robust. Essentially, it works by getting the attributes that are on a default subclass of object to ignore. It then gets the mro of the class that's passed to it and traverses it in reverse order so that subclass keys can overwrite superclass keys. It returns a dictionary of key-value pairs. If you want a list of key, value tuples like in inspect.getmembers then just return either attrs.items() or list(attrs.items()) in Python 3.
If you don't actually want to traverse the mro and just want attributes defined directly on the subclass then it's easier:
def get_user_attributes(cls):
boring = dir(type('dummy', (object,), {}))
if hasattr(cls, '__dict__'):
attrs = cls.__dict__.copy()
elif hasattr(cls, '__slots__'):
if hasattr(base, base.__slots__[0]):
# We're dealing with a non-string sequence or one char string
for item in base.__slots__:
attrs[item] = getattr(base, item)
else:
# We're dealing with a single identifier as a string
attrs[base.__slots__] = getattr(base, base.__slots__)
for key in boring:
del attrs['key'] # we can be sure it will be present so no need to guard this
return attrs
Double underscores on both ends of 'special attributes' have been a part of python before 2.0. It would be very unlikely that they would change that any time in the near future.
class Foo(object):
a = 1
b = 2
def get_attrs(klass):
return [k for k in klass.__dict__.keys()
if not k.startswith('__')
and not k.endswith('__')]
print get_attrs(Foo)
['a', 'b']
I'm using the plex python library to get some info from my plex server.
What I wanted to get was the path of a movie.
I tried to use dir(movie_object), vars(movie_object), and movie_object.__dict__ to try and find all of the movie attributes, and to see where the path was stored.
But there was no attribute that contained the file path information.
In the end I found it under movie_object.location by inspecting the object in the VSCode debugging tools.
Why does VSCode show the location attribute, but dir, vars, or __dict__ do not show it?
Is there a way to reliably get ALL of an objects attributes in python?
I've had a lot of issues getting information into and out of a list of classes that I've generated by iteration. In my latest project, I'm using PDF2image to open a pdf and store each page in a list of classes as well as a few other attributes unique to each page. My problem is that I have a really loose grip on how to handle data coming in and out of functions and particularly classes. Like in the following:
'class page():
def __init__(self, image, other_stuff)
Self. Image = image
Self. Other_stuff = otherPage_list = []
def pdfloader():
Pages = convert_from_bytes(path)
For page in pages:
Page_list.append(page(image = page, other_stuff = None))'
So like, in this example, I've appended 'page_list' with a new instance for each page that was pulled from the pdf and stored as an array. This works great. But now I have no idea how to access each instance to get the array, and then write 'other_stuff' to that instance.
(Also, sorry for the formatting, I'm writing this on mobile and I have to be in bed for work tomorrow. If it makes no sense, I'll take it down and re-post when I get the chance on desktop)
That reference isn't describing a special case of the language rules, it's a natural result of everything being an object.
The special case is that MyClass(args...) is wired up to create a new object and call MyClass.__init__ (among other things).
It allows you to change the state of the class after it is defined. This can be as simple as changing "static" data based on some configuration.
class EggsApiClient:
default_url = "example.com"
def connect(self):
# do stuff with default_url
if __name__ = "main":
EggsApiClient.default_url = parse_args("default_url")
This is not something that I think most Python users will ever need to do and almost surely shouldn't but it does have a distinct purpose and it's worth understanding.
Consider the following example:
class Foo:
def set_a(self, a):
self.a = a
class Bar:
def set_b(self, b):
self.b = b
foo = Foo()
foo.set_a(1)
print(foo.a)
bar = Bar()
# interesting part here!
Foo.set_a(bar, 2)
print(bar.a)
Through this feature, we have effectively called set_a on a Bar instance, despite the fact that Bar doesn't have a set_a method defined. That is, if we try:
bar.set_a()
We get an error: AttributeError: 'Bar' object has no attribute 'set_a'.
You might (quite reasonably) ask, "OK, but why would I do that?" Personally, I think I did something like this many moons ago but there was probably a simpler solution to whatever I was trying to accomplish.
I can imagine this be useful in various frameworks e.g. something like unit testing. But the main reason I think you might end up doing this is when you are using a more functional style. For example, you might have a function like this which has no knowledge of Foo or Bar:
def apply(obj, func, *params):
func(obj, *params)
Which you can then call like so:
apply(bar, Bar.set_b, 3)
print(bar.b)
A real example of the kind of thing you might actually do:
class Person:
def __init__(self, name: str, student: bool):
self.name = name
self.student = student
def is_student(self):
return self.student
def __repr__(self):
return f"{self.name} - student: {self.student}"
people = [Person("bob", False), Person("alice", True), Person("carl", True)]
def display(iter):
print("---")
for i in iter:
print(i)
display(people)
display(filter(Person.is_student, people))
Or maybe something like this:
people = map(Person, ["dave", "edith", "frank"], [True, False, True])
display(people)
Check out the functools module for more interesting functional-style approaches like this.