2

I am learning python, step-by-step. Today is about Object Oriented Programming. I know how to create and use simple classes, but something bugs me. Most of the objects I use in python do not require to call a constructor

How can this works? Or is the constructor called implicitly? Example:

>>> import xml.etree.ElementTree as etree    
>>> tree = etree.parse('examples/feed.xml')  
>>> root = tree.getroot()                    
>>> root
<Element {http://www.w3.org/2005/Atom}feed at cd1eb0>

(from http://www.diveinto.org/python3/xml.html#xml-parse)

I would have gone this way (which actually works):

>>> import xml.etree.ElementTree as etree 
>>> tree = etree.ElementTree() # instanciate object
>>> tree.parse('examples/feed.xml')

I'd like to use this way of programming (do not call constructor, or at least call it implicitly) for my own project, but I can't get how it really works.

Thanks

3
  • 2
    The .parse() function creates an object for you. Functions can do that; do stuff then return the result. Why is that surprising? Commented Jun 20, 2013 at 14:22
  • If somebody comes here looking for the answer to the question's title, that's easy; create a subclass which overrides __init__ with an empty method. Commented Jun 20, 2013 at 14:28
  • This won't directly answer your question, but applies to Python Programming as a whole and classes. Classes have what are called magic methods. __init__ is one, but there are many others. You should look into the __call__ method, which relates to your question and what you want to do, even though you won't be able to do it with a factory function. rafekettler.com/magicmethods.html#callable Commented Jun 20, 2013 at 14:32

4 Answers 4

6

etree.parse is a Factory function. Their purpose is mainly to be convenient ways of constructing objects (instances). As you can easily verify by looking at the source, the parse function does almost exactly as you do in your second example except it ommits a line of code or two.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, I actually looked at the source but settled on the .parse() method of ElementTree class hg.python.org/cpython/file/2.7/Lib/xml/etree/… which confused me because it does not instanciate any object.
@CJlano That's the main difference between the method that you looked at and the function that mgilson linked to. A method is already bound to an instance: that's what the self parameter means. A function, on the other hand, sits at the module level and is not implicitly given a reference to an object instance, so it must create one if one is needed.
@HenryKeiter : in Python a method is not necessarily bound to an instance - it can also be classmethod (very useful for alternate constructors), a staticmethod, or even an unbound instancemethod (in which case you have to explicitely pass the instance).
@brunodesthuilliers Yes, yes. I'm trying not to bog him down with details that aren't relevant to his question, though.
2

In this case, what's happening is that the etree.parse() function is creating the ElementTree object for you, and returning it. That's why you don't have to call a constructor yourself; it's wrapped up in the parse function. That function creates an ElementTree instance, parses the data and modifies the new object to correctly represent the parsed information. Then it returns the object, so you can use it (in fact, if you look at the source, it does essentially what you wrote in your second example).

This is a pretty common idiom in object-oriented programming. Broadly speaking, it's called a factory function. Basically, especially for complex objects, a lot of work is required to create a useful instance of the object. So, rather than pack a lot of logic into the object's constructor, it's cleaner to make one or more factory functions to create the object and configure it as needed. This means that someone developing with the library may have several clean, simple ways to instantiate the class, even if "under the hood" that instantiation may be complex.

Comments

1

In the first case, you are calling a helper function from the module. Its not a class method (though internally it might create an object and then call its method). In the second case, you are instantiating an object and then calling its method.

Comments

1

For a class named ClassName, calling ClassName() implicity calls __init__() and returns you a new instance of ClassName.

If __init__ is not defined in ClassName, the super's __init__ will be called.

In your case, this is all inside a function:

def name(foo):
    return ClassName(foo)

n = name("bar") # a function call returns a new instance

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.