1

I have this code:

class Pet(object):

    def __init__(self,name=""):
        self.name = name 
        self.kind = "Unknown"
        self.toys = []  
    def add_toys(self,toys):
        new_list = []
        for toy in self.toys:
            if toy not in new_list:
                new_list.append(toy)   
        return new_list
    def __str__(self):
        toys_list = add_toys(self,toys)  
        if self.toys == []:
            return "{} is a {} that has no toys".format(self.name,self.kind)
        else:
            return "{} is a {} that has the following toys: {}".format(self.name,self.kind,toys_list)     

In the function add_toys() I have the return value new_list. I want to use that return value in the function __ str__ and define it as toys_list. However, when I write toys_list = add_toys(self, toys) it says that:

add_toys is an undefined variable

2
  • 2
    I am not fully sure what you are trying to achieve, but for the error where you say "it says that add_toys is an undefined variable.", I believe you need self.add_toys. Commented Apr 10, 2021 at 13:26
  • Does this answer your question? function name is undefined in python class Commented Apr 10, 2021 at 13:36

4 Answers 4

4

Your add_toys method isn't good, you're not using the toys parameters and it shouldn't return anything, it should be like

class Pet:
    # __init__ is OK

    def add_toys(self, *toys):
        for toy in toys:
            if toy not in self.toys:
                self.toys.append(toy)

    def __str__(self):
        if not self.toys:
            return "{} is a {} that has no toys".format(self.name, self.kind)
        else:
            return "{} is a {} that has the following toys: {}".format(self.name, self.kind, self.toys)

Use like

p = Pet("Foo")
p.add_toys("ball")
p.add_toys("plate", "frisbee")
print(p) # Foo is a Unknown that has the following toys: ['ball', 'plate', 'frisbee']

You could use directly a set

class Pet:

    def __init__(self, name, kind="Unknown"):
        self.name = name
        self.kind = kind
        self.toys = set()

    def add_toys(self, *toys):
        self.toys.update(toys)
Sign up to request clarification or add additional context in comments.

Comments

0

First thing in add_toys you are accesing toys variable from the class level variable, so remove that argument and the second is add_toys(self,toys) is not correct syntax, you will need to use it like self.add_toys()

class Pet(object):
    def __init__(self,name=""):
        self.name = name
        self.kind = "Unknown"
        self.toys = []
    
    def add_toys(self):
        new_list = []
        for toy in self.toys:
            if toy not in new_list:
                new_list.append(toy)
        return new_list
    
    def __str__(self):
        toys_list = self.add_toys()
        if self.toys == []:
            return "{} is a {} that has no toys".format(self.name, self.kind)
        else:
            return "{} is a {} that has the following toys: {}".format(self.name, self.kind, toys_list)

Alternative:

class Pet(object):
    def __init__(self,name=""):
        self.name = name
        self.kind = "Unknown"
        self.toys = []
    
    def add_toys(self, toys):
        new_list = []
        for toy in toys:
            if toy not in new_list:
                new_list.append(toy)
        return new_list
    
    def __str__(self):
        toys_list = self.add_toys(self.toys)
        if self.toys == []:
            return "{} is a {} that has no toys".format(self.name, self.kind)
        else:
            return "{} is a {} that has the following toys: {}".format(self.name, self.kind, toys_list)

Comments

0

Issue is the undefined function. A referencing self (needed for each class member, field or method) was missing: toys_list = self.add_toys().

Reconsider design

Why have the collection of toys managed twice? (a) as field toys wich can have duplicates, (b) as return from add_toys which will hide duplicates and ensures unique elements.

You will have to maintain both in sync. They differ in their capabilities and should be applied to different use-cases.

Assumption: unique toys

I would also go with a set as type for the field toys directly. Because this way you can reuse an existing data structure which guarantees the uniqueness you have implemented explicitly in add_toys. Additionally the add/update function is convenient to modify the collection.

Improve: string building

Furthermore your string function can be refactored:

def __str__(self):
    subject = "{} is a {}".format(self.name, self.kind)
    hasToys = "has no toys" if not self.toys else "has the following toys: {}".format(self.toys)
    return "{subject} that {hasToys}".format (subject, hasToys)

it uses a ternary operator instead of the if statement; with referencing (via self!) new set field directly: self.toys Plus a 3 step building to allow the single return as clearly visible expectation at the end.

Comments

-1

you can't call class method directly, you must call it using self.

like this ..

self.toys_list= self.add_toys(self, toys)

2 Comments

Can't we omitt the first argument self when inside the class: self.add_toys( toys ) ?
yes, we can omitt that first argument ` self` , but i am talking about that self. which comes before method name, any method or variable under a class can't call directly, it leads to undefined error. we must have to call it using self. like self.method_name() and self.variable_name ..

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.