Matteo NNZ
Matteo NNZ

Reputation: 12665

When instantiating a class, what is the difference between with and without parentheses/brackets?

Say I have a very simple class like the following:

class myClass:
    def __init__(self): 
        self.myProp = 2

If I instantiate using the parentheses/brackets, everything works as I expect:

>>> a = myClass()
>>> a.myProp
2

However, if I don't use the parentheses/brackets on the two lines above, i.e.:

>>> a = myClass

I get the following error:

>>> a.myProp
Traceback (most recent call last):
File "<pyshell#45>", line 1, in <module>
a.myProp
AttributeError: class myClass has no attribute 'myProp'

If I print the object,

>>> a = myClass
>>> a

I get

<class __main__.myClass at 0x0275C538>

It seems that a is an instance of the class, but somehow is not initialized.

In other languages, I would expect a compile error if trying to cast a class instance into an object without initalizing it (e.g. in C#, myClass a = new myClass(); would work fine but myClass a = new myClass; would return a compile error).

So my question is: what is, technically speaking, the object a = myClass without parentheses/brackets?

Upvotes: 16

Views: 9272

Answers (3)

mgilson
mgilson

Reputation: 309939

a is the class itself -- In python, classes are first class objects1. You can pass them around as parameters, alias them to different names (as you've done in your example) and then you can instances from any reference that you have in the current namespace.

a = myClass  # a and myClass identical at this point.  The interpretter won't care which you use.
a_instance = a()  # instance of myClass

def make_instance(cls):
    return cls()

another_instance = make_instance(a)
yet_another_instance = make_instance(myClass)

You see, python doesn't have any "compile time checking" because really -- there is no compile time. Python code gets interpreted at runtime. True, you can have SyntaxErrors pop up at when you import something, but that is still during runtime.

1No pun intended

Upvotes: 15

wkschwartz
wkschwartz

Reputation: 3877

Everything in Python is an object and thus an instance of a class, including classes. There is nothing special about manipulating classes or passing them around as variables. Thus your variables a and MyClass, which refer to the same object, are just the object that is MyClass.

>>> class R: pass # In Python 2, you would need class R(object): pass
>>> r = R()

Now we have two variables, R and r. r is an instance of class R. The trick here is that R is an instance of class type, which is why we call R a class. Both r and R are instances of object, which is why we call both of them objects. And R is a subclass of class object because R is a class.

>>> isinstance(R, type)
True
>>> isinstance(r, R)
True
>>> issubclass(R, object)
True
>>> isinstance(r, object)
True
>>> isinstance(type, object)
True
>>> isinstance(type, type)
True

Every Python object is an instance of object and every Python class is a subclass of object and every Python class is an instance of type.

Note that what I'm saying is true in Python 3 and for Python 2 "new style" classes. Do not concern yourself with Python old-style classes.

Upvotes: 3

Jessamyn Smith
Jessamyn Smith

Reputation: 1649

It's a reference to the class itself, rather than a reference to an instance of the class. Note the difference:

>>> a = myClass
>>> a
<class __main__.myClass at 0x10cd1de20>
>>> b = myClass()
>>> b
<__main__.myClass instance at 0x10cd8efc8>

Upvotes: 11

Related Questions