ホームページ  >  記事  >  バックエンド開発  >  Python でよく使われる PEP8 の仕様と Python のコツ

Python でよく使われる PEP8 の仕様と Python のコツ

不言
不言オリジナル
2018-04-04 15:29:101205ブラウズ

この記事の内容は、Python の一般的に使用される PEP8 の仕様と Python のテクニックです。必要な友達はこの記事の内容を参照してください


多くの人からの移動 + 概要です。この標準は、Python のいくつかのトリックを組み合わせて、より多くの Python コードを記述します~

PEP8 コーディング仕様

英語の原文についてはここをクリックしてください

以下は@bobo の編集、原文 PEP8 Python コーディング標準編成

コード配置

インデントをご覧ください。 4 スペースのインデント (すべての編集者がこの機能を実行できます)、Tap は使用せず、Tap とスペースを混合することはできません。
  1. 各行の最大長は 79 です。改行にはバックスラッシュを使用できます。括弧を使用することをお勧めします。改行ポイントは演算子の後にヒットする必要があります。
  2. クラスとトップレベル関数定義の間に 2 つの空白行、クラス内のメソッド定義の間に 1 つの空白行、関数内の論理的に無関係な段落の間に 1 つの空白行を避けるようにしてください。
  3. ドキュメントの配置

モジュール内容の順序: モジュールの説明と docstring -インポート -グローバルと定数 -その他の定義。インポート部分は、標準、サードパーティ、自作の順に空白行を挟んで配置されています
  1. import os, sysなど、複数のライブラリを一文でインポートしないでください
  2. 場合from XX import XX を使用します ライブラリを引用する場合、'module.' を省略できますが、この場合は import XX を使用する必要があります
  3. スペースの使用

さまざまな閉じ括弧の前のスペース。
  1. カンマ、コロン、セミコロンの前にスペースを追加しないでください。
  2. 関数の左括弧の前にスペースを追加しないでください。たとえば、Func(1)
  3. シーケンスの左括弧の前にスペースを追加しないでください。たとえば、list[2]
  4. 演算子の左右にスペースを追加します。
  5. 関数のデフォルトパラメータで使用される代入演算子の前後にスペースを追加しないでください。
  6. 「;」の使用は許可されていますが、実行ステートメントが 1 文であっても、新しい行で開始する必要があります。

コメント

原則として、間違ったコメントはコメントがないより悪いです。したがって、コードの一部が変更された場合、最初に行うことはコメントを変更することです。コメントは英語で記述し、最初の文字を大文字にして完全な文章にする必要があります。文の後にはターミネータが必要で、ターミネータの後には次の文を開始する 2 つのスペースが必要です。フレーズの場合、ターミネータは省略できます。

  1. コメント、コードの前に追加されたコメントをブロックします。 「#」の後にスペースを追加します。段落は「#」のみの行で区切る必要があります。例:

# Description : Module config.# # Input : None## Output : None
  1. 行コメント。コード行の後にコメントを追加します。例: x = x + 1 # Increment xただし、この方法はできるだけ使用しないでください。

  2. 不必要なコメントは避けてください。

ドキュメントの説明

  1. すべてのパブリックモジュール、関数、クラス、およびメソッドの docstring を記述します。非パブリックなものは必要ありませんが、コメントを (def の次の行に) 記述できます。

  2. 単一行コメントについては、次の方法を参照してください

def kos_root():
    """Return the pathname of the KOS root directory."""
    global _kos_root    if _kos_root: return _kos_root
    ...

命名規則

* 原則として、新しいコードは次の命名スタイルと既存のコードに従ってコンパイルする必要がありますライブラリは可能な限りスタイルを維持する必要があります。大文字の「i」と大文字の「o」* を単独で使用しないでください。モジュール名はできるだけ短くし、すべて小文字を使用し、アンダースコアを使用してください。

  1. パッケージ名はできるだけ短くし、すべて小文字を使用し、アンダースコアは使用しないでください。

  2. クラスは CapWords 形式で名前が付けられ、モジュール内で使用されるクラスは _CapWords 形式で名前が付けられます。

  3. 例外の名前付けには、CapWords+Error サフィックスが使用されます。

  4. グローバル変数は、C 言語の static と同様に、可能な限りモジュール内でのみ有効である必要があります。実装方法は 2 つあり、1 つは

    all

    メカニズムで、もう 1 つはアンダースコアを接頭辞として付けます。
  5. 関数名はすべて小文字を使用し、アンダースコアも使用できます。

  6. 定数に名前を付けるときはすべて大文字を使用し、アンダースコアも使用できます。

  7. クラスの属性 (メソッドと変数) はすべて小文字で名前を付ける必要があり、アンダースコアを使用できます。

  8. クラス属性には、パブリック、非パブリック、およびサブクラス API の 3 つのスコープがあり、C++ ではパブリック、プライベート、保護として理解できます。非パブリック属性の前にはアンダースコア接頭辞があります。

  9. クラスの属性がキーワード名と競合する場合は、末尾にアンダースコアを付け、略語やその他の方法を使用しないようにしてください。

  10. サブクラス属性との名前の競合を避けるために、クラスの一部の属性の前に 2 つのアンダースコアを付けます。例: __a はクラス Foo で宣言されており、アクセスするときは、あいまいさを避けるために Foo._Foo__a を介してのみアクセスできます。サブクラスの名前も Foo である場合、できることは何もありません。

  11. クラスメソッドの最初のパラメータはselfである必要があり、静的メソッドの最初のパラメータはclsである必要があります。

编程建议

  1. 编码中考虑到其他python实现的效率等问题,比如运算符‘+’在CPython(Python)中效率很高,都是Jython中却非常低,所以应该采用.join()的方式。

  2. 尽可能使用‘is’‘is not’取代‘==’,比如if x is not None 要优于if x

  3. 使用基于类的异常,每个模块或包都有自己的异常类,此异常类继承自Exception。

  4. 常中不要使用裸露的except,except后跟具体的exceptions。例如

try:
    ...except Exception as ex:    print ex
  1. 异常中try的代码尽可能少。

  2. 使用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'

  1. 使用isinstance()比较对象的类型。比如:

foo = 'abc000xyz'# 提倡print isinstance(foo,int) # false# 不提倡print type(foo) == type('1') #true

  1. 判断序列空或不空,有如下规则:

foo = 'abc000xyz'if foo:    print "not empty"else:    print "empty"#不提倡使用如下if len(foo):    print "not empty"else:    print "empty"

  1. 二进制数据判断使用 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)


Python奇技淫巧


使用 Counter 进行计数统计

>>> from collections import Counter>>> Counter(s=3, c=2, e=1, u=1)
Counter({&#39;s&#39;: 3, &#39;c&#39;: 2, &#39;u&#39;: 1, &#39;e&#39;: 1})>>> some_data=(&#39;c&#39;, &#39;2&#39;, 2, 3, 5, &#39;c&#39;, &#39;d&#39;, 4, 5, &#39;d&#39;, &#39;d&#39;)>>> Counter(some_data).most_common(2)
[(&#39;d&#39;, 3), (&#39;c&#39;, 2)]>>> some_data=[&#39;c&#39;, &#39;2&#39;, 2, 3, 5, &#39;c&#39;, &#39;d&#39;, 4, 5, &#39;d&#39;, &#39;d&#39;]>>> Counter(some_data).most_common(2)
[(&#39;d&#39;, 3), (&#39;c&#39;, 2)]>>> some_data={&#39;c&#39;, &#39;2&#39;, 2, 3, 5, &#39;c&#39;, &#39;d&#39;, 4, 5, &#39;d&#39;, &#39;d&#39;}>>> Counter(some_data).most_common(2)
[(&#39;c&#39;, 1), (3, 1)]


enumerate获取键值对

  • 在同时需要index和value值的时候可以使用 enumerate。下列分别将字符串,数组,列表与字典遍历序列中的元素以及它们的下标

>>> for i,j in enumerate(&#39;abcde&#39;):...     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 &#39;list&#39;>, {&#39;brown&#39;: [2], &#39;lazy&#39;: [7], &#39;over&#39;: [5], &#39;fox&#39;: [3],
# &#39;dog&#39;: [8], &#39;quick&#39;: [1], &#39;the&#39;: [0, 6], &#39;jumps&#39;: [4]})


os.path的使用

  • 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]),&#39;ams8B.gz&#39;)  # /Users/didi/Desktop/testhelp/ams8B.gzprint os.path.join("home","user","test")  # home/user/test# 把路径分割成dirname和basename,返回一个元组,作用在于不用区别到底是&#39;\&#39;还是&#39;/&#39;print os.path.split(path)  # (&#39;/Users/didi/Desktop/testhelp&#39;, &#39;ams8B.zip&#39;)print os.path.join(os.path.split(path)[0],&#39;ams8B.gz&#39;)  #   /Users/didi/Desktop/testhelp/ams8B.gzprint os.getcwd()  # /Users/didi/Desktop/testhelpprint os.listdir(os.getcwd())  # [&#39;t1.txt&#39;, &#39;test1.py&#39;, &#39;test2.py&#39;, &#39;\xe6\x8e\xa5\xe9\xa9\xbeeta\xe5\x88\x86\xe5\xb8\x83.sh&#39;]


善用列表推导式

>>> 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]>>> [&#39;>3&#39; if i>3 else &#39;<3&#39; for i in foo]
[&#39;<3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;]>>> t=map(lambda x:&#39;<3&#39; if x<3 else &#39;>3&#39;,foo)>>> t
[&#39;<3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;, &#39;>3&#39;]
>>>

可参考:最简单的理解lambda,map,reduce,filter,列表推导式


sort 与 sorted

# 函数原型sorted(iterable[, cmp[, key[, reverse]]])   # 返回一个排序后的列表s.sort([cmp[, key[, reverse]]])             # 直接修改原列表,返回为None>>> persons = [{&#39;name&#39;: &#39;Jon&#39;, &#39;age&#39;: 32}, {&#39;name&#39;: &#39;Alan&#39;, &#39;age&#39;: 50}, {&#39;name&#39;: &#39;Bob&#39;, &#39;age&#39;: 23}]>>> sorted(persons, key=lambda x: (x[&#39;name&#39;], -x[&#39;age&#39;]))
[{&#39;name&#39;: &#39;Alan&#39;, &#39;age&#39;: 50}, {&#39;name&#39;: &#39;Bob&#39;, &#39;age&#39;: 23}, {&#39;name&#39;: &#39;Jon&#39;, &#39;age&#39;: 32}]>>> a = (1, 2, 4, 2, 3)>>> sorted(a)
[1, 2, 2, 3, 4]>>> students = [(&#39;john&#39;, &#39;A&#39;, 15), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;dave&#39;, &#39;B&#39;, 10),]  
>>> sorted(students, key=lambda student : student[2])   # sort by age  [(&#39;dave&#39;, &#39;B&#39;, 10), (&#39;jane&#39;, &#39;B&#39;, 12), (&#39;john&#39;, &#39;A&#39;, 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作为条件


善用traceback 追踪深层错误

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.dump()/loads() 存储字典结构

# 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 &#39;str&#39;> {"55": "66", "1": 2, "3": 4}print type(json.loads(json_str)) 
# <type &#39;dict&#39;> {u&#39;55&#39;: u&#39;66&#39;, u&#39;1&#39;: 2, u&#39;3&#39;: 4}


pprint打印结构

from pprint import pprint
data = [(1,{&#39;a&#39;:&#39;A&#39;,&#39;b&#39;:&#39;B&#39;,&#39;c&#39;:&#39;C&#39;,&#39;d&#39;:&#39;D&#39;}),

        (2,{&#39;e&#39;:&#39;E&#39;,&#39;f&#39;:&#39;F&#39;,&#39;g&#39;:&#39;G&#39;,&#39;h&#39;:&#39;H&#39;,            &#39;i&#39;:&#39;I&#39;,&#39;j&#39;:&#39;J&#39;,&#39;k&#39;:&#39;K&#39;,&#39;l&#39;:&#39;L&#39;

            }),]print data
pprint(data)#print效果[(1, {&#39;a&#39;: &#39;A&#39;, &#39;c&#39;: &#39;C&#39;, &#39;b&#39;: &#39;B&#39;, &#39;d&#39;: &#39;D&#39;}), (2, {&#39;e&#39;: &#39;E&#39;, &#39;g&#39;: &#39;G&#39;, &#39;f&#39;: &#39;F&#39;, &#39;i&#39;: &#39;I&#39;, &#39;h&#39;: &#39;H&#39;, &#39;k&#39;: &#39;K&#39;, &#39;j&#39;: &#39;J&#39;, &#39;l&#39;: &#39;L&#39;})]# pprint效果[(1, {&#39;a&#39;: &#39;A&#39;, &#39;b&#39;: &#39;B&#39;, &#39;c&#39;: &#39;C&#39;, &#39;d&#39;: &#39;D&#39;}),
 (2,
  {&#39;e&#39;: &#39;E&#39;,   &#39;f&#39;: &#39;F&#39;,   &#39;g&#39;: &#39;G&#39;,   &#39;h&#39;: &#39;H&#39;,   &#39;i&#39;: &#39;I&#39;,   &#39;j&#39;: &#39;J&#39;,   &#39;k&#39;: &#39;K&#39;,   &#39;l&#39;: &#39;L&#39;})]


zip打包元组

定义:zip([seql, …])接受一系列可迭代对象作为参数,将对象中对应的元素打包成一个个tuple(元组),然后返回由这些tuples组成的list(列表)。若传入参数的长度不等,则返回list的长度和参数中长度最短的对象相同。

#!/usr/bin/python# -*- coding: utf-8 -*-name = [&#39;mrlevo&#39;,&#39;hasky&#39;]
kind = [&#39;human&#39;,&#39;dog&#39;]
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和**kw

*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_ = {&#39;x&#39;: 1, &#39;y&#39;: 2, &#39;z&#39;:3}def bar(x, y, z):
    return x + y + z

bar(**dict_)  # 6bar(dict_[&#39;x&#39;],dict_[&#39;y&#39;],dict_[&#39;z&#39;])  # 6


内建函数 itertools优雅的迭代器

方法很多,就先介绍笔试题碰到的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:&#39;&#39;.join(x), itertools.permutations(ss)))))

Permutation(&#39;abc&#39;)# [&#39;abc&#39;, &#39;acb&#39;, &#39;bac&#39;, &#39;bca&#39;, &#39;cab&#39;, &#39;cba&#39;]

更多可以参考:Python标准库13 循环器 (itertools)


使用with open() as f 来读取文件

对于文本的读取,使用f=open(‘path’)的方法来说,局限性很大,第一是内存加载问题,第二是文件流打开之后最后还需要关闭的问题,使用with..as轻松解决

with open(&#39;path&#39;) as f:    for line in f:
        do songthing# for line in f 这种用法是把文件对象f当作迭代对象,系统将自动处理IO缓存和内存管理。对于读取超大的文件,这个方法不会把内存撑爆,这个是按行读取的with open(&#39;path&#39;) as f:    for line in f.readlines():
        do something# 这个方法是将文本中的内容都放在了一个列表里,然后进行迭代,对于大量的数据而言,效果不好


使用yield节省内存开销

[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 &#39;here&#39;...>>> 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, &#39;rb&#39;) as f:        while True:
            block = f.read(BLOCK_SIZE)            if block:                yield block            else:                return


相关推荐:

Python安装流程指南


以上がPython でよく使われる PEP8 の仕様と Python のコツの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。