Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is __init__ always required?

Okay. So I saw someone using this code, and I understand it, I so I'm going to use it. Is it necessary to have __init__?

class A(object):
    def __init__(self):
        self.x = 'Hello'

    def method_a(self, foo):
        print self.x + ' ' + foo

a = A() 
a.method_a('Sailor!')

Couldn't I just do something like this:

class A(object):
    def method_a(self):
        print "Hello, Sailor!"

a = A()
print a.method_a()

When I do do this, I do get the "Hello, Sailor!" but I get a "None" right below it? Does that have to do with the __init__? Someone explain.

like image 809
jped Avatar asked Mar 24 '14 04:03

jped


2 Answers

What you're asking doesn't have much to do with __init__. You can do what you say in your second example, but it doesn't do the same thing as the first example.

In the first example, it prints "Hello" followed by an argument that you pass to the method. You can make it print something besides "sailor" by passing something else in:

>>> a.method_a('buddy!')
Hello buddy!

In the second example, it always prints "Hello, Sailor!" and you can't make it print anything else.

As for __init__, in your example, the __init__ is not that useful, because all it does is set an attribute x that is the same string for each object. You should use __init__ if you want to "set up" each object as you create it. In your example, this setup is not that interesting because it's always the same for every object. You don't have to use __init__, but there's usually not much point in creating objects that don't have some sort of individual state attached to them. Here is a more illustrative example:

class Greeter(object):
    def __init__(self, greeting):
        self.greeting = greeting

    def greet(self, who):
        print self.greeting + ", " + who + "!"

Then you can do this:

>>> hello = Greeter("hello")
>>> hello.greet('sailor')
hello, sailor!
>>> howdy = Greeter('Howdy')
>>> howdy.greet('partner')
Howdy, partner!

Here, when you create a Greeter, you specify the greeting. That greeting is stored with the object, and used whenever it greets someone. The point of the __init__ is that you can make multiple greeters with different greetings.

Notice that I still pass in the person to greet when I call greet. So the greeting (hello or howdy in this example) is set when I create the object, but the person to greet is specified anew each time I use the object to greet.

Generally you will mix these two kinds of things in your code. Some pieces of information are "part of the object" and you will handle them in __init__ and store them on the object. Others are more specific or transitory information that you will pass in as function arguments for each task you want to do. The balance between these depends on what the class is supposed to do, but the above example should illustrate the difference.

Also, neither of these has anything to do with why you see "None" printed. dr_jimbob has explained why that happens.

like image 182
BrenBarn Avatar answered Nov 15 '22 07:11

BrenBarn


You can safely leave out __init__ if you do not need to set any attributes or do any other initialization to the object when it is created. The reason you get None is there's no return type to your method_a(). So when you print it, you get None.

If you had:

class A(object):
    def method_a(self):
        return "Hello, Sailor!"
a = A()
print a.method_a()

You will not see the None (as method_a returns a string) and then later you call print on the string to display it.

Or if you had:

class A(object):
    def method_a(self):
        print "Hello, Sailor!"
a = A()
a.method_a()

This time calling method_a prints the string, but since you aren't printing this result (just calling it) you don't see a None displayed.

like image 41
dr jimbob Avatar answered Nov 15 '22 07:11

dr jimbob