Python 编程摘要

几年前终于系统学了一下 Python,没有耐心看教程,东翻西查花大半天整理出来给自己速成了一下,只是个提纲,很多细节需要拿着关键词再查,分享给同样没有耐心的朋友……


Python 编程摘要

  -杨武 2018

  1. 背景: Guido van Rossum 1989年圣诞假期闲得没事儿干而为 Unix/C 背景的程序员设计的脚本语言,1991 年正式公开发行。
  2. 环境:学习语言可以考虑 Thonny IDE,Python 发行版中应该都自带有idle集成环境。工业界比较流行 PyCharm 和 Jupyter Notebook.
    目前 Python 有 2.7 和 3.x 两个主要的发行版,3.x 2009 年开始发行,对 2.x 不完全兼容。如果工作上并不依赖还没有适配 3.x 的库,建议学习、使用 3.x 。
    python 解释器都有交互模式,可以直接在命令行上使用。交互模式下,最后一个表达式的结果会保存在特殊变量 _ 里
    编写纯文本的程序,然后 python xxx.py 也可以执行。
    Unix/Linux 风格的脚本,可使用 #!/usr/bin/env python 这样的 unix shebang
  3. 安装:不管 Windows/Mac/Linux ,初学者均推荐 Anaconda, Mac 自带,但还是推荐 anaconda 或 virtualenv 避免环境污染
    1. 可以使用国内镜像加速包安装,如清华大学镜像(版权原因该镜像已停)
      1. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
      2. conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
      3. pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
      4. conda 用 —remove, pip 用 unset 移除镜像渠道
    2. 如果碰到 ssl 错误
      1. 出错信息:Could not connect to https://repo.continuum.io/pkgs/free/osx-64/....tar.bz2 Error: Connection error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590): https://repo.continuum.io/pkgs/free/osx-64/....tar.bz2
      2. 解决办法
        1. 找到证书存储位置,然后:conda config --set ssl_verify <pathToYourFile>.crt
        2. 禁用 ssl 校验(不安全):conda config --set ssl_verify false
  4. 语言
    1. 文法
      1. 一般语句不能跨逻辑行,物理行可以用末尾的 \ 字符连接成逻辑行
      2. 缩进表达逻辑结构,必须严格一致
        1. 行首空白的tab(制表符)将视多个空格,空格个数为将行首空格数补全为8的倍数
        2. 行首空白不要混用tab(制表符)和space(空格)
      3. 注释:#字符后面的是注释,程序执行时将被忽略,可以是单行也可以接在语句后面
      4. 源文件编码:Python3 默认为 utf-8,探测到 BOM 则强制 utf-8,可使用编码注释申明
        1. # -*- coding: utf-8 -*-
          1. 这个格式 GNU Emacs 也认识
        2. # vim:fileencoding=utf-8
          1. 这个格式 VIM 也认识
        3. 字符编码背景知识 中文编码小知识 - 知乎
      5. 标识符
        1. Python 2.x 标识符只能使用 ASCII 集中的大小写字母、_和数字
        2. Python 3.x 则支持 Unicode 集中的字母、数字和部分符号,完整清单见 https://www.dcl.hpi.uni-potsdam.de/home/loewis/table-3131.html
        3. 特殊意义的名字
          1. _开头的符号在 import * 时会忽略
          2. __id__ 是系统定义的名字
          3. __id 用于类私有名字,这种类属性会进行名字粉碎(name mangling)以防止冲突
    2. 命令行参数
      import sys;
      sys.argv 数组就是命令行参数
    3. 变量定义
      1. 赋值即定义:name = value
      2. 动态类型:赋值时推导类型,可以在不同时间保存不同类型的值
      3. 强类型:表达式的类型需要显式转换,不支持隐式转换
        1. 使用目标类型名为函数:int(var)
      4. 作用域
        1. 变量在申明的块内有效,不在任何块内的是全局变量
        2. 局部可以引用全局量作为右值
        3. 定义在局部块的名字屏蔽全局相同的名字
        4. 显式引入全局变量:global name
          1. 如果要修改全局变量,必须显式引入
          2. 否则是定义了一个新的同名局部变量
            1. 如果在定义时右值部分也引用到该名字,此时这个变量还没有赋值,会报错
              1. UnboundLocalError: local variable ‘name’ referenced before assignment
    4. 基本类型
      1. 数字:int, float, Decimal, Fraction, complex number (加 j 或 J 后缀)
        1. 字面量
          1. 9, 9.2, .1, 2.
          2. 2/8/十六进制:0b110 0O76 0xFE
          3. 字面量分段用_,可任意加,求值时忽略: 1_000_000
          4. 科学计数法格式:31.4e-2
        2. 算术运算:+ - * / **指数 //整除 %取余
        3. 比较运算:== != > < >= <=
        4. 赋值运算:= += -= *= /= %= **= //=
        5. 位运算:& | ^ ~ << >>
      2. 字符串(string):
        1. 定义
          1. 字面量用单引号或双引号包起来
          2. 转义序列:\ ,字符串加r前缀表示原始串不进行转义 r’c:\name’
          3. 二进制串:b’xyz’
            1. 只能使用ASCII字符
          4. 多行: 用一对 """或 ''' 包起来的多行文本
          5. 字面量是不可变的 (immutable)
        2. 运算
          1. 连接:字符串可以+ ,连续的字符串字面量会合并
            1. 重复并拼接:"#" * 8 得到 "########"
          2. 索引:name[idx],idx为负数时从末尾向前数,注意-0就是0 并不能取最后一个字符(最后一个字符是[-1])
          3. 切片:name[from:to], [from]~[to-1] 的子串,省略from时从0开始,省略to时到末尾结束。方便起见from/to可视为指向字符之间,比较容易搞清楚切片范围。
          4. .replace(fromStr, toStr)
      3. 逻辑(布尔)类型
        1. 字面量:True, False
        2. 运算:
          1. and or not
          2. 成员运算:in, not in
            1. if var in (‘a’, ‘b’, ‘c’)
          3. 身份运算:is, is not
            1. 引用的是否是同一个对象
            2. 区分:== 是比较引用变量的值是否相等,但引用的可能2个对象
    5. 复合类型
      1. tuple 多元数
        1. 由逗号分隔的若干个值
        2. 定义
          1. t = 1, 2, “a”
          2. ( v1, v2, v3, … )
          3. 可嵌套
          4. 解包赋值:x,y,z = t
          5. tuple(expr):每个list成员或string字符转化为一元
        3. 运算:
          1. tuple+tuple, tuple*int
          2. len(tuple)
          3. del tuple #执行之后该变量就未定义了
          4. cmp(t1,t2), 返回值:0-等长,1-t1长,-1-t1短
          5. max(t), min(t):取出元组中最大/小的元素
      2. 列表 (list)
        1. 字面量:[ 1, 2, 3 ] 方括号内由逗号分隔的一系列值
        2. 跟字符串一样可以索引、切片
        3. 列表字面量是可变的 (mutable)
          1. list[idx] = newValue
          2. list.append( value )
        4. 列表可嵌套,即某个元素是另一个列表
        5. 操作:
          1. .append(x), .extend(itr), .insert(i, x), .remove(x), .pop([i]),  .clear(),
            1. .popleft() 是 deque 特有的
          2. .index(x[,start[,end]]), #在范围内找x出现的位置
          3. .count(x), #数x出现的次数
          4. .sort(key=None,reverse=False),
          5. .reverse(), .copy()
          6. del 语句:del list[idx] 删除该元素
        6. List Comprehension (列表推导式/列表解析式/列表生成式)
          1. 用来构造列表的简洁表达
          2. [expr for name in range]
            1. 用 for 语句遍历 range 范围取得 name 的每一个值,传进 expr里对name的引用 ,expr 的值做为元素追加到结果列表里
          3. 可嵌套:expr 部分可以是另一个生成式
            1. 执行时,最右的生成式相当于循环的最外层
      3. 集合 (set)
        1. 字面量:{ val1, val2, … }
          1. 空集要用 set() 构造,{} 是空字典
          2. 同列表一样支持生成式
        2. 定义:s = set()
        3. 操作:
          1. s[index]
          2. .add(one), .update(collection)
          3. .remove(e), .discard(e) # e不存在前者会异常
          4. .pop() 弹出最早加入的成员
      4. 字典 (dictionary)
        1. 字面量:{ key:value, key:value, … }
          1. tuple 也可以做为 key,如果其中只包含strings, numbers, or tuples
        2. 操作
          1. .keys()
          2. d[key]=value
          3. in, not in:作用于 key
        3. 同样支持生成式
    6. 语句
      1. Python 使用缩进决定代码的层次结构
      2. if 语句
        1. if bool_expr:
              statements
          elif expr:
              statements
          else:
              statements
      3. for 语句
        1. for var in expr:
              expr
        2. range expr
          range( from, to, step )
        3. 流程控制子句
          1. break;
          2. continue;
          3. for-else: 循环结束且没有 break 过时执行
      4. while bool_expr: 当 bool_expr 计算结果为 True 时重复执行下属的语句块
      5. pass 显式说明这里啥也不干
      6. with
        1. with xxx: 为下级语句块定义一个作用域, xxx 部分返回 ContextManager
          1. 进入作用域时自动调用 contextManager.__enter__(),
          2. 作用域结束时自动调用其 __exit__()
        2. 系统库的许多方法返回对象都是 ContextManager
          1. File, zipfile.ZipFile, subprocess.Popen, tarfile.TarFile, telnetlib.Telnet, pathlib.Path
        3. contextLib
          1. @contextmanager decorator
            1. 所修饰生成器(generator function)的代码行 yield 之前是 __enter__(), 之后是 __exit__()
          2. contextlib.ContextDecorator
            1. 继承该类定义,重载 __enter__(self), __exit__(self, *exc)
            2. 获得自定义修饰器 @myclass()
      7. 标准 I/O
        1. input(prompt)
        2. print(arg… end=‘’)
          1. str() 可转换任何类型为可读字符串
          2. repr() 可转换任何类型为解释器可读字符串
        3. 文件读写
          1. f = open(path, mode) #r,w,a,+,b
            1. 推荐的安全写法:
              with open(path) as f:
                  read_data = f.read()
              即使有异常,离开 with block 时文件也会安全关闭
          2. f.read(), f.readline(), f.write(expr), f.tell(),
          3. f.seek(ofs, from): from 0=开头向后 1=当前位置向后 2=末尾向前
          4. f.isatty(), f.truncate()
          5. 行遍历:
            for line in f:
                print(line)
    7. 表达式
      1. Lambda 表达式
        1. 定义:lambda param: expr
        2. 相当于匿名函数,但只能包含一个表达式,不能包含语句和注解(annotation)
        3. 所含表达式执行时求出的值就是lambda的值
      2. 运算优先级由低到高:逻辑->成员->身份->赋值->比较->位->算术
      3. 序列比较:短的小,同长度逐个元素比较字典序(lexicographical)
    8. 代码单元
      1. 函数 (function)
        1. def funcName(formalParameters):
              """ 可选的多行 docstring """
              statements
        2. 参数
          1. 定义时
            1. 参数列表用逗号分隔
            2. 默认值: param1=expr,提供了默认值的参数在调用时可以不指定值
            3. 带星参数(starred parameter):表示调用时这一个形参名将接收后续的若干参数值
              1. *name:从这个位置往传入的参数值组成一个 tuple
                1. 实现可变参数列表
              2. **name:形参末尾的这个参数将会收到一个dictionary,其中存有所有调用时用keyword arguments方式传入且不对应其它形参的参数值
              3. *name 必须出现在 **name 之前
            4. 注解:函数参数和返回值都可以加注解
              1. 参数:在形参名后加 : expr,用 paramName.__annotations__ 读
              2. 返回值:在) 和 : 之间加 -> expr,用 funcName.__annotations__读
          2. 调用时
            1. 参数值(arguments)是传值的 (call-by-value)
            2. 参数都是对象引用,所以传递的是对象引用的值,而不是对象本身的值
            3. 可用形参名做为关键字指定要传给特定参数的值(keyword arguments):print(‘abc’, end=‘;’)
            4. 展开参数列表:*list_expr 会将list中的元素展开并依次传给函数参数
        3. 返回值
          1. return value;
            1. 省略 value 则返回特殊值 None
          2. 即使不写 return 也有返回值 None
        4. 函数本身也是对象,函数名也是一个变量
        5. first-class-function
          1. 函数名本身的值是对函数这个对象的引用
          2. 引用值可以赋给任意变量,该变量即可做为函数调用
        6. 匿名函数
          1. 即lambda表达式
        7. 函数式编程范式
          1. 高阶函数: 接收其他函数作为参数的函数
          2. 内置 map()/reduce()/filter()
          3. 闭包 closure
            1. 在函数内可以定义函数,并可作为返回值
            2. 内部函数可以引用外部函数的变量
              1. 引用的是符号,而不是当前值
              2. 所引符号会在闭包执行时,取那一刻的当前值
              3. 如果引用循环变量,只会取到相同的循环结束时的值
          4. 柯理化 currying
        8. 协程 coroutine:Python 3.5 实现了PEP492
          1. 异步函数: async def fname…,内部可以使用await 表达式、async for 和 async with 语句
          2. await 表达式:await expr,expr 通常是对协程的调用
          3. async for 语句
          4. async with 语句
        9. 类型提示 : Python 3.7 实现了 PEP484
          1. def func(arg: type) -> returnType
          2. 类型别名:alias = type 例如Url = str
          3. 使用 None:-> None 相当于 ->type(None)
          4. Callable 类型:用来提示只接受特定的函数签名
            1. Callable[arg1Type, arg2Type...]
          5. 范型 generic
            1. from typing import Mapping, Set
            2. 提示特定元素类型的容器类型:Set[elemType], Mapping[keyType, valueType]
            3. TypeVar factory:typing模块新加了这个工厂方法
              1. T = TypeVar('name') : 接受任意类型
                1. def first(Sequence[T]) -> T 返回类型为容器元素类型
              2. T = TypeVar('name', Text, bytes) : 接受指定的基本类型,基本类型也就是不能是参数化的
            4. Any 可以用来表示任意类型
      2. 类 (Class)
        1. 定义
          class Name:
               ”””可选的 docstring ”””
              statements
          1. 变量赋值语句:即定义属性并初始化
          2. 定义函数: 即定义方法,第一个参数应为 self
            1. __init__() 是实例初始化方法,在每个实例创建时被调用
              1. __init(self, …) 可以接收参数
            2. __new__(cls, *args, **kargs) 重载可控制实例构造过程
            3. 使用特定名字的函数实现操作符重载
              1. + __add__(self, other), - __sub__
              2. [idx] __getitem__(self,idx)/__setitem__(self,idx,val)
              3. 完整清单: https://docs.python.org/3/reference/datamodel.html#special-method-names
          3. 可见性:Python 没有可见性控制,惯例 _ 开头的成员是内部接口, 外部不应使用
        2. 实例化
          1. obj = ClassName()
        3. 对象模型
          1. 类上的属性:所有实例共享的类属性
          2. __init__() 里 self.name 定义的属性:实例私有的属性
          3. 实例上可以随时添加属性
        4. 继承
          1. class Name(BaseClassName):
          2. 检查:isinstance(obj, cls), issubclass(sub, base)
          3. 多重继承:class Name(B1, B2, B3):
        5. 迭代器支持
          1. for-in 会对序列容器对象调用 iter(c) 获取迭代器
          2. 然后调用 i.__next__() 取下一个
            1. 可用内建函数 next(it) 来调用 it.__next__()
            2. 遍历超出后会抛出 StopIteration
      3. 生成器 (generator)
        1. 定义跟函数一样,内部使用 yield 语句返回值
          1. 解释器会记录 yield 点
          2. 并在 g.next() 调用时,从 yield 点之后继续执行
        2. 实现
          1. 本质上还是个迭代器
          2. 解释器会自动生成 __iter__() 和 __next__(),自动在完成后抛出 StopIteration
          3. 局部变量在调用之间会自动保存
        3. Generator Expression
          1. 跟 List Comprehensions 类似,不过不是[ ]里而是在 ( ) 间
          2. 例如: sum(i*i for i in range(10))
      4. 模块
        1. 定义模块:任意.py文件
          1. __name__
            1. import 时为模块文件名
            2. 通过python做为程序执行时,__name__ 会是 “__main__”
          2. 顶层代码为初始化代码,在引入时会执行
          3. 每个模块的符号表是私有的,定义全局变量不会冲突,使用者需要用 module.var 引用
        2. 使用模块
          1. import name 引入到当前模块中
          2. from module import symbol_list 可将指定符号加到当前模块中
            1. 符号由逗号分隔
            2. * 表示全部符号
          3. 以上是全局查找,相对路径引用见下面6.2/6.3
          4. from __future__ import xxx
            1. 这个称为 future statement,不是常规模块
            2. https://docs.python.org/3/reference/simple_stmts.html#future-statements
            3. 用以引进未来版本的新特性,在编译时特殊处理,可以改变关键词的解释
            4. 需要写在在程序文件最开始
            5. import __future__ [as name] 只是普通模块引用语句
        3. 模块查找路径
          1. built-in
          2. sys.path
            1. input script所在的目录
            2. PYTHONPATH 环境变量
            3. 安装路径中的默认位置
            4. 程序可以修改这个变量,影响当前进程内的查找过程!
        4. 编译和缓存
          1. 默认会在 __pycache__ 目录按 module.pythonversion.pyc 文件名保存编译过的模块
          2. compile all 模块可以为目录下的所有模块生成 .pyc 文件
          3. pyc文件可以脱离源码发行,没有源码时 python 不会使用缓存
        5. 标准模块
          1. sys 模块内建在每个python解释器里
            1. sys.ps1, sys.ps2, sys.path
          2. dir() 内建函数:可列出模块中定义的名字
            1. 为指定模块时,则列出当前有定义的所有名字
        6. package 包管理机制
          1. 定义
            1. package 是一个目录,里边有 __init__.py 文件
            2. __init__.py 可以为空,也可以用 __all__ 列表发布所有的名字
              1. from m1.m2 import * 时,如果 __all__ 则引入其中所有的名字
                1. 否则只引入模块里的全部名字,不会递归处理子模块
          2. 模块的名字空间可以嵌套,用 A.B 来访问
            1. import sound.effects.echo 对应 sound/effects/echo
          3. 包间引用
            1. 绝对引用:子模块需要引用其它模块时,可以始终用完整模块名字空间路径
            2. 相对引用:但也可以用相对路径指示对应的模块
              1. from . import m
              2. from .. import m
              3. from ..filters.abc import m
        7. 常用模块
          1. dir(module);
            1. help(module);
          2. import json;
            1. json.dumps(o[, f]);
            2. json.load(f)
          3. import os;
            1. os.getcwd();
            2. os.chdir(path);
            3. os.system(‘cmd’);
          4. import shutil;
            1. shutil.copyfile(fromPath, toPath);
            2. shutil.move(fat);
          5. import glob;
            1. glob.glob(‘*.py’)
          6. import sys;
            1. sys.argv .stdin, .stdout, .stderr
          7. import re;
            1. re.findall(r’regexpr’, str);
            2. re.sub(r’regexpr’, r’repo’, str)
          8. math.cos(n), random.random()
          9. statistics
            1. .mean(d), .median(d), .variance(d)
          10. from urllib.request import urlopen;
            1. with urlopen(url) as resp:
                  for line in response
                      line = line.decode(‘utf-8’)
          11. import smtplib
            1. server = smtplib.SMTP(host)
            2. server.sendmail(…)
            3. server.quit()
          12. datetime.date.tody()
          13. import zlib
            1. t = zlib.compress(text)
              1. len(str)
            2. .decompress(zs)
            3. .crc32(s)
          14. from timeit import Timer
            1. Timer(stmt_literals).timeit()
        8. 环境管理
          1. 虚拟环境(virtual env)
            1. python3  自带 venv 模块
            2. python3 -m venv name
            3. source name/bin/activate
              1. name\Scripts\activate.bat for Windows
          2. pip 包管理
            1. 默认从 https://pypi.python.org/pypi 安装包
            2. pip search name
            3. pip install [--upgrade] name[==version]
            4. pip uninstall name
            5. show name; list; freeze > requires.txt
              1. pip install -r requires.txt 可在别处装全这些依赖
            6. 使用 Anaconda 发行版时,尽量避免混用conda install 和 pip install,只有 conda 不提供的包才 pip 安装
    9. 异常处理
      1. 区分异常与语法错误:异常是语法正确但运行时有问题。
      2. 异常处理语法
        1. try:
              statements
          except ValueError as ename: #
              statements
              raise #再抛出
          except (Err1,Err2):
              pass
          finally: #clean-up actions
              statements
      3. 抛出异常:raise ValueError(msg)

语言基础有了,要系统学习编程的数据结构与算法,http://interactivepython.org/runestone/static/pythonds/index.html 是一个非常好的资源

Jupiter Notebook tips

tab/shift-tab for code intelligence

%config IPCompleter.greedy=True

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值