0

I'm working on a python assingment involving creating and using a class with several methods. I won't post the whole thing as it'll be simpler to point out my issue if I instead show an example of what I'm trying to do.

class Fruit(self,color,name):
    def __init__(self, color, name):
        self.color = color
        self.name = name

    def return_list(self, index):
        print fruit_list[index]

fruit_list = []

fruit_1 = Fruit("red", "apple")
fruit_list.append(fruit_1.color) 
fruit_list.append(fruit_1.name)

So the above code works. My issue is getting return_list to work when used outside of the class, as so:

fruit_choice = int(raw_input("What fruit would you like?"))
Fruit.return_list(fruit_choice)

Basically I'm trying to create a method that when called, outputs the item at an index within a list, the index being specified by user input (i.e fruit_choice = 0, printed item is first element of list.)

I have a basic understanding of classes, but getting a somewhat vague method to work like return_list is a little unintuitive. The error message I get:

Fruit.return_list(fruit_choice)
TypeError: unbound method return_list() must be called with Fruit instance as first argument (got int instance instead)

I know that if I got the code to work the output would be "red" if input was 0 instead of "red,"apple", but that's an issue for another time.

If someone could point out to me what I'm doing wrong in creating/calling the return_list method, please and thanks.

Cyanidies
  • 57
  • 1
  • 2
  • 9
  • `Fruit.return_list(fruit_choice)` should be `fruit_1.return_list(fruit_choice)`. You have to attach the method to an instance (that's what the message says). But after that it won't work because `fruit_list` is not a member of the class (and it should not be because you don't want a fruit list in your fruit object!). Learn OO programming some more... – Jean-François Fabre Sep 04 '16 at 11:04

3 Answers3

1

Basically you are calling an instance method without an instance that's why you are getting this error

    TypeError: unbound method return_list() must be called with Fruit instance as first argument (got int instance instead)

The corrected code

    fruit_1.return_list(fruit_choice)

The way you are doing is the behaviour of static methods, they are called without an instance. Please go through some oops programming like instance methods and static methods in python.

Hope it helps :)

Sunil Lulla
  • 797
  • 10
  • 18
0

You seem to have a misunderstanding of Classes and class instances.

The return_list function you have defined is part of the Fruit class, i.e. each instance of the Fruit class contains this method. But the use of this function, which is to return a specific fruit from fruit list, is independent of the individual Fruit instances, which means this method should not have been in the Fruit class in the first place.

The signature of class definition class Fruit(self,color,name) is wrong. It should be class Fruit:. The initial parameters should be defined as parameters to the __init__ method.

The list fruit_list should contain Fruit instances. The program could be written as:

class Fruit:
    def __init__(self, color, name):
        self.color = color
        self.name = name

    def __str__(self):
        return 'I am a ' + self.color + ' ' + self.name

fruit_list = []

fruit_1 = Fruit("red", "apple")
fruit_list.append(fruit_1)

fruit_choice = int(raw_input("What fruit would you like?"))
print(fruit_list[fruit_choice])

Printing a Python object calls the __str__ magic method.

If you do really want to have a separate function which returns a Fruit from the fruit_list, you can define a function outside the class (but these seem unnecessary when you can directly access the instance using the index):

def return_list(list, index):
    return list[index]

or

def return_list(index):
    global fruit_list
    return fruit_list[index]

If you try to print the entire list using print(fruit_list) the output is:

[<__main__.Fruit instance at 0x110091cf8>]

That is because Python does not call __str__ on each instance when you print a list of instances. You can print the fruit_list by doing:

for fruit in fruit_list:
    print(fruit)
Ananth
  • 4,227
  • 2
  • 20
  • 26
  • Thanks, that helps me a lot. If I wanted to show the whole list, how would I do that? Just putting [:] as an index or having no [] at all doesn't seem to work.(referring to your first block of code) – Cyanidies Sep 04 '16 at 12:45
0

Here's a possible solution to your problem:

class Fruit():

    def __init__(self, color, name):
        self.color = color
        self.name = name

    def __str__(self):
        return "Color: {0} Name: {1}".format(self.color, self.name)


class FruitBasket():

    def __init__(self):
        self.fruits = []

    def get_fruit(self, index):
        try:
            value = self.fruits[index]
            return value
        except Exception as e:
            print "Error with index {0} -> {1}".format(index, e)

if __name__ == "__main__":
    basket = FruitBasket()
    names = ["apple", "orange", "lemon"]
    colors = ["green", "orange", "yellow"]

    for name, color in zip(names, colors):
        fruit = Fruit(color, name)
        basket.fruits.append(fruit)

    print basket.get_fruit(0)
    print basket.get_fruit(1)
    print basket.get_fruit(2)
    basket.get_fruit(3)

Few comments about the above code:

  • Fruit object doesn't have more responsabilities than setting up a fruit with a certain name & color, that's pretty much. One fruit shouldn't contain any list of fruits, that should be the responsability of another object
  • FruitBasket is the container of fruits, you could do perfectly this without using OOP but for the sake of this question, this is a valid option to hold many fruits

With respect to your error, the other answers and comments are already pointing out what's wrong. Also, about class Fruit(self,color,name):, don't do that, in that sentence you're declaring the class type, not the constructor.

I'd strongly recommend you try to follow some of the many OOP python tutorials out there.

BPL
  • 9,632
  • 9
  • 59
  • 117