Ryan
Ryan

Reputation: 747

Python: Am I using "self" correctly?

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")

Upvotes: 0

Views: 186

Answers (2)

ShadowRanger
ShadowRanger

Reputation: 155403

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

Upvotes: 3

John Zwinck
John Zwinck

Reputation: 249153

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.

Upvotes: 6

Related Questions