Monday, March 10, 2014

Python Style: Refrain from Setting/Getting Instance Variables Outside your Class

Overview
Instance Variables can cause some really bad stuff to happen in your program, but they're basically necessary to have in any class to keep track of the state of an object. Even worse is that there are no private variables in python. Because of this, it's especially important to make sure your programs have setters and getters, as well as naming your variables in a way that prevents other classes/programs from accessing them directly.

What Are Getters?
Getters are just methods in your class that return the variable, or variation of the variable, that the user wants. They allow you to send the variable to whoever asks for the variable on your terms. For example, lets say a person asks for data of a user. In your database, you've stored the user object with a password that you don't want others to see. So, when someone calls your method, you return them all of the info except the password.

Getters also allow you to keep track of anyone who asks for the variable. Lets say you want to find all of the referred methods that call your getter. You can set a console.log to print out the stack trace every time the method is called. This would allow you to go through your log files later and see where your getter was called from.

What Are Setters?
Setters are very similar to Getters, but instead are used to set the variables in your class. They are very useful for making sure variables are set correctly, providing extra info into your variables, and seeing who's set your variables.

Setters make sure variables are set correctly because you're able to add extra checking to make sure the variables don't become corrupt. For example, lets say you have a bank app that stores dict objects. These dict objects look like this: {'deposit': 500}. Lets say a user decided to just add a dict object like this: {'deposit': 'foo'}. 'foo' is not a number, so the program is likely to crash. If you have a setter, you can check the key and value of the dict and make sure each are valid when being set, and, if they aren't, send a nicely-worded error message back to the user.

Setters can also provide extra, very useful data into your variables. Lets say you want to add a deposit, and you want to also record when that deposit was made. Well, you don't really want to trust the user to pass in the proper timestamp, because he can send a made up timestamp. So, in your method you record the time the method was called in the variable, so the variable would look like this: {'deposit': 500, 'time_created': 523423423}

Setters allow you to see who has set your variables. Like in the getters example, you can set a console.log to log a stacktrace to see everywhere your method was called.

Debugging Reasons
One of my favorite reasons is for Debugging. If someone sets the variable directly, its very hard to track down where it happened. You can grep all your files, but if it came from some other source, then you are not going to have much luck. If you have setters and getters, you can set a pdb.set_trace() in those methods and see every time you get the value and you set the value.

Creating your Instance Variables Correctly
Anyone can change any variable in your class, but most people don't. If you follow the PEP8 Guide, you can be sure that the fewest number of programmers try to change your instance variables. To do this, add an underscore before your variable name, like this: _var_name. This is the syntax to say that variable is "private". If you want to make it really hard on programmers trying to screw things up, put 2 underscores before your variable name, like this: __var_name. This obfuscates the variable, making it harder for people to change it.

Conclusion
Setters and Getters are always a good idea. Use them.

References:

  • http://stackoverflow.com/questions/1641219/does-python-have-private-variables-in-classes

NOTE: Please note that I am not an expert at this topic and this info can certainly be improved. If you have questions, comments or suggestions for this blog post, please comment! Also, this guide is currently in rough draft form. If you would like it to be more in depth, I will be extremely happy to improve on this, all you need to do is ask in the comments and I will do it asap (I just don't want to spend forever on something no one reads and/or cares about).

No comments :

Post a Comment