Reputation: 747
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
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
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 self
s in the process.
Upvotes: 6