python代码编写过程中有一些习惯写法,Bad和Good是对相同代码的不同表示,其中Good是python中通用的代码编写规范。
Bad
|
Good
|
x=5 if ( (x==8) and (y>5) ) : ... 1<<5&2 return(5); while (x<5) : ... 7. |
x = 5 if x == 8 and y > 5: ... (1 << 5) & 2 return 5 while x < 5: ... 7.0 |
print x,x*x+1 v[i + 1 + a] + v[i + 2 + b] |
# Sometimes rules can be broken, for # example to show grouping better: print x, x*x + 1 v[i+a+1] + v[i+b+2] |
def Function ( x ): ... | def function(x): ... |
class fooclass: ... | class Fooclass(object): ... |
d = dict() | freqs = {} # Descriptive names are often better # But in small scopes a short name may be fine |
list = [1, 2, 3] dict = {'alpha': 0x1234} sum = x + y |
# Don't shadow builtin names values = [1, 2, 3] symbol_address = {'alpha': 0x1234} tot = x + y |
"some string" and 'some string' and """some string""" and '''some string''' are the same string. |
|
mapping = { 5 :"5", 6:"6" } | mapping = {5: "5", 6: "6"} |
mapping = {5 : "5", 6 : "6"} if mapping.has_key(6): ... |
mapping = {5: "5", 6: "6"} if 6 in mapping: ... |
def function( x, l = [] ): ... | # Generally don't use mutables as a default def function(x, items=None): ... if items is None: items = [] |
if x == None: ... | if x is None: ... |
x = 1 if z > 5: var1 = 55 |
# Always use 4 spaces as indent # (Or always a Tab, but it's less good) x = 1 if z > 5: var1 = 55 |
mapping = {5 : "5", 6 : "6"} for key, val in mapping.items(): ... for key in mapping.keys(): ... |
# Use iter* methods when possible mapping = {5: "5", 6: "6"} for key, val in mapping.iteritems(): ... for key in mapping: ... |
for i in range(10, 20000): ... | for i in xrange(10, 20000): ... |
# Use to denote the code that has to # run when a module is executed and not # imported: if __name__ == '__main__': |
|
# Python profiler: python -m profile -o stats myscript.py >>> import pstats >>> p = pstats.Stats('stats') >>> p.sort_stats('time').print_stats(15) |
|
For source code with not 7-bit ASCII add this on top: # -*- coding: UTF-8 -*- # Or just, if you have less memory: # coding: latin |
|
al = [1, 2, 3] for i in xrange(len(al)-1, -1, -1): del al[i] |
items = [1, 2, 3] del items[:] # But often if speed isn't critical you # can just use (but this is a different # thing, this creates a new list): items = [] # If you just want to remove one refence # to the list: del items |
repeat xxx until yyy |
# Equals to: while True xxx if yyy: break |
# To add a zip file containing modules # to the search path: sys.path.append("some.zip") |
|
a = 5 b = 6 aux = a a = b b = aux |
a = 5 b = 6 a, b = b, a # swap |
if x < 10 and x > 2: ... | if 2 < x < 10: ... |
a = 5 b = 5 c = 5 |
a = b = c = 5 |
if x == 1: y = fun1(x) else if x == 2: y = fun2(x) else if x == 3: y = fun3(x) else: y = None |
if x == 1: y = fun1(x) elif x == 2: y = fun2(x) elif x == 3: y = fun3(x) else: y = None # But sometimes a dict is better: funs = {1: fun1, 2: fun2, 3: fun3} y = funs.get(x, lambda x:None)(x) |
mapping = {5 : "5", 6 : "6"} for key in mapping.iterkeys(): ... |
mapping = {5: "5", 6: "6"} for key in mapping: ... |
al = [1, 2, 3] for i in xrange(len(al)): print al[i] |
al = [1, 2, 3] for el in al: print el |
al = [1, 2, 3] for i in xrange(len(al)-1, -1, -1): print al[i] |
al = [1, 2, 3] for el in reversed(al): print el |
class Test(object): def __init__(I, x): ... |
class Test(object): def __init__(self, x): ... |
# Compute the sum of the ... def sum_of(x, y, z): ... |
def sum_of(x, y, z): ... """Compute the sum of the ...""" |
from operator import add sl = ["ab", "cd", "ef"] all = "" for s in sl: all += s # Or: sl = ["ab", "cd", "ef"] all = reduce(lambda x,y: x+y, sl, "") |
sl = ["ab", "cd", "ef"] all = "".join(sl) |
a = "this isn't a word, right?" a = a.replace("'", " ") a = a.replace(".", " ") a = a.replace("?", " ") a = a.replace(",", "") |
# .replace can be fine. This is faster: from string import maketrans tab = maketrans("'.?", " ") a = "this isn't a word, right." afilt = a.translate(tab, ",") |
values = ["stop",0,0] | values = ["stop", 0, 0] |
def mul(x, y): return x*y l = [2, 3] print apply(mul, l) |
def mul(x, y): return x * y l = [2, 3] print mul(*l) |
vals = [2, 3, -5, 0] result = [] for el in vals: if el > 0: result.append(el * el) |
vals = [2, 3, -5, 0] result = [el * el for el in vals if el > 0] |
l = [0] * 4 m = [l] * 4 m[1][1] = 5 print m |
# One correct way to create a matrix: m = [[0] * 4 for _ in xrange(4)] m[1][1] = 5 print m |
a = 1 print a / 2, a / float(2) |
# A kind of alternative: from __future__ import division a = 1 print a // 2, a / 2 |
class Foo(object): def __init__(self, x, y, z): self.x_public = x self.y_private = y self.z_veryprivate = z def getx(self): return self.x_public print Foo(1, 2, 3).getx() |
# Generally getters and setters are not used. |
finder = re.compile("^s*([[]])s*([-+]?d+) s*,s*([-+]?d+)s*([[]])s*$") |
finder = re.compile(r""" ^ s* # start at beginning+ opt spaces ( [[]] ) # Group 1: opening bracket s* # optional spaces ( [-+]? d+ ) # Group 2: first number s* , s* # opt spaces+ comma+ opt spaces ( [-+]? d+ ) # Group 3: second number s* # opt spaces ( [[]] ) # Group 4: closing bracket s* $ # opt spaces+ end at the end """, flags=re.VERBOSE) # Sometimes it's positive to indent logically those # lines just like code. # Sometimes it can be positive to compose REs: spaces = r"s*" # optional spaces number = r"( [-+]? d+ )" # Group bracket = r"( [[]] )" # Group. Closing bracket parts = ["^", bracket, number, ",", number, bracket, "$"] finder = re.compile(spaces.join(parts), flags=re.VERBOSE) |
def function(data): """A comment""" ...implementation... |
# Use doctests (or module tests): def function(data): """A comment >>> function() if __name__ == "__main__": |
x = (1, 2, 6, 55, 63, 96, 125, 256, 301, 456, 958, 1256, 1359, 2568, 3597) |
x = (1, 2, 6, 55, 63, 96, 125, 256, 301, 456, 958, 1256, 1359, 2568, 3597) # Too much long lines must be broken with # but isn't necessary inside () [] {} |
from Tkinter import * from mymodule import * |
import Tkinter as tk from mymodule import fun1, Class1, baseconvert as bc |
import psyco psyco.bind(myfun1) a = [3.56, 2.12] |
try: import psyco # Psyco classes may be very useful from psyco.classes import __metaclass__ psyco.bind(myfun1) except ImportError: pass # Using psyco array.array of double and # signed long become very fast import array a = array.array("d", [3.56, 2.12]) # In some situations arrays of chars too are fast # psyco can be slow with itertools, map, filter # and generators, but fast with list # comprehensions. For max speed with Psyco # use low level coding style. |
# to print strings without spaces between: from sys import stdout stdout.write(string1) stdout.write(string2) |
|
This is good enough: words = ['me', 'do' 'bye', 'taz', 'foo', 'bar'] A shorter, more readable, but slower alternative: words = 'me do bye taz foo bar'.split() |
|
# sorting on the second item of the tuple # try to remove the i index from the temporary tuples lp = [(5J,"b"),(2J,"c"),(3+1J,"a"),(1+2J,"a")] lp2 = [(c, i, n) for i,(n, c) in enumerate(lp)] lp2.sort() print [(n, c) for (c, i, n) in lp2] |
from operator import itemgetter lp = [(5J, "b"), (2J, "c"), (3+1J, "a"), (1+2J, "a")] print sorted(lp, key=itemgetter(1)) |
vals = [5, 7 ,8] tot = -2.0 for v in vals: tot += v |
vals = [5, 7 ,8] tot = sum(vals, -2.0) |
ll = [[1, 2, 3], [4], [5, 6]] print sum(ll, []) |
data = [[1, 2, 3], [4], [5, 6]] result = [] for sublist in data: result.extend(sublist) # Or even, for max speed from itertools import imap data = [[1, 2, 3], [4], [5, 6]] result = [None] * sum(imap(len, data)) pos = 0 for sublist in data: lensl = len(sublist) result[pos : pos+lensl] = sublist pos += lensl |
print "%s %s" % (string1, string2) print '"' + chr(c) + '":', freq[c] |
print string1, string2 print '"%c": %d' % (c, freq[c]) |
[' ', c][c.isalpha()] | # For Python V.2.5+: (c if c.isalpha() else ' ') |
# How to invert string, lists, etc. alist[::-1] astring[::-1] |
|
# To negate (inplace) each second # element of alist: result = [] for (i, v) in enumerate(alist): # faster than i % 2 if i & 1 == 0: result.append(v) else: result.append(-v) alist[:] = result |
from operator import neg alist[1::2] = map(neg, alist[1::2]) # Or a bit slower but easier to read: alist[1::2] = [-el for el in alist[1::2]] |
# To shallow copy a list or dict: # (tuples don't need to be copied) newlist = list(alist) newdict = dict(adict) # Or just: newlist = list[:] |
|
import sys sys.exit() |
# To stop a console program: raise SystemExit #Or just: exit() |
if type(s) == type(""): ... if type(seq) == list or type(seq) == tuple: ... |
if isinstance(s, basestring): ... if isinstance(seq, (list, tuple)): ... # Or even: if hasattr(seq, "__getitem__"): ... # But quite often in dynamic languages you # don't test types, you just use them (look # for duck typing), catching exception that # may occur. |
name1 = 5; name2 = 20; print name2 a = 1 b = 2 c = 3 |
name1 = 5 name2 = 20 print name2 a, b, c = 1, 2, 3 |
prima = 1 rossa = "Il colore rosso" léger = 30 |
# English only for names: first = 1 red = "Il colore rosso" light = 30 |
__del__ method of classes is usually left undefined. |
|
try: fin = file("absent_file.txt") except: ... try: something() except: ... |
# Generally specify what exception to catch: try: fin = file("absent_file.txt") except IOError: ... try: something() except someException: ... |
except ImportError, IOError: ... | except (ImportError, IOError): ... |
bytes = array.array('B', [0] * nbytes) # Or: from itertools import repeat bytes = array.array('B', repeat(0, nbytes)) |
# This can be much faster bytes = array.array('B', [0]) * nbytes |
freqs = {} for c in "abracadabra": try: freqs[c] += 1 except: freqs[c] = 1 |
# Short way: freqs = {} for c in "abracadabra": freqs[c] = freqs.get(c, 0) + 1 # Often the fastest way: freqs = {} for c in "abracadabra": if c in freqs: freqs[c] += 1
else:freqs[c] = 1 # Or better with Python 2.5+: from collections import defaultdict freqs = defaultdict(int) for c in "abracadabra": freqs[c] += 1 |
someitems = set([1, 2, 3]) |
someitems = set([1, 2, 3]) somemap = {1: 2, 3: 4, 5: 6} print iter(someitems).next() print iter(somemap).next() |
from time import clock | # This works well on Windows and Linux: from timeit import default_timer as clock # Or often use the timeit module |