目錄
前言
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脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25:如何解鎖Myrise中的所有內容
4 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

mysql 是否要付費 mysql 是否要付費 Apr 08, 2025 pm 05:36 PM

MySQL 有免費的社區版和收費的企業版。社區版可免費使用和修改,但支持有限,適合穩定性要求不高、技術能力強的應用。企業版提供全面商業支持,適合需要穩定可靠、高性能數據庫且願意為支持買單的應用。選擇版本時考慮的因素包括應用關鍵性、預算和技術技能。沒有完美的選項,只有最合適的方案,需根據具體情況謹慎選擇。

mysql安裝後怎麼使用 mysql安裝後怎麼使用 Apr 08, 2025 am 11:48 AM

文章介紹了MySQL數據庫的上手操作。首先,需安裝MySQL客戶端,如MySQLWorkbench或命令行客戶端。 1.使用mysql-uroot-p命令連接服務器,並使用root賬戶密碼登錄;2.使用CREATEDATABASE創建數據庫,USE選擇數據庫;3.使用CREATETABLE創建表,定義字段及數據類型;4.使用INSERTINTO插入數據,SELECT查詢數據,UPDATE更新數據,DELETE刪除數據。熟練掌握這些步驟,並學習處理常見問題和優化數據庫性能,才能高效使用MySQL。

mysql 需要互聯網嗎 mysql 需要互聯網嗎 Apr 08, 2025 pm 02:18 PM

MySQL 可在無需網絡連接的情況下運行,進行基本的數據存儲和管理。但是,對於與其他系統交互、遠程訪問或使用高級功能(如復制和集群)的情況,則需要網絡連接。此外,安全措施(如防火牆)、性能優化(選擇合適的網絡連接)和數據備份對於連接到互聯網的 MySQL 數據庫至關重要。

如何針對高負載應用程序優化 MySQL 性能? 如何針對高負載應用程序優化 MySQL 性能? Apr 08, 2025 pm 06:03 PM

MySQL數據庫性能優化指南在資源密集型應用中,MySQL數據庫扮演著至關重要的角色,負責管理海量事務。然而,隨著應用規模的擴大,數據庫性能瓶頸往往成為製約因素。本文將探討一系列行之有效的MySQL性能優化策略,確保您的應用在高負載下依然保持高效響應。我們將結合實際案例,深入講解索引、查詢優化、數據庫設計以及緩存等關鍵技術。 1.數據庫架構設計優化合理的數據庫架構是MySQL性能優化的基石。以下是一些核心原則:選擇合適的數據類型選擇最小的、符合需求的數據類型,既能節省存儲空間,又能提升數據處理速度

HadiDB:Python 中的輕量級、可水平擴展的數據庫 HadiDB:Python 中的輕量級、可水平擴展的數據庫 Apr 08, 2025 pm 06:12 PM

HadiDB:輕量級、高水平可擴展的Python數據庫HadiDB(hadidb)是一個用Python編寫的輕量級數據庫,具備高度水平的可擴展性。安裝HadiDB使用pip安裝:pipinstallhadidb用戶管理創建用戶:createuser()方法創建一個新用戶。 authentication()方法驗證用戶身份。 fromhadidb.operationimportuseruser_obj=user("admin","admin")user_obj.

Navicat查看MongoDB數據庫密碼的方法 Navicat查看MongoDB數據庫密碼的方法 Apr 08, 2025 pm 09:39 PM

直接通過 Navicat 查看 MongoDB 密碼是不可能的,因為它以哈希值形式存儲。取回丟失密碼的方法:1. 重置密碼;2. 檢查配置文件(可能包含哈希值);3. 檢查代碼(可能硬編碼密碼)。

mysql workbench 可以連接到 mariadb 嗎 mysql workbench 可以連接到 mariadb 嗎 Apr 08, 2025 pm 02:33 PM

MySQL Workbench 可以連接 MariaDB,前提是配置正確。首先選擇 "MariaDB" 作為連接器類型。在連接配置中,正確設置 HOST、PORT、USER、PASSWORD 和 DATABASE。測試連接時,檢查 MariaDB 服務是否啟動,用戶名和密碼是否正確,端口號是否正確,防火牆是否允許連接,以及數據庫是否存在。高級用法中,使用連接池技術優化性能。常見錯誤包括權限不足、網絡連接問題等,調試錯誤時仔細分析錯誤信息和使用調試工具。優化網絡配置可以提升性能

mysql 需要服務器嗎 mysql 需要服務器嗎 Apr 08, 2025 pm 02:12 PM

對於生產環境,通常需要一台服務器來運行 MySQL,原因包括性能、可靠性、安全性和可擴展性。服務器通常擁有更強大的硬件、冗餘配置和更嚴格的安全措施。對於小型、低負載應用,可在本地機器運行 MySQL,但需謹慎考慮資源消耗、安全風險和維護成本。如需更高的可靠性和安全性,應將 MySQL 部署到雲服務器或其他服務器上。選擇合適的服務器配置需要根據應用負載和數據量進行評估。

See all articles