この記事の内容は、Python の一般的に使用される PEP8 の仕様と Python のテクニックです。必要な友達はこの記事の内容を参照してください
英語の原文についてはここをクリックしてくださいPEP8 コーディング仕様
以下は@bobo の編集、原文 PEP8 Python コーディング標準編成
コード配置
インデントをご覧ください。 4 スペースのインデント (すべての編集者がこの機能を実行できます)、Tap は使用せず、Tap とスペースを混合することはできません。モジュール内容の順序: モジュールの説明と docstring -インポート -グローバルと定数 -その他の定義。インポート部分は、標準、サードパーティ、自作の順に空白行を挟んで配置されています
さまざまな閉じ括弧の前のスペース。
if/for/while ステートメントでは ';' の使用が許可されていますが、実行ステートメントが 1 文だけであっても、同じ行に複数のステートメントを記述しないでください。新しい行
原則として、間違ったコメントはコメントがないより悪いです。したがって、コードの一部が変更された場合、最初に行うことはコメントを変更することです。コメントは英語で記述し、最初の文字を大文字にして完全な文章にする必要があります。文の後にはターミネータが必要で、ターミネータの後には次の文を開始する 2 つのスペースが必要です。フレーズの場合、ターミネータは省略できます。
コメント、コードの前に追加されたコメントをブロックします。 「#」の後にスペースを追加します。段落は「#」のみの行で区切る必要があります。例:
# Description : Module config.# # Input : None## Output : None
行コメント。コード行の後にコメントを追加します。例: x = x + 1 # Increment x
ただし、この方法はできるだけ使用しないでください。
不必要なコメントは避けてください。
ドキュメントの説明
すべてのパブリックモジュール、関数、クラス、およびメソッドの docstring を記述します。非パブリックなものは必要ありませんが、コメントを (def の次の行に) 記述できます。
単一行コメントについては、次の方法を参照してください
def kos_root(): """Return the pathname of the KOS root directory.""" global _kos_root if _kos_root: return _kos_root ...
命名規則
* 原則として、新しいコードは次の命名スタイルと既存のコードに従ってコンパイルする必要がありますライブラリは可能な限りスタイルを維持する必要があります。大文字の「i」と大文字の「o」* を単独で使用しないでください。モジュール名はできるだけ短くし、すべて小文字を使用し、アンダースコアを使用してください。
all
メカニズムで、もう 1 つはアンダースコアを接頭辞として付けます。関数名はすべて小文字を使用し、アンダースコアも使用できます。
プログラミングの提案
コーディングの際には、他の Python 実装の効率やその他の問題を考慮してください。たとえば、演算子「+」は CPython (Python) では非常に効率的ですが、Jython では非常に効率が低くなります。したがって、 .join() メソッドを使用する必要があります。
尽可能使用‘is’‘is not’取代‘==’,比如if x is not None 要优于if x
使用基于类的异常,每个模块或包都有自己的异常类,此异常类继承自Exception。
常中不要使用裸露的except,except后跟具体的exceptions。例如
try: ...except Exception as ex: print ex
异常中try的代码尽可能少。
使用startswith() and endswith()代替切片进行序列前缀或后缀的检查。
foo = 'abc000xyz'if foo.startswith('abc') and foo.endswith('xyz'): print 'yes'else: print 'no'#yes#而如下的方式不提倡if foo[:3]=='abc' and foo[-3:]=='xyz': print 'yes'else: print 'no'
使用isinstance()比较对象的类型。比如:
foo = 'abc000xyz'# 提倡print isinstance(foo,int) # false# 不提倡print type(foo) == type('1') #true
判断序列空或不空,有如下规则:
foo = 'abc000xyz'if foo: print "not empty"else: print "empty"#不提倡使用如下if len(foo): print "not empty"else: print "empty"
二进制数据判断使用 if boolvalue的方式。
使用pylint进行代码检查,@permilk–Python代码分析工具:PyChecker、Pylint
# 安装pip install pylint
写一段测试代码,命名为test.py
# -*- coding:utf-8 -*-# 原理:http://blog.csdn.net/morewindows/article/details/6684558# 代码提供: http://www.cnblogs.com/yekwol/p/5778040.htmldef parttion(vec, left, right): key = vec[left] low = left high = right while low < high: while (low < high) and (vec[high] >= key): high -= 1 vec[low] = vec[high] while (low < high) and (vec[low] <= key): low += 1 vec[high] = vec[low] vec[low] = key return low# 采用递归的方式进行函数构建def quicksort(vec, left, right): if left < right: p = parttion(vec, left, right) quicksort(vec, left, p-1) # 再同样处理分片问题 quicksort(vec, p+1, right) return vec#s = [6, 8, 1, 4, 3, 9, 5, 4, 11, 2, 2, 15, 6]before_list = [4, 6, 1, 3, 5, 9]print "before sort:", before_list after_list = quicksort(before_list, left=0, right=len(before_list)-1)print"after sort:", after_list
进行代码规范测试
# 使用pylint test.py# 输出Problem importing module variables.py: No module named functools_lru_cache Problem importing module variables.pyc: No module named functools_lru_cache No config file found, using default configuration ************* Module test C: 24, 0: Trailing whitespace (trailing-whitespace) C: 1, 0: Missing module docstring (missing-docstring) C: 5, 0: Missing function docstring (missing-docstring) C: 20, 0: Missing function docstring (missing-docstring) C: 22, 8: Invalid variable name "p" (invalid-name) C: 28, 0: Invalid constant name "before_list" (invalid-name) C: 30, 0: Invalid constant name "after_list" (invalid-name) Report ======23 statements analysed. Statistics by type ------------------ +---------+-------+-----------+-----------+------------+---------+ |type |number |old number |difference |%documented |%badname | +=========+=======+===========+===========+============+=========+ |module |1 |1 |= |0.00 |0.00 | +---------+-------+-----------+-----------+------------+---------+ |class |0 |0 |= |0 |0 | +---------+-------+-----------+-----------+------------+---------+ |method |0 |0 |= |0 |0 | +---------+-------+-----------+-----------+------------+---------+ |function |2 |2 |= |0.00 |0.00 | +---------+-------+-----------+-----------+------------+---------+Raw metrics----------- +----------+-------+------+---------+-----------+ |type |number |% |previous |difference | +==========+=======+======+=========+===========+ |code |23 |71.88 |23 |= | +----------+-------+------+---------+-----------+ |docstring |0 |0.00 |0 |= | +----------+-------+------+---------+-----------+ |comment |5 |15.62 |5 |= | +----------+-------+------+---------+-----------+ |empty |4 |12.50 |4 |= | +----------+-------+------+---------+-----------+Duplication----------- +-------------------------+------+---------+-----------+ | |now |previous |difference | +=========================+======+=========+===========+ |nb duplicated lines |0 |0 |= | +-------------------------+------+---------+-----------+ |percent duplicated lines |0.000 |0.000 |= | +-------------------------+------+---------+-----------+Messages by category-------------------- +-----------+-------+---------+-----------+ |type |number |previous |difference | +===========+=======+=========+===========+ |convention |7 |7 |= | +-----------+-------+---------+-----------+ |refactor |0 |0 |= | +-----------+-------+---------+-----------+ |warning |0 |0 |= | +-----------+-------+---------+-----------+ |error |0 |0 |= | +-----------+-------+---------+-----------+Messages-------- +--------------------+------------+ |message id |occurrences | +====================+============+ |missing-docstring |3 | +--------------------+------------+ |invalid-name |3 | +--------------------+------------+ |trailing-whitespace |1 | +--------------------+------------+Global evaluation-----------------Your code has been rated at 6.96/10 (previous run: 6.96/10, +0.00)
>>> from collections import Counter>>> Counter(s=3, c=2, e=1, u=1) Counter({'s': 3, 'c': 2, 'u': 1, 'e': 1})>>> some_data=('c', '2', 2, 3, 5, 'c', 'd', 4, 5, 'd', 'd')>>> Counter(some_data).most_common(2) [('d', 3), ('c', 2)]>>> some_data=['c', '2', 2, 3, 5, 'c', 'd', 4, 5, 'd', 'd']>>> Counter(some_data).most_common(2) [('d', 3), ('c', 2)]>>> some_data={'c', '2', 2, 3, 5, 'c', 'd', 4, 5, 'd', 'd'}>>> Counter(some_data).most_common(2) [('c', 1), (3, 1)]
在同时需要index和value值的时候可以使用 enumerate。下列分别将字符串,数组,列表与字典遍历序列中的元素以及它们的下标
>>> for i,j in enumerate('abcde'):... print i,j... 0 a1 b2 c3 d4 e>>> for i,j in enumerate([1,2,3,4]):... print i,j... 0 11 22 33 4>>> for i,j in enumerate([1,2,3,4],start=1):... print i,j... 1 12 23 34 4
# 通过键索引来追踪元素 from collections import defaultdict s = "the quick brown fox jumps over the lazy dog"words = s.split() location = defaultdict(list)for m, n in enumerate(words): location[n].append(m)print location # defaultdict(<type 'list'>, {'brown': [2], 'lazy': [7], 'over': [5], 'fox': [3], # 'dog': [8], 'quick': [1], 'the': [0, 6], 'jumps': [4]})
os.path.join用于拼接路径,好处是可以根据系统自动选择正确的路径分隔符”/”或”\”
os.path.split 把路径分割成dirname和basename,返回一个元组
os.listdir 获取路径下所有文件,返回list
import os path=os.path.abspath("ams8B.zip")print path # /Users/didi/Desktop/testhelp/ams8B.zip # 实际上该文件夹下没有ams8B.zipprint os.path.join("/".join(path.split("/")[:-1]),'ams8B.gz') # /Users/didi/Desktop/testhelp/ams8B.gzprint os.path.join("home","user","test") # home/user/test# 把路径分割成dirname和basename,返回一个元组,作用在于不用区别到底是'\'还是'/'print os.path.split(path) # ('/Users/didi/Desktop/testhelp', 'ams8B.zip')print os.path.join(os.path.split(path)[0],'ams8B.gz') # /Users/didi/Desktop/testhelp/ams8B.gzprint os.getcwd() # /Users/didi/Desktop/testhelpprint os.listdir(os.getcwd()) # ['t1.txt', 'test1.py', 'test2.py', '\xe6\x8e\xa5\xe9\xa9\xbeeta\xe5\x88\x86\xe5\xb8\x83.sh']
>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]>>> print filter(lambda x: x % 3 == 0, foo) [18, 9, 24, 12, 27] >>>>>> print map(lambda x: x * 2 + 10, foo) [14, 46, 28, 54, 44, 58, 26, 34, 64] >>>>>> print reduce(lambda x, y: x + y, foo)139
使用列表推导式
>>> [x * 2 + 10 for x in foo] [14, 46, 28, 54, 44, 58, 26, 34, 64]>>> [x for x in foo if x % 3 == 0] [18, 9, 24, 12, 27]
对于轻量级循环,可尽量使用列表推导式,熟练使用列表推导式可以很多情况下代替map,filter等
>>> foo = [2, 18, 9, 22, 17, 24, 8, 12, 27]>>> foo [2, 18, 9, 22, 17, 24, 8, 12, 27]>>> ['>3' if i>3 else '<3' for i in foo] ['<3', '>3', '>3', '>3', '>3', '>3', '>3', '>3', '>3']>>> t=map(lambda x:'<3' if x<3 else '>3',foo)>>> t ['<3', '>3', '>3', '>3', '>3', '>3', '>3', '>3', '>3'] >>>
可参考:最简单的理解lambda,map,reduce,filter,列表推导式
# 函数原型sorted(iterable[, cmp[, key[, reverse]]]) # 返回一个排序后的列表s.sort([cmp[, key[, reverse]]]) # 直接修改原列表,返回为None>>> persons = [{'name': 'Jon', 'age': 32}, {'name': 'Alan', 'age': 50}, {'name': 'Bob', 'age': 23}]>>> sorted(persons, key=lambda x: (x['name'], -x['age'])) [{'name': 'Alan', 'age': 50}, {'name': 'Bob', 'age': 23}, {'name': 'Jon', 'age': 32}]>>> a = (1, 2, 4, 2, 3)>>> sorted(a) [1, 2, 2, 3, 4]>>> students = [('john', 'A', 15), ('jane', 'B', 12), ('dave', 'B', 10),] >>> sorted(students, key=lambda student : student[2]) # sort by age [('dave', 'B', 10), ('jane', 'B', 12), ('john', 'A', 15)]
所以如果实际过程中需要保留原有列表,可以使用sorted()。sort()不需要复制原有列表,消耗内存较小,效率较高。同时传入参数key比传入参数cmp效率要高,cmp传入的函数在整个排序过程中会调用多次,而key针对每个元素仅作一次处理。
关于cmp的使用,这位哥们总算踩到点python中sort()方法自定义cmp PythonTip-最大正整数
# cmp --如果排序的元素是其他类型的,如果a逻辑小于b,函数返回负数;a逻辑等于b,函数返回0;a逻辑大于b,函数返回正数就行了,这决定着两者是否交换位置def Reverse(a,b): return b-a list_ = [5,3,4,1,2] new = sorted(list_,cmp=ps)print new # [5, 4, 3, 2, 1]# # 这里的例子是,5,3做差值,为负,故两者不交换位置,里面的return作为条件
import tracebacktry: do somethingexcept Exception as ex: print ex traceback.print_exc()
相当于浅copy的作用
>>> a=[1,2,3]>>> b=a[:]>>> b.append(4)>>> b [1, 2, 3, 4]>>> a [1, 2, 3]>>> import copy>>> c=copy.copy(a)>>> c [1, 2, 3]>>> c.append(4)>>> a [1, 2, 3]>>> c [1, 2, 3, 4]>>> d=a>>> d.append(4)>>> d [1, 2, 3, 4]>>> a [1, 2, 3, 4]# 这里顺便说下deepcopy# [理论部分可以参考这里](http://www.cnblogs.com/wait123/archive/2011/10/10/2206580.html)# 浅copy>>> import copy>>> a = [[1,2],3,4]>>> b = copy.copy(a) >>> id(a)54936008L>>> id(b)54964680L>>> a is bFalse>>> b [[1, 2], 3, 4]>>> b[0][1]2>>> b[0][1]=2333>>> b [[1, 2333], 3, 4]>>> a [[1, 2333], 3, 4]# deepcopy>>> a = [[1,2],3,4]>>> c = copy.deepcopy(a)>>> id(a)55104008L>>> id(c)54974536L>>> a is cFalse>>> c [[1, 2], 3, 4]>>> c[0][1]2>>> c[0][1]=233>>> c [[1, 233], 3, 4]>>> a [[1, 2], 3, 4] # 不会随之改变# 这里测试下切片操作相当于浅copy>>> d = a[:]>>> d [[1, 2], 3, 4]>>> d[0][1]=0>>> d [[1, 0], 3, 4]>>> a [[1, 0], 3, 4] # 会随之改变
进行逆序排列
>>> b [1, 2, 3, 4]>>> b[::-1] [4, 3, 2, 1]
# json.dumps : dict转成str # json.loads:str转成dictimport json dict_ = {1:2, 3:4, "55":"66"} json_str = json.dumps(dict_)print type(json_str), json_str # <type 'str'> {"55": "66", "1": 2, "3": 4}print type(json.loads(json_str)) # <type 'dict'> {u'55': u'66', u'1': 2, u'3': 4}
from pprint import pprint data = [(1,{'a':'A','b':'B','c':'C','d':'D'}), (2,{'e':'E','f':'F','g':'G','h':'H', 'i':'I','j':'J','k':'K','l':'L' }),]print data pprint(data)#print效果[(1, {'a': 'A', 'c': 'C', 'b': 'B', 'd': 'D'}), (2, {'e': 'E', 'g': 'G', 'f': 'F', 'i': 'I', 'h': 'H', 'k': 'K', 'j': 'J', 'l': 'L'})]# pprint效果[(1, {'a': 'A', 'b': 'B', 'c': 'C', 'd': 'D'}), (2, {'e': 'E', 'f': 'F', 'g': 'G', 'h': 'H', 'i': 'I', 'j': 'J', 'k': 'K', 'l': 'L'})]
定义:zip([seql, …])接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同。
#!/usr/bin/python# -*- coding: utf-8 -*-name = ['mrlevo','hasky'] kind = ['human','dog'] z1 = [1,2,3] z2 = [4,5,6] result = zip(z1,z2) # 压缩过程uzip= zip(*result) # 解压过程,拆分为元组print "the zip:",result# the zip: [(1, 4), (2, 5), (3, 6)]print "the uzip:",uzip#the uzip: [(1, 2, 3), (4, 5, 6)]print "the uzip part of z1:%s\nthe uzip part of z2:%s"%(str(uzip[0]),str(uzip[1]))#the uzip part of z1:(1, 2, 3)#the uzip part of z2:(4, 5, 6)
*args仅仅只是用在函数定义的时候用来表示位置参数应该存储在变量args里面。Python允许我们制定一些参数并且通过args捕获其他所有剩余的未被捕捉的位置。当调用一个函数的时候,一个用*标志的变量意思是变量里面的内容需要被提取出来然后当做位置参数被使用。
def add(x, y): return x + y list_ = [1,2] add(list_[0], list_[1]) # 3add(*list_) # 3
*args要么是表示调用方法大的时候额外的参数可以从一个可迭代列表中取得,要么就是定义方法的时候标志这个方法能够接受任意的位置参数。接下来提到的**,**kw代表着键值对的字典,也就是说,你不用一个个字典用key来取value了
dict_ = {'x': 1, 'y': 2, 'z':3}def bar(x, y, z): return x + y + z bar(**dict_) # 6bar(dict_['x'],dict_['y'],dict_['z']) # 6
方法很多,就先介绍笔试题碰到的permutations
permutations(p[,r]);返回p中任意取r个元素做排列的元组的迭代器
如:permutations(‘abc’, 2) # 从’abcd’中挑选两个元素,比如ab, bc, … 将所有结果排序,返回为新的循环器。
注意,上面的组合分顺序,即ab, ba都返回。
combinations(‘abc’, 2) # 从’abcd’中挑选两个元素,比如ab, bc, … 将所有结果排序,返回为新的循环器。
注意,上面的组合不分顺序,即ab, ba的话,只返回一个ab。
再来个实际点的算法的一个例子,虽然毫无算法结构可言
# 输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba# itertools,内建库的用法# 参考:http://blog.csdn.net/neweastsun/article/details/51965226import itertoolsdef Permutation(ss): # write code here if not ss: return [] return sorted(list(set(map(lambda x:''.join(x), itertools.permutations(ss))))) Permutation('abc')# ['abc', 'acb', 'bac', 'bca', 'cab', 'cba']
更多可以参考:Python标准库13 循环器 (itertools)
对于文本的读取,使用f=open(‘path’)的方法来说,局限性很大,第一是内存加载问题,第二是文件流打开之后最后还需要关闭的问题,使用with..as轻松解决
with open('path') as f: for line in f: do songthing# for line in f 这种用法是把文件对象f当作迭代对象,系统将自动处理IO缓存和内存管理。对于读取超大的文件,这个方法不会把内存撑爆,这个是按行读取的with open('path') as f: for line in f.readlines(): do something# 这个方法是将文本中的内容都放在了一个列表里,然后进行迭代,对于大量的数据而言,效果不好
[1,2,3,4]这个是迭代器,用for来迭代它,生成器(x for x in range(4))也是迭代器的一种,但是你只能迭代它们一次.原因很简单,因为它们不是全部存在内存里,它们只在要调用的时候在内存里生成,
Yield
的用法和关键字return
差不多,下面的函数将会返回一个生成器。迭代的时候碰到yield立刻return一个值,下一次迭代的时候,从yield的下一条语句开始执行
>>> mygenerator = (x*x for x in range(4))>>> mygenerator <generator object <genexpr> at 0x1121b55a0>>>> mygenerator.next()0>>> mygenerator.next()1---------------------->>> def generater(n):... for i in range(n):... yield i... print 'here'...>>> g = generater(5)>>> g <generator object generater at 0x10c801280> # 凡是带有yield的函数都变成了生成器,都可以被迭代next()使用,>>> g.next()0>>> g.next() here1>>> g.next() here2 # 这里说明了它的运作过程,第一次迭代的时候,运行到yield函数,进行返回,而不执行下一个动作,第二次迭代的时候,直接从上一次yield的地方的下一条语句进行执行,也就看到了如下的效果。
另一个 yield 的例子来源于文件读取。如果直接对文件对象调用 read() 方法,会导致不可预测的内存占用。好的方法是利用固定长度的缓冲区来不断读取文件内容。通过 yield,我们不再需要编写读文件的迭代类,就可以轻松实现文件读取:
# from 廖雪峰def read_file(fpath): BLOCK_SIZE = 1024 with open(fpath, 'rb') as f: while True: block = f.read(BLOCK_SIZE) if block: yield block else: return
相关推荐:
以上がPython でよく使われる PEP8 の仕様と Python のコツの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。