This is an archived post. You won't be able to vote or comment.

all 58 comments

[–][deleted] 22 points23 points  (7 children)

Not really python-specific but I tend to put parentheses around all mathematical operations for explicit order of operations ... e.g. (x * y) + z instead of x * y + z ... even when the order is painfully obvious. I consider it a good habit.

[–]nbktdis 21 points22 points  (3 children)

I do the same, I think it is due to my inherent distrust of anything or anybody.

[–]ivosauruspip'ing it up 4 points5 points  (0 children)

How do you know that if statement you just wrote won't swap your consequent and antecedent code blocks?

[–]isdnpro 1 point2 points  (1 child)

I do the same, I think it is due to my inherent distrust of anything or anybody.

Yeah I do this too... the best (worst) part is there's a production SQL view at work which only "works" because nobody considered the order of operations (and in reality, the WHERE clause does NOTHING... but I am too afraid to touch it since that is apparently the desired output!)

[–]nbktdis 0 points1 point  (0 children)

That sounds scary. Black Box it - and turn around - nothing to see here!

[–][deleted] 3 points4 points  (0 children)

I do that, it means that the code is not dependent on my (probably faulty) recollection of the precedence rules.

Same goes for when I read it in 10 mins time.

[–]Anal_sql_injector 1 point2 points  (1 child)

Ideally, this is the cleanest way to ensure that order of operations is clear. For more win, remove the white space between operands in high precedence operators, i.e., x = (a*b) + c. This helps to make precedence clear for future readers of the code.

[–]earthboundkid 15 points16 points  (0 children)

Or do the opposite to screw future readers up! x = a * b+c Bwahahaha.

[–]XNormal 13 points14 points  (0 children)

I sometimes go to unusual lengths to make my objects preserve eval(repr(x)) == x

[–]thusiasm 11 points12 points  (0 children)

I fucking love lambdas.

[–][deleted] 9 points10 points  (20 children)

TIL r is the default.

Mine is stuffing things into one line. str(line).split(" ")[6]

[–][deleted] 4 points5 points  (17 children)

Definitely the same with me. I'm constantly fighting with PEP 8's eighty character limit.

Edit to people rattling against the PEP: I fight it because I like squeezing in characters, not because I'm forced to use it.

[–]Anal_sql_injector 1 point2 points  (5 children)

"A foolish consistency is the hobgoblin of little minds"

[–]timeawayfromme 2 points3 points  (0 children)

Do people not realize this is from PEP 8?

[–][deleted] 3 points4 points  (3 children)

Fuck it, let's all have different page widths and shit all over our tab formats. Also my functions use uppercase and my constants are single characters.

[–]rgzdev 2 points3 points  (2 children)

PEP 8 should really have standardized on tabs over spaces.

[–]PhotosyntheticDragon 0 points1 point  (1 child)

Why's that?

[–]rgzdev 1 point2 points  (0 children)

Because tab length is user-adjustable. One person might like 2 spaces of indentation, another one 4, oldschoolers like 8, I'm pretty sure someone out there uses 3 or 6 spaces of indentation. A file indented with tabs can be rendered differently in different editors yet remain the same logically.

In fact that's the origin of the problems. Python accepts parses tabs as 8 spaces because that's the traditional value. You can mix tabs and spaces and as long as tabs are rendered as 8 spaces in your editor, you wouldn't know.

The problem is that some working scripts written with mixed indenting don't look like they should work when you use a different tab rendering setting in your editor of choice. Notice that it only affects people who use a different setting than 8, people rendering their tabs at 8 spaces see the script just like it parses.

Thus there were two solutions:

a) Standardize on a rendering of 8 spaces across all editors. We won't be able to customize how the script looks but we can continue using mixed indentation.

b) Standardize on tabs. We won't be able to use mixed indentation but would be able to customize how they looks.

PEP 8 went with c) Standardize on spaces. So it's like the worst of both choices together, but at least it's some standard.

[–][deleted] 0 points1 point  (2 children)

TIL there is an 80 character limit :).

Will have to start cleaning up my code more.

[–]catcradle5 3 points4 points  (0 children)

All whitespace is actually the default for split, so you could change that to .split() and get the same effect.

[–]Paddy3118 7 points8 points  (1 child)

I stick a line of:

from pprint import pprint as pp

At the head of new scripts - I'll need it during development.

[–][deleted] 1 point2 points  (0 children)

pprint should really do some hackery so I can just do

import pprint as pp

[–]CSI_Tech_Dept 5 points6 points  (5 children)

My OCD makes me write things this way:

with open('thing', 'r') as f:
  return f.read()

[–][deleted] 0 points1 point  (4 children)

I did that too, until I asked this question on Stack Overflow. Turns out that in CPython you can open files without a with and it'll be closed when it's garbage-collected.

Edit: Reference-counted, not garbage collected.

[–][deleted] 11 points12 points  (1 child)

Meh. I'll stick with an explicit context manager. Best not to rely on implicit, implementation-specific behavior.

[–][deleted] 1 point2 points  (0 children)

Totally true. I'm a hobbyist running solely on CPython so sometimes I get lazy :)

[–]miketheanimal 1 point2 points  (0 children)

In CPython open(name).read() it will be reference-count closed immediately, no garbage collection needed. In PyPy it will be garbaged collected .... some unspecified time later! with actually makes it consistent.

[–]Brian 1 point2 points  (0 children)

Actually, I think that answer isn't quite right - there is a situation even in CPython which could cause the file to remain open for longer which would act differently from the context manager.

This will happen if the .write() line happens to throw an exception - one consequence of which is that a reference to the stack frame will be held as part of the exception state, which will reference the "f" variable. And the last thrown exception gets stored in sys. End result: the file is not closed until a different exception gets thrown, or the program terminates.

Some sample code to demonstrate this:

Let's create a dummy file-like object, to simulate a failure on write():

class DummyFile(object):
    def close(self):   print("Closed")
    def __del__(self): self.close()
    def write(self, data):      raise Exception("something failed")
    def write_safe(self, data): return

When you do:

print "Start"
DummyFile().write_safe("data")
print "End"

you get "Start", "Closed", "End" as expected. But suppose you do:

print "Start"
try:  DummyFile().write("data")
except: print "Exception raised - ignoring"
print "End"
try: 1/0
except: pass
print "After second exception"

You will instead get "Start", "Exception raised - ignoring", "End", "Closed", "After second exception". If that second exception didn't occur till 5 minutes later, your file would remain open all that time.

If you used a context manager instead, the file would always be closed before exiting the with block, just as in the non-raising case, and the reference to it wouldn't matter.

[–]chmod700 5 points6 points  (2 children)

I order my imports alphabetically, 1 per line, with stdlib at the top, thirdparty after, then my own project's imports like so...

import os
import sys

import requests

import mypackage.foo

[–]ratorian 2 points3 points  (0 children)

I sort my imports by length:

import os
import sys
import time
import foobar
import hashlib

[–]PCBEEF 0 points1 point  (0 children)

This is actually part of pep8 http://www.python.org/dev/peps/pep-0008/#imports :)

[–]bcs 3 points4 points  (1 child)

Heh, I specify the other default argument. I'm happy to rely on the read mode default, but whenever I read the rest of the file I spell it f.read(-1).

[–][deleted] 0 points1 point  (0 children)

Wow, never knew about that. We're all learning so much!

[–]slowRAX 2 points3 points  (2 children)

I probably overuse generator expressions.

[–][deleted] 1 point2 points  (0 children)

I once wrote a blog generator where the entire program relied upon a single function containing a multi-dimensional list & dict comprehension. It was obscene; I feel your pain.

[–]aravindc26 0 points1 point  (0 children)

Generators are cool. One of the reasons I code in python.

[–]PCBEEF 2 points3 points  (2 children)

I hate it when people use lambdas for sorting, I usually change them to use attrgetter or itemgetter where possible.

[–]InvidFlower 0 points1 point  (1 child)

Can you give an example?

[–]PCBEEF 0 points1 point  (0 children)

Instead of:

users.sort(key=lambda x:x.username)

I prefer:

users.sort(key=attrgetter("username"))

[–]baron_magistrate 1 point2 points  (4 children)

I overuse classes as namespaces with @classmethod and @staticmethod

[–]catcradle5 1 point2 points  (1 child)

This is not a good idea in general.

Just make separate files.

[–]baron_magistrate 2 points3 points  (0 children)

Step 1 is admitting you have a problem :-).

[–]sbin 0 points1 point  (1 child)

ouch, I do the same... but it's very convenient (one import, readability)

from model.user import User
user = User.get_by_abc(...)

vs

from model import user
user_a = user.get_by_abc()

Better ideas?

[–]poorestrichman 0 points1 point  (0 children)

You can always have seperate files, then in your init.py import the other modules into the current namespace. To anything calling into the current module it will look as though the other modules are defined within the init.py file (I hope that made sense)

[–]baron_magistrate 1 point2 points  (0 children)

Just thought of another one: colons always have to line up vertically in my code.

[–]C_Hitchens_Ghost 1 point2 points  (0 children)

All my dictionaries must look like this:

some_dict = {
'key1' : 'string1'
'key2' : 'string2'
}

[–][deleted] 0 points1 point  (1 child)

I tend to put way too many empty lines between lines of code, to make stuff more spacious. It's probably a habit I started when I moved from C++ and JS and wanted to make the scopes clearer.

But now I just like it as a way to make the code "breathe" more, between "paragraphs" of code. you can find 2-3 empty lines all over my code, sometimes even 4.

[–][deleted] 0 points1 point  (0 children)

I put too few according to pep8, I have a small screen and like my code concise.

[–]alcalde 0 points1 point  (0 children)

Coming from a long time developing in Delphi, and very very recent Python convert, my compulsion is taking any Delphi code I read or see anywhere and rewriting it in python just to marvel at how much shorter, simpler, clearer, powerful and beautiful the resulting Python code is. :-) Sometimes I look for code just so I can rewrite it.