1

I'm trying to learn OOP in Python but I'm confused about some parts.

class Song(object):

    def __init__(self, lyrics):
        self.lyrics = lyrics

    def sing_me_a_song(self):
        for line in self.lyrics:
            print line

    def print_x(self):
        print x

happy_bday = Song(["Happy birthday to you,",
               "I don't want to get sued",
               "So I'll stop right there"])

bulls_on_parade = Song(["They'll rally around the family",
                    "With pockets full of shells"])

happy_bday.sing_me_a_song()

bulls_on_parade.sing_me_a_song()

x = Song(4)

x.print_x()

print_x() returns:

<__main__.Song object at 0x7f00459b4390>

instead of 4. So I try adding x to the parameters for __init__ and print_x, and changing print x to print self.x in the print_x function plus adding self.x = x to init, but it returns this:

TypeError: __init__() takes exactly 3 arguments (2 given)

I honestly don't know what's gone awry here. But any help would be hugely beneficial to me finally understand OOP.

3
  • 1
    You're confusing the scopes of these variables. Local variables and instance variables are completely different things. Commented Mar 16, 2015 at 5:21
  • You have to pass value of x at the time of creating instance. something like happy_bday = Song(["Happy birthday to you,", "I don't want to get sued", "So I'll stop right there"], 'x-value') Commented Mar 16, 2015 at 5:26
  • What exactly should print_x return? Commented Mar 16, 2015 at 5:52

2 Answers 2

3

This is less an OOP issue and more of a scoping issue. Lets examine a very cut down version.

class Song(object):
    def __init__(self, lyrics):
        self.lyrics = lyrics

    def print_x(self):
        print x

From here we instantiate x (in the local scope):

>>> x = Song(4)

Now, before we do anything, lets examine x:

>>> print x.lyrics
4

The reason is that when you called Song(4) the value 4 is determined to be lyrics by its position.

And when we call print_x:

>>> x.print_x()
<__main__.Song object at 0x7f00459b4390> # Or some other memory address

The reason is that the only x that Python is aware of is the local x we just made.

What happens when we start again and make y:

>>> y = Song(4)
>>> print y.print_x ()
NameError: global name 'x' is not defined

No x exists to print and it throws an exception.

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

1 Comment

Despite the acceptance - I think there's a typo here. You say that print y.lyrics will throw the NameError, but I think that will be fine. I think the point you're trying to make is that y.print_x() will throw the NameError.
0

I think you are trying like

def __init__(self, lyrics, x):
    self.lyrics = lyrics
    self.x = x
...
def print_x(self):
    print self.x

By this way it will produce TypeError: init() takes exactly 3 arguments (2 given)

You can find the error from this. When you creating Song instance like

happy_bday = Song(["Happy birthday to you,",
           "I don't want to get sued",
           "So I'll stop right there"])

You have to pass the value of x to the __init__().Thats why the error is showing.This can done by

 happy_bday = Song(["Happy birthday to you,",
           "I don't want to get sued",
           "So I'll stop right there"],
            'x-value')

OR Set default value for x

def __init__(self, lyrics, x="default value"):
    self.lyrics = lyrics
    self.x = x

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.