Curious2learn
Curious2learn

Reputation: 33628

How to find attributes of a python user-defined class?

Please see the following example code, which is in a file, say

classattr.py

class BaseClass(object):
    def __init__(self, param1, param2):
        self.param1 = param1
        self.param2 = param2

    def somemethod(self):
        return "This is returned when I do Base.__dict__"

class ChildOfBaseClass(BaseClass):
    def __init__(self, param1, param2, param3, param4):
        super(ChildOfBaseClass, self).__init__(param1, param2)
        self.param3 = param3
        self.param4 = param4

    def somemethod(self, param3, param4):
        a = param3 + param4
        return a

I want to get all the attributes (I am assuming that param1, param2 etc. are called attributes) of the classes before I create any instance. Command dir(classattr.BaseClass) does not list param1 and param2. It, however, does return the method somemethod.

I am trying to get the attributes for the following reason: The module classattr is imported in another file where the name of the class, either classattr.BaseClass or classattr.ChildOfBaseClass is provided as an input to some function. I want to determine which one it is during the runtime and then use appropriate inputs (either param1 and param2 if the former, or all the parameters param1 to param4 if the latter) when creating the instance. The way I was thinking of doing this is to check whether the class has param3 as an attribute and then creating the instance with correct inputs. Is there another better way to check? Another way is to have param3 and param4 as inputs in BaseClass even if they do not do anything and then always create instance with all four parameters as inputs. But that does not seems appropriate way of doing things.

Thank you.

Upvotes: 0

Views: 1908

Answers (3)

kindall
kindall

Reputation: 184181

There's no real way to get the names of attributes that are only assigned after the object is created, such as those defined in __init__(), without actually creating the instance. The __init__() method can do anything at all, and an instance might have been even further amended by code that's not even in the class. So if you want to know what attributes an instance has, you need an instance.

Upvotes: 2

Ben
Ben

Reputation: 71450

BrenBarn's answer directs you to some ideas that might help you solve your problem. I just thought I'd add some notes on terminology.

In Python, the attributes of an object are the named values stored within it (and an object is pretty much nothing more and nothing less than "a thing that has attributes"). They are retrieved with the dotted.name syntax.

Classes in Python are objects. They therefore have attributes. The most important ones are all the names that you defined in the class block (including the methods), which become attributes of the class object. So when you ask about the attributes of a class, it sounds like you're wanting to retrieve the attributes of the class object itself, which is not actually the case.

Indeed one of the things dir(classattr.BaseClass) is doing is looking up the attributes of classattr.BaseClass, where it finds the somemethod attribute, but does not find param1 or param2 because they are not attributes of the class object BaseClass; they (will be) attributes of instances of BaseClass once those instances have been created and initialised.

But what you really seem to be asking about is how to find out the call signature of the __init__ method of a given class. As noted by BrenBarn, although classes are often written to simply directly initialise their instances' attributes from the arguments to __init__, there is absolutely no guarantee that this is the case. But if your purpose is just to know what information to pass to a class in order to create an instance, then you don't need to know (and shouldn't care) what will end up being stored as attributes, but rather just what are the required parameters to the __init__ method.

Upvotes: 1

BrenBarn
BrenBarn

Reputation: 251383

You can't know what instance attributes a class will give to its instances, because they don't exist before an instance is created.

However, if what you want is to know what parameters you need to pass when instantiating the class, you can inspect the call signature of the class's __init__ method to see what parameters it accepts. See Determining the number of parameters in a lambda for some information about getting the call signature.

Note that there's no inherent relationship between instance attributes and __init__ parameters. You could have a class like this:

class Foo(object):
    def __init__(self):
        self.someAttr = 10

. . . which defines an instance attribute without receiving any parameters. (Or vice versa, a class that accepts parameters but doesn't use them to create instance attributes.)

Upvotes: 2

Related Questions