I'm relatively new to python and oop, and i have a question around the design of my code for a hobby project.
I created a lot of variables in my main program. These variables are lists of objects (not configuration parameters and not constants). The objects in the lists are sprites.
I'm passing these variables around between objects, by calling methods and passing the variables around as arguments for a specific method. (pass-by-reference)
For example:
spritelist = [Sprite(...), Sprite(..)]
mycollisiondetector = CollisionDetector()
mycollisiondetector.check_collision(spritelist)
Then, in class CollisionDetector, spritelist is passed to "private" methods of the class. These private methods call other methods, and keep passing spritelist ... .
So, my question is just this: is there an alternative for endlessly passing variables around from one method to another ?
If you're dealing with instance variables (not configuration constants), it's considered bad practice to separate the variables into a module (a different file), since you're mixing instance state and global state.
If you have many references being passed around repeatedly, this is usually a indicator of bad class hierarchy design. You may want to consider subclassing, or defining a new class for your variables and passing a reference to it. The details will depend on your specific situation - it's hard to tell without seeing the code.
Related
When there is a long function, how to limit the scope of variables within only a section of the function? I know in many languages one can do this with {}. How to do this in python?
I am aware that a separate function for just that section will encapsulate variables to its local namespace. But for a long, linear function, many people argue that it does not make sense to write many functions (and thus names) that are only called once.
Generally speaking, you can't. Python only creates scopes for modules (files, generally), classes, and functions; variables can have a more limited lifetime only in a few special cases, like the target_list in a list comprehension in Python 3. There's no block-level scope like in Perl.
So, your possible workarounds are:
Create single-use functions or classes. The function would have to be called, whereas the class would never have to be named again after its definition, because class definitions are executed immediately.
del variables when you're done with them.
Fun fact: coming to terms with this limitation of Python is what finally got us to get rid of let in Hy, because there's no way to make it work as one would expect. Update 5 years later: yet another version of let is implemented, and the way it works is by implementing our own entire system for tracking the scopes of variables, and enforcing it by issuing compile-time errors and adding nonlocal and global when needed. I guess there are no shortcuts here.
What is the good practice in Python when I need to initialize an objects that contains, for example, big array and it should be filled with calculated values during the object creation. Is it ok in Python to do this inside constructor or this is like a code-smell and I should use Factory instead? What is the Pythonic way here?
If you can initialize the array in a couple of lines of clear code then it's quite ok to initialize it directly in the __init__ method. Otherwise, initialize it in a separate method.
Python does have static methods and class methods (see here for some simple examples). You could use a static method to initialize your array, but if the initializer method uses attributes of the instance in its calculation you may as well make it a normal method, otherwise you'll need to pass it those values as parameters.
Python doesn't have private methods, but it's conventional to indicate that a method is for private use of the class by giving it a name that starts with a single leading underscore, eg _init_my_array. If a user of your class wants to call that method they can, but they know that doing so may cause the class to misbehave, and that it's generally not a good idea to call such "private" methods unless you know what you're doing.
Suppose I have an instance method that contains a lot of nested conditionals. What would be a good way to encapsulate that code? Put in another instance method of the same class or a function? Could you say why a certain approach is preferred?
If the function is only used by one class, and especially if the module has more classes with potentially more utility functions (used only by one class), it might clarify things a bit if you kept the functions as static methods instead to make it obvious which class they belong to. Also, automated refactorings (using the e.g. the rope library, or PyCharm or PyDev etc) then automatically move the static method along with the class to wherever the class is moved.
P.S. #staticmethods, unlike module-level functions, can be overridden in subclasses, e.g. in case of a mathematical formula that doesn't depend on the object but does depend on the type of the object.
There are two different questions here. The first one is what to do with multiple nested conditionals. There's no single right answer: it depends on your coding style, how the conditions interact, the architecture of your program and so on. Have a look at this Programmers.SE question and Jeff Atwood's blog post for some ideas; personally, I like
if not check1: return
code1
if not check2: return
code 2
...
although some people object to the multiple exit points.
The second question is what to do with individual functions if you're writing object oriented Python. The usual answer is just to put them as functions inside the module containing the class, since there's no requirement that a function be attached to a particular class. If you want, though, you can include them in the class as static methods.
Are classes necessary for creating methods (defs) in Python?
No. However, def's which aren't part of a class are usually called functions, not methods - but they are exactly the same thing, aside from not being associated with a class.
def myFunction(arg1, arg2):
# do something here
No, you can create functions using def without having to wrap them in classes.
If you are coming from a Java or C# background - where a class is required - you may want to read over An Introduction to Python: Functions or a similar article to understand how to work with functions in Python, as the language provides many other features such as first-class functions, returning multiple values, anonymous functions, etc.
It depends on your definition of "method".
In some sense, no, classes aren't necessary for creating methods in Python, because there are no methods anyway in Python. There are only procedures (which, for some strange reason, are called functions in Python). You can create a procedure anywhere you like. A method is just syntactic sugar for a procedure assigned to an attribute.
In another sense, yes, classes are necessary for creating methods. It follows pretty much from the definition of what a method is in Python: a procedure stuck into a class's __dict__. (Note, however, that this means that you do not have to be inside a class definition to create method, you can create a procedure anywhere and any way you like and stick it into the class afterwards.)
[Note: I have simplified a bit when it comes to exactly what a method is, how they are synthesized, how they are represented and how you can create your own.]
I'm a C++ programmer just starting to learn Python. I'd like to know how you keep track of instance variables in large Python classes. I'm used to having a .h file that gives me a neat list (complete with comments) of all the class' members. But since Python allows you to add new instance variables on the fly, how do you keep track of them all?
I'm picturing a scenario where I mistakenly add a new instance variable when I already had one - but it was 1000 lines away from where I was working. Are there standard practices for avoiding this?
Edit: It appears I created some confusion with the term "member variable." I really mean instance variable, and I've edited my question accordingly.
I would say, the standard practice to avoid this is to not write classes where you can be 1000 lines away from anything!
Seriously, that's way too much for just about any useful class, especially in a language that is as expressive as Python. Using more of what the Standard Library offers and abstracting away code into separate modules should help keeping your LOC count down.
The largest classes in the standard library have well below 100 lines!
First of all: class attributes, or instance attributes? Or both? =)
Usually you just add instance attributes in __init__, and class attributes in the class definition, often before method definitions... which should probably cover 90% of use cases.
If code adds attributes on the fly, it probably (hopefully :-) has good reasons for doing so... leveraging dynamic features, introspection, etc. Other than that, adding attributes this way is probably less common than you think.
pylint can statically detect attributes that aren't detected in __init__, along with many other potential bugs.
I'd also recommend writing unit tests and running your code often to detect these types of "whoopsie" programming mistakes.
Instance variables should be initialized in the class's __init__() method. (In general)
If that's not possible. You can use __dict__ to get a dictionary of all instance variables of an object during runtime. If you really need to track this in documentation add a list of instance variables you are using into the docstring of the class.
It sounds like you're talking about instance variables and not class variables. Note that in the following code a is a class variable and b is an instance variable.
class foo:
a = 0 #class variable
def __init__(self):
self.b = 0 #instance variable
Regarding the hypothetical where you create an unneeded instance variable because the other one was about one thousand lines away: The best solution is to not have classes that are one thousand lines long. If you can't avoid the length, then your class should have a well defined purpose and that will enable you to keep all of the complexities in your head at once.
A documentation generation system such as Epydoc can be used as a reference for what instance/class variables an object has, and if you're worried about accidentally creating new variables via typos you can use PyChecker to check your code for this.
This is a common concern I hear from many programmers who come from a C, C++, or other statically typed language where variables are pre-declared. In fact it was one of the biggest concerns we heard when we were persuading programmers at our organization to abandon C for high-level programs and use Python instead.
In theory, yes you can add instance variables to an object at any time. Yes it can happen from typos, etc. In practice, it rarely results in a bug. When it does, the bugs are generally not hard to find.
As long as your classes are not bloated (1000 lines is pretty huge!) and you have ample unit tests, you should rarely run in to a real problem. In case you do, it's easy to drop to a Python console at almost any time and inspect things as much as you wish.
It seems to me that the main issue here is that you're thinking in terms of C++ when you're working in python.
Having a 1000 line class is not a very wise thing anyway in python, (I know it happens alot in C++ though),
Learn to exploit the dynamism that python gives you, for instance you can combine lists and dictionaries in very creative ways and save your self hundreds of useless lines of code.
For example, if you're mapping strings to functions (for dispatching), you can exploit the fact that functions are first class objects and have a dictionary that goes like:
d = {'command1' : func1, 'command2': func2, 'command3' : func3}
#then somewhere else use this list to dispatch
#given a string `str`
func = d[str]
func() #call the function!
Something like this in C++ would take up sooo many lines of code!
The easiest is to use an IDE. PyDev is a plugin for eclipse.
I'm not a full on expert in all ways pythonic, but in general I define my class members right under the class definition in python, so if I add members, they're all relative.
My personal opinion is that class members should be declared in one section, for this specific reason.
Local scoped variables, otoh, should be defined closest to when they are used (except in C--which I believe still requires variables to be declared at the beginning of a method).
Consider using slots.
For example:
class Foo:
__slots__ = "a b c".split()
x = Foo()
x.a =1 # ok
x.b =1 # ok
x.c =1 # ok
x.bb = 1 # will raise "AttributeError: Foo instance has no attribute 'bb'"
It is generally a concern in any dynamic programming language -- any language that does not require variable declaration -- that a typo in a variable name will create a new variable instead of raise an exception or cause a compile-time error. Slots helps with instance variables, but doesn't help you with, module-scope variables, globals, local variables, etc. There's no silver bullet for this; it's part of the trade-off of not having to declare variables.