Oftentimes, professors mistake Java for programming.

People are terrible and brains are rubbish. This is why we sometimes find ourselves sticking to what we know regardless of what's correct. People mistake common patterns in one language for common patterns in all, conflating their local scopes with globals, so to speak.

There are many examples of bad python practice that pop up regularly in dealing with new python programmers, some of which we'll go through here. Pretty much all of them are due to Java influenced source material, or just generally ignoring good python practices in favour of idioms from other languages.

Just like writing python patterns in other languages is stupid, writing other language's idioms in python is bad too.

For anyone thinking I'm about to shove PEP8 down their throats, or thinking I'm about to shove python idioms and patterns in their faces just like the very people I'm complaining about; I am not. I also am. But I also am not.

The benefit of teaching computer science through python is python's abstraction and relative simplicity. If that's ignored, you may as well use C or something. We'll take a classic anti-pattern as an example.


The Dishonorable "for i in range(len(some_iterable))"

To teach or learn array/list iteration is to deal with a concept, not an implementation. Let's say we want to talk about iterating a list and printing each element. A phrase like "to transverse a list in sequence, printing the value of each element as you go" is more useful in expressing the idea of list iteration, than:

for ( int i = 0; i < myArraySize; i += 1 ) {
	printf("%d\n", myArray[i]);
}

Following that, creating a C like index based version of list iteration in python like this:

for i in range(len(my_list)):
	print(my_list[i])
	

is still too far from the idea expressed in our simple phrase, and is more focused on an implementation the teacher is used to, or considers more "computer sciencey". (It's also inefficient and dumb.)

Python is expressive. Python reduces the disparity between concept and implementation. Here is how it should look:

for item in my_list:
	print(item)
	

If you're teaching a concept, lead with these simple pythonic implementations. If you want to show index based looping, just show it in C and compare them.

If you're on the learning side of this and you've been doing the range(len()) stuff, it's not your fault. Very seriously question the validity of your learning material though.

Also, for baby-budda's sake; if you have to do something involving index tomfoolery in python use enumerate().


Setters and Getters, no thank you.

Far too often, I see code like the following from people new to python, (and those with no excuse at all):

class SomeObject:
	def __init__(self, x=None):
		self.x = x

	def setX(self, x):
		self.x = x

	def getX(self):
		return self.x

a = SomeObject()

a.getX()
a.setX(True)

Aside from the camelCase which is a whole realm of crimes upon its self, it has getter and setter methods.

These are terrible. Python is a Big Boy and Big Girl language for adults, who are free to access an object's attributes as they like. By simply not heaping crap on top of it, the above code can be rewritten to be faster, more useful, and more readable.

class SomeObject:
	def __init__(self, x=None):
		self.x = x

a = SomeObject()

a.x
a.x = True

Calling a method to access or modify an object's attribute is insane. Leave it in Java. If you have to control how an attribute is accessed, learn to use @property.


_Private __Parts.

Python does not have public or private methods. It just has methods. The single leading underscore indicates internal use, not private use. It is used to avoid importing objects from a module when the module is * imported, so as to not pollute the importer's namespace.

_SOME_CONSTANT = 42
meaning_of_life = _SOME_CONSTANT

class SomeObject:
	def __init__(self):
		self.x = 'lol'
		self._y = 'wat'

Were you to * import the above file you would have access to meaning_of_life in your global namespace but not _SOME_CONSTANT. (You could explicitly import _SOME_CONSTANT if you wanted). Furthermore, the _ is indicating that the maintainer may change the value of _SOME_CONSTANT in the future.

You would have regular access to ._y just like you would .x. To reiterate: _prefacing is for indicating internal use and not ruining people's namespaces. It is not for the privatisation of objects.

Note that if you find yourself wanting to manually modify _prefaced things, you should probably just take the code and refactor it in such a manner that any internal reliance is safeguarded from your meddling.

Double leading underscore does something very different, and generally should be avoided at all costs. It's the closest thing python has to private, but it's still not private.

class SomeObject:
	def __init__(self):
		self.x = 'lol'
		self._y = 'wat'
		self.__z = 'wow'
	

Here, if you want to access __z, you have to reference it by _SomeObject__z, because for whatever terrible reason you've decided to implicitly obfuscate your code and make both you and your user's lives more miserable with no measurable gain.

Practically nobody uses this ever, and if you think your use case demands it you are probably wrong.

While we're at it, here's a link to a collection of anti-patterns.
	class RandomLang:
	    def __init__(self, patterns, kws, syntax, source):
	        self.patterns = patterns
	        self.kws = kws
	        self.syntax = syntax
	        self.source = source

	    def __contains__(self, x):
	        return True

	>>> python = RandomLang(**py_stuff)
	>>> javaPatterns = java.getIdioms()
	>>> javaPatterns in python
	True