Skip to content

Instantly share code, notes, and snippets.

@oiuww09fn
Last active August 29, 2015 14:04
Show Gist options
  • Save oiuww09fn/d4906407196a8269290c to your computer and use it in GitHub Desktop.
Save oiuww09fn/d4906407196a8269290c to your computer and use it in GitHub Desktop.
import this

安装及开发环境

第一个 Python 程序

注释

注释有两种,一种以#开头,另一种是文档字符串。文档字符串可以再运行时访问(__doc__),并可以生成帮助文档。

操作符

运算符 说明
x + y, x -y 加减
x * y, x / y 乘除
+x, -x 正负
x += y, x -= y
x *= y, x /= y
x // y 整除
x ** y
x % y 取模
x & y, x y, x ^ y
~x 位取反
x << y, x >> y 位移
x > y, x >= y 比较
x < y, x <= y
x == y, x != y 相等
x is y, x is not y 同一对象
x in y, x not in y 包含, 序列、字典、迭代器
not x
x and y, x or y 布尔
abs 绝对值
all 全部
any 任意
pow
len 元素数量
min, max 最大、最小元素
divmod (商,余数)
sum 统计
cmp 比较

变量和赋值

Python不需要预先声明变量的类型, 变量的类型和值在赋值的那一刻被初始化。

    x = 123

如上,x是一个变量。变量名以下划线或字母开头,可包含字母、下划线、数字。

在python中x其实是一个字符串对象,它和123在名字空间中构成一项关联{"x": 123}

Python有多种名字空间,比如globals, locals, 还有class、instance名字空间。不同的名字空间决定了对象的作用域和生存周期。

    >>> a = 123
    >>> globals()  # 获取 module  名字空间。
    {'a': 123, ......}

可以看出,名字空间就是一个字典(dict) 。我们完全可以直接在名字空间添加项来创建变量。

    >>> globals()["b"] = "Hello, World!"
    >>> b
    'Hello, World!'

变量名的作用仅仅是在某个时刻与名字空间中的某个对象进关联。其本本身不包含目标对象的任何信息,正因为如此在运行时可将某变量关联到任何类型对象。

数字

  • bool: 类型可以当数字来用. None、0 、空字符串、以及没有元素的容器对象都可视为 False,反之为True。
  • int
  • long
  • float
        >>> 3/2
        1
        >>> float(3)/2
        1.5
  • complex

字符串

字符串定义可以使用单引号、双引号和三引号,python中单引号和双引号没有区别,可以互相嵌套(不能多层)。三引号一般用于文档字符串书写,三引号中定义的字符串保留了字符串定义时的格式。

         S.lowercase()

         S.capitalize()      #首字母大写

         S.lower()           #转小写

         S.upper()           #转大写

         S.swapcase()        #大小写互换

         S.split(str, ' ')   #将string转list,以空格切分

         S.join(list, ' ')   #将list转string,以空格连接

         S.find(substring, [start [,end]])  #可指范围查找子串,返回索引值,否则返回-1

         S.rfind(substring,[start [,end]])  #反向查找

         S.index(substring,[start [,end]])  #同find,只是找不到产生ValueError异常

         S.rindex(substring,[start [,end]])  #同上反向查找

         S.count(substring,[start [,end]])   #返回找到子串的个数

处理字符串的内置函数

         len(str)                #串长度

         cmp("my friend", str)   #字符串比较。第一个大,返回1

         max('abcxyz')           #寻找字符串中最大的字符

         min('abcxyz')           #寻找字符串中最小的字符

列表和元组

元组是不可变的列表

         L.append(var)   #追加元素

         L.insert(index,var)

         L.pop(var)      #返回最后一个元素,并从list中删除之

         L.remove(var)   #删除第一次出现的该元素

         L.count(var)    #该元素在列表中出现的个数

         L.index(var)    #该元素的位置,无则抛异常

         L.extend(list)  #追加list,即合并list到L上

         L.sort()        #排序

         L.reverse()     #倒序

         # list 操作符:,+,*,关键字del

         a[1:]       #片段操作符,用于子list的提取

         [1,2]+[3,4] #为[1,2,3,4]。同extend()

         [2]*4       #为[2,2,2,2]

         del L[1]    #删除指定下标的元素

         del L[1:3]  #删除指定下标范围的元素

         # list的复制

         L1 = L      #L1为L的别名,用C来说就是指针地址相同,对L1操作即对L操作。函数参数就是这样传递的

         L1 = L[:]   #L1为L的克隆,即另一个拷贝。

字典

         D.get(key, 0)       #同dict[key],多了个没有则返回缺省值,0。[]没有则抛异常

         D.has_key(key)      #有该键返回TRUE,否则FALSE

         D.keys()            #返回字典键的列表

         D.values()

         D.items()

         D.update(dict2)     #增加合并字典

         D.popitem()         #得到一个pair,并从字典中删除它。已空则抛异常

         D.clear()           #清空字典,同del dict

         D.copy()            #拷贝字典

         D.cmp(dict1,dict2)  #比较字典,(优先级为元素个数、键大小、键值大小),第一个大返回1,小返回-1,一样返回0

         # dictionary的复制

         dict1 = dict        #别名

         dict2=dict.copy()   #克隆,即另一个拷贝。

条件和循环

if

    a = 1
    if a is True:
        print "in if"
    elif a is False:
        print "in else if"
    else:
        print "in else"

while

    i = 0
    while 1:
        i += 1
        if i > 10:
            break
        else:
            print(i)
    else:  # break 跳出while,else部分不会被执行,while正常结束,else才会执行。
        print("Finish")

for循环总是配合列表、元组、字典等可迭代对象使用(for in)。

    for i in xrange(10):
        print i
        if i > 10:
            break
    else:  # 同while中的else,此例中的else会被执行。
        print "Finish"

pass: 占位符,通常用来标记空代码块。

break:中断循环

continue:开始下一次循环

注意:break、continue不能跳出多层嵌套循环。

异常

异常不仅仅是错误,还是一种正常的逻辑跳转,完整的try格式如下:

    try:
        raise RuntimeError("something error")
    except RuntimeError as e:
        print e
    except (IndexError, ValueError) as e:  # 一次捕获多个异常
        print e
    except Exception as e:  # 捕获任意类型异常, 少用!
        print e
    else:  # 没有异常运行
        print "Else"
    finally:  # 有没有异常都运行
        print "Finally"

try...except中可以嵌套try..except, except中可以再抛出异常。

函数

当解释器遇到def时,会生成创建函数对象指令。也就是说def是执行指令,而不仅仅是个语法关键字。可以在任何地方动态创建函数对象。

函数和python中的其他对象一样,可以作为其他函数的参数或返回值。

python中匿名函数用lambda:lamdba x: x。lambda中只能有一条有返回值的简单表达式。

In [1]: def hello(n):
   ...:     if n == "a":
   ...:         def a():
   ...:             pass
   ...:         return a
   ...:     elif isinstance(n, int):
   ...:         return lambda x: n**x
   ...:     else:
   ...:         return n
   ...:

In [2]: a = hello("a")

In [3]: print(a())
None

In [4]: a = hello(3)

In [5]: a
Out[5]: <function __main__.<lambda>>

In [6]: print(a(2))
9

In [7]: print hello("Hello")
Hello

python中函数传参方式有很多种:

    def hello(a, b, c=None, *args, **kwargs):
        pass

带默认值的参数,默认值参数对象是在创建函数时生成的,所有调用者都使用同一个对象。如果是可变对象,会造成意向不到的后果。

In [12]: def hello(a=[]):
   ....:     a.append(1)
   ....:     return a
   ....: 

In [13]: hello()
Out[13]: [1]

In [14]: hello()
Out[14]: [1, 1]

In [15]: hello()
Out[15]: [1, 1, 1]

带默认值的参数后边不能再跟位置参数。

变参*args收集剩余的位置参数,**kwargs收集剩余的命名参数。这两个参数如果有,必须按放在所有参数后面,且**kwargs要放到最后。 lambda也支持默认值参数和变参,使用方法和普通函数一样。

# TODO 函数作用域,LEGB

模块,包

编码规范

代码布局

  • 统一使用4空格缩进。不要用俩,不要用tab,更不要空格tab混用。
  • 每行最大长度79。如果长度超过79,可以看看变量名是不是太长了,能不能拆成多行,括号中的参数是可以拆成多行的,另外括号中的字符串也可以拆成多行,如:
       print(
           "Line1",
           "Line2"
       )  # ('Line1', 'Line2')

       print("Line1"
             "Line2"
             "Line3")  # Line1Line2Line3
  • 类和函数前空两行;类中的方法前空一行;其他地方逻辑无关段落之间空一行。

  • 模块内的顺序:(每部分之间要有一个空行)

    • 模块说明
    • 模块的文档字符串
    • 导入内置模块
    • 导入第三方模块
    • 导入自己开发的模块
    • 全局变量定义
    • 代码部分
  • 不要用一个import导入多个库,比如导入os和sys应该用:

       import os
       import sys
  • 如果采用from...import...的方式,可以一次导入多个库,如:
       from os.path import join, isfile
  • 导入库的时候注意名字冲突,如果自己定义的一个函数叫join,然后需要os.path.join,上面的导入方法就会出问题,解决方法:
       import os
       import os.path
       from os.path import join as builtin_join

空格的使用

  • 不要为了对齐增加空格。行末不要加多余的空格。文件末尾不要有空行。
  • 右括号前不要加空格。
  • 逗号、冒号、分号前不要加空格。
  • 函数的左括号前不要加空格。
  • 序列的左括号前不要加空格。
  • 操作符左右各加一个空格。
  • 函数默认参数使用的赋值符两边不要加空格。
  • 不要将多句语句写在同一行,不要使用分号。
  • if/for/while语句中,即使执行语句只有一句,也要另起一行。

注释

  • 块注释,在一段代码前增加的注释。注意:#后面有一个空格, 空行只有一个#。
       # Description : Module config.
       #
       # Input : None
       #
       # Output : None
  • 行注释,在一句代码后加注释。代码后面至少要有两个空格,然后#后要有一空格。如:
       print "Hello World"   # Need no comment
  • 不要加没用的注释。比如函数名已经很明确了,然后又在注释里解释了一下函数名,这个没有必要。
  • 模块、公共函数、类、方法的注释最好写文档字符串里边,而且最好按reStructuredText格式书写,这样可以通过工具导出成格式非常好的文档。

命名规范

新编代码须按下面命名风格进行,现有库的编码尽量原有风格。

  • 避免使用l、o这种容易混淆的单个字母
  • 包名中字母全部小写,不要包含下划线(package)。
  • 模块名中字母全部小写,单词间可用下划线(module_name)。
  • 类名单词首字母大写(ClassName),模块私有类以下划线开头(_ClassName)。
  • 异常命名使用CapWords+Error后缀的方式。
  • 尽量不要有跨模块的全局变量,模块内的全局变量前要加单下划线(_module_global_var
  • 函数名字母全部小写,可以使用下划线。
  • 常量命名使用全部大写的方式,可以使用下划线。
  • 类里边的方法和变量名字母全部小写,可以使用下划线。
  • 类的属性有3种作用域public、non-public和subclass API,可以理解成C++中的public、private、protected,non-public属性前,前缀一条下划线。

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

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

编码建议

  • 判断None True False用isis not。(不要用if a: 因为不能分清a是None,False,True或是其他的值)
  • 判断列表、字典、元组、字符串是否为空用if aif not a
  • 字符串连接不要用+,应该用"".join()(不同的python实现+的效率差别很大)
  • 检查字符串前缀或后缀时使用startswith()endswith()(不要用切片)
  • 对象比较应该用isinstance()
  • 字符串有两种str和unicode,这两种都继承自basestring,所以检查对象是不是字符串的时候应该用isinstance(a, basestring)
  • 不要使用try...except: pass, 这样会捕获所有异常,造成不好维护。另外try中的代码尽可能要少,不要把整段代码放到try里面,应该把出异常的那一句放到try里面。
  • 注意python2中的除法
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment