目录
前言
PEP8 编码规范
给自己的代码打分
Python奇技淫巧
使用 Counter 进行计数统计
enumerate获取键值对
os.path的使用
善用列表推导式
sort 与 sorted
善用traceback 追踪深层错误
切片操作[]
json.dump()/loads() 存储字典结构
pprint打印结构
zip打包元组
*args和**kw
内建函数 itertools优雅的迭代器
使用with open() as f 来读取文件
使用yield节省内存开销
首页 后端开发 Python教程 Python 常用的PEP8规范及Python小把戏

Python 常用的PEP8规范及Python小把戏

May 05, 2018 pm 02:50 PM
python 规范

本篇文章的内容是Python 常用PEP8规范及Python小把戏 ,现在分享给大家,有需要的朋友可以看一下这篇文章的内容


前言

从很多地方搬运+总结,以后根据这个标准再将python的一些奇技淫巧结合起来,写出更pythonic的代码~

PEP8 编码规范

英文原版请点击这里

以下是@bobo的整理,原文请见PEP8 Python 编码规范整理代码编排

  1. 缩进。4个空格的缩进(编辑器都可以完成此功能),不使用Tap,更不能混合使用Tap和空格。

  2. 每行最大长度79,换行可以使用反斜杠,最好使用圆括号。换行点要在操作符的后边敲回车。

  3. 类和top-level函数定义之间空两行;类中的方法定义之间空一行;函数内逻辑无关段落之间空一行;其他地方尽量不要再空行。

文档编排

  1. 模块内容的顺序:模块说明和docstring—import—globals&constants—其他定义。其中import部分,又按标准、三方和自己编写顺序依次排放,之间空一行

  2. 不要在一句import中多个库,比如import os, sys不推荐

  3. 如果采用from XX import XX引用库,可以省略‘module.’,都是可能出现命名冲突,这时就要采用import XX

空格的使用

  1. 各种右括号前不要加空格。

  2. 逗号、冒号、分号前不要加空格。

  3. 函数的左括号前不要加空格。如Func(1)

  4. 序列的左括号前不要加空格。如list[2]

  5. 操作符左右各加一个空格,不要为了对齐增加空格

  6. 函数默认参数使用的赋值符左右省略空格

  7. 不要将多句语句写在同一行,尽管使用‘;’允许

  8. if/for/while语句中,即使执行语句只有一句,也必须另起一行

注释

总体原则,错误的注释不如没有注释。所以当一段代码发生变化时,第一件事就是要修改注释!注释必须使用英文,最好是完整的句子,首字母大写,句后要有结束符,结束符后跟两个空格,开始下一句。如果是短语,可以省略结束符。

  1. 块注释,在一段代码前增加的注释。在‘#’后加一空格。段落之间以只有‘#’的行间隔。比如:

# Description : Module config.# # Input : None## Output : None
登录后复制
  1. 行注释,在一句代码后加注释。比如:x = x + 1 # Increment x但是这种方式尽量少使用。

  2. 避免无谓的注释。

文档描述

  1. 为所有的共有模块、函数、类、方法写docstrings;非共有的没有必要,但是可以写注释(在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. 包命名尽量短小,使用全部小写的方式,不可以使用下划线。

  3. 类的命名使用CapWords的方式,模块内部使用的类采用_CapWords的方式。

  4. 异常命名使用CapWords+Error后缀的方式。

  5. 全局变量尽量只在模块内有效,类似C语言中的static。实现方法有两种,一是all机制;二是前缀一个下划线。

  6. 函数命名使用全部小写的方式,可以使用下划线。

  7. 常量命名使用全部大写的方式,可以使用下划线。

  8. 类的属性(方法和变量)命名使用全部小写的方式,可以使用下划线。

  9. 类的属性有3种作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public属性前,前缀一条下划线。

  10. 类的属性若与关键字名字冲突,后缀一下划线,尽量不要使用缩略等其他方式。

  11. 为避免与子类属性命名冲突,在类的一些属性前,前缀两条下划线。比如:类Foo中声明__a,访问时,只能通过Foo._Foo__a,避免歧义。如果子类也叫Foo,那就无能为力了。

  12. 类的方法第一个参数必须是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中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

PHP和Python:解释了不同的范例 PHP和Python:解释了不同的范例 Apr 18, 2025 am 12:26 AM

PHP主要是过程式编程,但也支持面向对象编程(OOP);Python支持多种范式,包括OOP、函数式和过程式编程。PHP适合web开发,Python适用于多种应用,如数据分析和机器学习。

Python vs. JavaScript:学习曲线和易用性 Python vs. JavaScript:学习曲线和易用性 Apr 16, 2025 am 12:12 AM

Python更适合初学者,学习曲线平缓,语法简洁;JavaScript适合前端开发,学习曲线较陡,语法灵活。1.Python语法直观,适用于数据科学和后端开发。2.JavaScript灵活,广泛用于前端和服务器端编程。

在PHP和Python之间进行选择:指南 在PHP和Python之间进行选择:指南 Apr 18, 2025 am 12:24 AM

PHP适合网页开发和快速原型开发,Python适用于数据科学和机器学习。1.PHP用于动态网页开发,语法简单,适合快速开发。2.Python语法简洁,适用于多领域,库生态系统强大。

vs code 可以在 Windows 8 中运行吗 vs code 可以在 Windows 8 中运行吗 Apr 15, 2025 pm 07:24 PM

VS Code可以在Windows 8上运行,但体验可能不佳。首先确保系统已更新到最新补丁,然后下载与系统架构匹配的VS Code安装包,按照提示安装。安装后,注意某些扩展程序可能与Windows 8不兼容,需要寻找替代扩展或在虚拟机中使用更新的Windows系统。安装必要的扩展,检查是否正常工作。尽管VS Code在Windows 8上可行,但建议升级到更新的Windows系统以获得更好的开发体验和安全保障。

visual studio code 可以用于 python 吗 visual studio code 可以用于 python 吗 Apr 15, 2025 pm 08:18 PM

VS Code 可用于编写 Python,并提供许多功能,使其成为开发 Python 应用程序的理想工具。它允许用户:安装 Python 扩展,以获得代码补全、语法高亮和调试等功能。使用调试器逐步跟踪代码,查找和修复错误。集成 Git,进行版本控制。使用代码格式化工具,保持代码一致性。使用 Linting 工具,提前发现潜在问题。

PHP和Python:深入了解他们的历史 PHP和Python:深入了解他们的历史 Apr 18, 2025 am 12:25 AM

PHP起源于1994年,由RasmusLerdorf开发,最初用于跟踪网站访问者,逐渐演变为服务器端脚本语言,广泛应用于网页开发。Python由GuidovanRossum于1980年代末开发,1991年首次发布,强调代码可读性和简洁性,适用于科学计算、数据分析等领域。

vscode怎么在终端运行程序 vscode怎么在终端运行程序 Apr 15, 2025 pm 06:42 PM

在 VS Code 中,可以通过以下步骤在终端运行程序:准备代码和打开集成终端确保代码目录与终端工作目录一致根据编程语言选择运行命令(如 Python 的 python your_file_name.py)检查是否成功运行并解决错误利用调试器提升调试效率

vscode 扩展是否是恶意的 vscode 扩展是否是恶意的 Apr 15, 2025 pm 07:57 PM

VS Code 扩展存在恶意风险,例如隐藏恶意代码、利用漏洞、伪装成合法扩展。识别恶意扩展的方法包括:检查发布者、阅读评论、检查代码、谨慎安装。安全措施还包括:安全意识、良好习惯、定期更新和杀毒软件。

See all articles