0

I'm new to Python and am only now starting to see the uses of self and would like to know if I am using it correctly. I have some sample code below and was wondering if someone could just skim through and see if it's the correct usage. I'm not sure if it's correct because I seem to be needing to use self a lot but perhaps that is just the style of the language. Thank You

Code

from tkinter import Canvas

class BouncyBall:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.d = 15
        self.color = 'blue'
        self.speed = 2
        self.move_left = False
        self.move_right = False

    def __init__(self, x, y, d, color):
        self.x = x
        self.y = y
        self.d = d
        self.color = color
        self.speed = 2
        self.move_left = False
        self.move_right = False

    #Accessor Methods
    def get_x(self):
        return self.x
    def get_y(self):
        return self.y
    def get_diameter(self):
        return self.d
    def get_color(self):
        return self.color
    def get_speed(self):
        return self.speed
    def moving_right(self):
        return self.move_right
    def moving_left(self):
        return self.move_left

    #Mutator Methods
    def set_x(self, x):
        self.x = x
    def set_y(self, y):
        self.y = y
    def set_diameter(self, d):
        self.d = d
    def set_color(self, color):
        self.color = color
    def set_speed(self, speed):
        self.speed = speed
    def set_move_right(self, move_right):
        self.move_right = move_right
    def set_move_left(self, move_left):
        self.move_left = move_left

    def draw_ball(self, canvas):
        if isinstance(canvas, Canvas):
            canvas.create_oval(self.x, self.y, self.x + self.d, self.y + self.d, fill=self.color)
        else:
            print("Improper Parameter Sent In")
9
  • 2
    You shouldn't be writing getters and setters in Python. Commented Mar 18, 2017 at 4:57
  • @juanpa.arrivillaga How else would I get/change the values? Or are the self variables public? Commented Mar 18, 2017 at 4:59
  • 1
    I believe they're always public. Commented Mar 18, 2017 at 5:00
  • 1
    There are no access modifiers in Python, i.e. there is no "public" and "private". Everything is accessible directly. Commented Mar 18, 2017 at 5:00
  • 1
    Technically, an instance attribute that begins with double underscores (and doesn't end with underscores) is "private", in that automatic name mangling occurs so you don't accidentally use it outside the class's methods. It's trivial to bypass that mangling (by doing it yourself), so it's not a security feature, it's just a convenient way to namespace privates so a subclass can't accidentally stomp on them. Commented Mar 18, 2017 at 5:09

2 Answers 2

6

You are using self correctly. It does tend to appear a lot in Python compared with other languages like C++ where the this parameter is implicit.

However, in Python it is not conventional to write get() and set() methods for everything, as you have done. You can reduce your code quite a bit by removing those--and remove a lot of selfs in the process.

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

Comments

3

Well, first off your __init__ is wrong. Python doesn't allow two definitions of a function/method with the same name in the same namespace, whether or not the prototype differs. I'd suggest dropping your first definition, and changing the def line of the second to:

def __init__(self, x=0, y=0, d=15, color='blue'):

which will do what you wanted (allow you to initialize without arguments by using default values).

You also probably want to drop all your set_ and get_ methods. If the attributes are read/write, just access them normally without getters and setters. If at some later point you need to make them read-only, or compute them, you can rename the attribute to have a leading underscore (e.g. _x) and use @property decorators to continue providing attribute-like access (with or without writability). That would instantly remove the vast majority of (unnecessary) accessor and mutator methods that make you reference self so often. For example, if x should be read-only, you'd set self._x = x in your __init__, then define a property:

@property
def x(self):
    return self._x

and users would continue to read it as if it were a simple attribute, they just couldn't write it by accident (they could directly write _x, but that's their problem; Python's philosophy is that we're all adults, and if you ignore the convention that underscore prefixes are internal implementation details, the consequences are on your head).

Otherwise, yes, you'll be referencing self a lot. Python prefers explicit namespacing to implicit, so you use self to differentiate between instance access and scoped variable access. If you are going to be using a given variable a lot (and it won't change during the course of a method), you can cache it to a local name and use the local name unqualified, e.g.:

 def some_method(self):
     # We use x a lot and never change it, so cache up front:
     x = self.x

     # Can read cached x over and over without qualification for rest of method

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.