0

I'm learning Python, mainly through the MIT OpenCourseWare project. I'm trying to do problem 2 of assignment 9 here.

It has a shell of code that simply has the class and def headers with comments. I added the actual code below

class ShapeSet:
    def __init__(self):
        """
        Initialize any needed variables
        """
        self.set1=[]
        set1=self.set1

    def addShape(self, sh):
        """
        Add shape sh to the set; no two shapes in the set may be
        identical
        sh: shape to be added
        """
        self.set1=[]
        set1=self.set1
        a=True
        for x in set1:
            if x==sh:
                a=False
        if a:
            set1.append(sh)
        return set1
        print(set1[:])

There is code above this that creates classes for the different shapes. It's giving me no problems so I didn't include it. This is my first time doing OOP so I have a few questions.

  1. In IDLE, I say s=ShapeSet() to create an instance. I have to do this each time because otherwise it disappears and I get a NameError that 's' is not defined. Why doesn't it persist?

  2. Probably related to that, I can successfully use addShape to add a shape once, but the set never contains more than one shape, no matter how many I try to add.

  3. You see that I have set1 defined in there twice. If I just put it in __init__, like I assumed I should do, I get an error that set1 is not defined. Why would it be undefined if it's in init? Related, I was always confused about how things are named in classes. Why do people always rename x=self.x? Is it OK to just call it set1 to begin with and avoid the self.set1?

martineau
  • 119,623
  • 25
  • 170
  • 301
Joe
  • 13
  • 5
  • Why you redefine `set1=self.set1`? You should simply use `self.set1`. And the reason you can't add more than one shape is because you initialize the set with `self.set1=[]`. The whole purpose of `__init__` is to hold this kind of initializations – Tomerikoo Jan 10 '20 at 00:55
  • Please take this as a constructive comment as I do not intend it to be criticism. I think you are going about learning Python in the wrong way. It makes no sense to work on tutorials until you understand how the language works. The answers to all of your questions are related to how the "class" statement works and what it means. You need to understand classes, the `__init__` function, the use of "self" and the rules defining variable scope. If your course hasn't exposed you to those concepts, use a different course. If it has, keep reading about them until it makes sense. – Paul Cornelius Jan 10 '20 at 01:12
  • Tomerikoo: I did that because I always see self.a or self.b set to just a or b in other people's code. Was never quite sure why they did that. Paul: I always appreciate advice, but I have read up on Python, online tutorials and books as well. I think it's best to do both coding and reading at the same time. It's hard to remember all the rules without using them. – Joe Jan 10 '20 at 01:29

2 Answers2

1

There is no need to do set1 = self.set1 just use self.set1.

When you run s = ShapeSet() you are initializing the class, which runs the code under def __init__(self): during this, you set self.set1 = [], an empty list.

This would be a great opportunity for you to read up on self and __init__ in a class. There is a great StackOverflow question covering this;

__init__ and self

Python Constructors

Your code works fine, so long as you change all your calls to set1 to self.set1 and only initialize the class once.

class ShapeSet:
    def __init__(self):
        """
        Initialize any needed variables
        """
        self.set1=[]

    def addShape(self, sh):
        """
        Add shape sh to the set; no two shapes in the set may be
        identical
        sh: shape to be added
        """

        a=True
        for x in self.set1:
            if x==sh:
                a=False
        if a:
            self.set1.append(sh)
        return self.set1
        print(self.set1[:])

>>> s = ShapeSet()
>>> s.addShape('Square')
['Square']
>>> s.addShape('Circle')
['Square', 'Circle']
>>> s.addShape('Square')
['Square', 'Circle']
martineau
  • 119,623
  • 25
  • 170
  • 301
PacketLoss
  • 5,561
  • 1
  • 9
  • 27
  • Thanks, that seems to work. I thought I saw people setting something like x=self.x often in their classes. Maybe I was thinking of methods though? – Joe Jan 10 '20 at 01:32
0
  1. Every time you press run in IDLE, all variables are cleared so that your program has the same behaviour every time and runs in a clean session.

  2. The first two lines of your addShape function seem to have been copied by mistake from __init__ and they reset the list to be empty.

  3. When you declare multiple functions, they don't have access to variables defined in other functions. Both of these functions have access to self because they are passed it as an argument. But when you declare set1 = self.set1 you create a local variable that is destroyed when the function returns. You can read more about variable scope here

Simon Crane
  • 2,122
  • 2
  • 10
  • 21