How to avoid explicit 'self' in Python?
PythonSelfPython Problem Overview
I have been learning Python by following some pygame tutorials.
Therein I found extensive use of the keyword self, and coming from a primarily Java background, I find that I keep forgetting to type self. For example, instead of self.rect.centerx
I would type rect.centerx
, because, to me, rect is already a member variable of the class.
The Java parallel I can think of for this situation is having to prefix all references to member variables with this.
Am I stuck prefixing all member variables with self, or is there a way to declare them that would allow me to avoid having to do so?
Even if what I am suggesting isn't pythonic, I'd still like to know if it is possible.
I have taken a look at these related SO questions, but they don't quite answer what I am after:
Python Solutions
Solution 1 - Python
Python requires specifying self. The result is there's never any confusion over what's a member and what's not, even without the full class definition visible. This leads to useful properties, such as: you can't add members which accidentally shadow non-members and thereby break code.
One extreme example: you can write a class without any knowledge of what base classes it might have, and always know whether you are accessing a member or not:
class A(some_function()):
def f(self):
self.member = 42
self.method()
That's the complete code! (some_function returns the type used as a base.)
Another, where the methods of a class are dynamically composed:
class B(object):
pass
print B()
# <__main__.B object at 0xb7e4082c>
def B_init(self):
self.answer = 42
def B_str(self):
return "<The answer is %s.>" % self.answer
# notice these functions require no knowledge of the actual class
# how hard are they to read and realize that "members" are used?
B.__init__ = B_init
B.__str__ = B_str
print B()
# <The answer is 42.>
Remember, both of these examples are extreme and you won't see them every day, nor am I suggesting you should often write code like this, but they do clearly show aspects of self being explicitly required.
Solution 2 - Python
Previous answers are all basically variants of "you can't" or "you shouldn't". While I agree with the latter sentiment, the question is technically still unanswered.
Furthermore, there are legitimate reasons why someone might want to do something along the lines of what the actual question is asking. One thing I run into sometimes is lengthy math equations where using long names makes the equation unrecognizable. Here are a couple ways of how you could do this in a canned example:
import numpy as np
class MyFunkyGaussian() :
def __init__(self, A, x0, w, s, y0) :
self.A = float(A)
self.x0 = x0
self.w = w
self.y0 = y0
self.s = s
# The correct way, but subjectively less readable to some (like me)
def calc1(self, x) :
return (self.A/(self.w*np.sqrt(np.pi))/(1+self.s*self.w**2/2)
* np.exp( -(x-self.x0)**2/self.w**2)
* (1+self.s*(x-self.x0)**2) + self.y0 )
# The correct way if you really don't want to use 'self' in the calculations
def calc2(self, x) :
# Explicity copy variables
A, x0, w, y0, s = self.A, self.x0, self.w, self.y0, self.s
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
# Probably a bad idea...
def calc3(self, x) :
# Automatically copy every class vairable
for k in self.__dict__ : exec(k+'= self.'+k)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
g = MyFunkyGaussian(2.0, 1.5, 3.0, 5.0, 0.0)
print(g.calc1(0.5))
print(g.calc2(0.5))
print(g.calc3(0.5))
The third example - i.e. using for k in self.__dict__ : exec(k+'= self.'+k)
is basically what the question is actually asking for, but let me be clear that I don't think it is generally a good idea.
For more info, and ways to iterate through class variables, or even functions, see answers and discussion to this question. For a discussion of other ways to dynamically name variables, and why this is usually not a good idea see this blog post.
UPDATE: There appears to be no way to dynamically update or change locals in a function in Python3, so calc3 and similar variants are no longer possible. The only python3 compatible solution I can think of now is to use globals
:
def calc4(self, x) :
# Automatically copy every class variable in globals
globals().update(self.__dict__)
sqrt, exp, pi = np.sqrt, np.exp, np.pi
return ( A/( w*sqrt(pi) )/(1+s*w**2/2)
* exp( -(x-x0)**2/w**2 )
* (1+s*(x-x0)**2) + y0 )
Which, again, would be a terrible practice in general.
Solution 3 - Python
Actually self
is not a keyword, it's just the name conventionally given to the first parameter of instance methods in Python. And that first parameter can't be skipped, as it's the only mechanism a method has of knowing which instance of your class it's being called on.
Solution 4 - Python
You can use whatever name you want, for example
class test(object):
def function(this, variable):
this.variable = variable
or even
class test(object):
def function(s, variable):
s.variable = variable
but you are stuck with using a name for the scope.
I do not recommend you use something different to self unless you have a convincing reason, as it would make it alien for experienced pythonistas.
Solution 5 - Python
yes, you must always specify self
, because explicit is better than implicit, according to python philosophy.
You will also find out that the way you program in python is very different from the way you program in java, hence the use of self
tends to decrease because you don't project everything inside the object. Rather, you make larger use of module-level function, which can be better tested.
by the way. I hated it at first, now I hate the opposite. same for indented-driven flow control.
Solution 6 - Python
The "self" is the conventional placeholder of the current object instance of a class. Its used when you want to refer to the object's property or field or method inside a class as if you're referring to "itself". But to make it shorter someone in the Python programming realm started to use "self" , other realms use "this" but they make it as a keyword which cannot be replaced. I rather used "its" to increase the code readability. Its one of the good things in Python - you have a freedom to choose your own placeholder for the object's instance other than "self". Example for self:
class UserAccount():
def __init__(self, user_type, username, password):
self.user_type = user_type
self.username = username
self.password = encrypt(password)
def get_password(self):
return decrypt(self.password)
def set_password(self, password):
self.password = encrypt(password)
Now we replace 'self' with 'its':
class UserAccount():
def __init__(its, user_type, username, password):
its.user_type = user_type
its.username = username
its.password = encrypt(password)
def get_password(its):
return decrypt(its.password)
def set_password(its, password):
its.password = encrypt(password)
which is more readable now?
Solution 7 - Python
self is part of the python syntax to access members of objects, so I'm afraid you're stuck with it
Solution 8 - Python
From: Self Hell - More stateful functions.
> ...a hybrid approach works best. All of your class methods that actually do computation should be moved into closures, and extensions to clean up syntax should be kept in classes. Stuff the closures into classes, treating the class much like a namespace. The closures are essentially static functions, and so do not require selfs*, even in the class...
Solution 9 - Python
Actually you can use recipe "Implicit self" from Armin Ronacher presentation "5 years of bad ideas" ( google it).
It's a very clever recipe, as almost everything from Armin Ronacher, but I don't think this idea is very appealing. I think I'd prefer explicit this in C#/Java.
Update. Link to "bad idea recipe": https://speakerdeck.com/mitsuhiko/5-years-of-bad-ideas?slide=58
Solution 10 - Python
Yeah, self is tedious. But, is it better?
class Test:
def __init__(_):
_.test = 'test'
def run(_):
print _.test