原文链接:https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000
感谢廖老师精彩的Python教程,收益良多,感谢感谢!
整理笔记,以备后续复习,第一部分一直到模块结束,整理如下,其中大量的单引号是有问题的,由于word直接打的,嫌麻烦,没有都进行修正,请见谅
1、a = ‘XYZ’ 的过程是先在内存中创建一个’XYZ’字符串,然后创建一个名为a的变量,并指向’XYZ’
2、布尔值:True 和 False ,注意大小写
3、空值:None
4、变量本身类型不固定称为动态语言
5、常量 就是不能变的变量,python中通常用全部大写表示名字表示一个常量,但是其本身任然是个变量,你想改也没人拦得住
6、除分两种,/ 这种得到的结果是浮点数 // 地板除,类似于取整 %求余
7、输出,print(‘AB’, ‘LOVE’, ‘CD’) 输出结果是AB LOVE CD
8、输入 name = input()
9、每一行都是一个语句,语句以:结尾的是一个语句块
10、始终坚持四个空格
11、python大小写敏感
12、用print(r‘\t’) 这样可以不用转义字符了,不然需要转义
13、用’’’ 可以标识输出多行 print(‘’’ line1
Line2’’’)
14、字符编码,最开始英文的时候ascii(一个字节), 中文GB2312, 所有的 (各国语言)unicode(一般是两个字节表示一个字),然后节约精神导致了utf-8:可变长编码,英文1个字节,中文一般三个字节,很生僻的4-6(主要如果是全英文的话,用unicode太浪费了)
所以,当传输的文本中有大量的英文字符,那就用utf-8
15、内存中都是unicode的编码方式,当保存磁盘或者传输时,转成uft-8
16、如从记事本中读入内存又写回,是先从文本读取utf-8,转成unicode到内存,编辑完成后,保存的时候,又转成uft-8
17、python3里面都是unicode的 ord()获取字符整数表示,chr()编码转换成对应字符串
\u4e2d表示的是unicode的编码形式,ord()后得到的值就是unicode对应的值的十进制表示
18、根据上一条,如果要在网络上传输或者存入磁盘,就涉及到str和bytes的转换
bytes可以用b’ABC’表示 str通过encode()转成指定编码的bytes
如:’ABC’.encode(‘ascii’) 或 ‘中文’.encode(‘utf-8’)
如果从网络上读取了字节流或磁盘读取了数据,读取的是bytes,变成str要用decode
如:b’ABC’.decode(‘ascii’) 或b‘\xe4\xb8\xad’.decode(‘utf-8’, errors=’ignore’) errors不是必须的,写了可以忽略错误字节
19、计算str中包含的字符,用len(),如果是bytes类型的话,len()计算的是字节数
20、python头,指定是可执行程序和指定编码
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
21、格式化 占位符:%s 字符串 %d 整形 %f 浮点型 %X 十六进制
还可以指定补0和宽度限制%04d 宽度是4,不够的补充0
%.9f 小数点后保留9位
%% 输出百分号
22、另一种格式化 format()
23、增长百分比,计算公式是(当前-之前)/之前
24、如果没有特殊要求,转换的时候,牢记使用utf-8
25、list 有序集合,可以下标访问,len获取元素个数,最后一个可以用-1做索引,-2等类似
append()追加到最后clas.append(‘ee’)
insert()指定到索引的位置 clas.insert(2, ‘cc’) #切记是从0开始的,2指的是第三个位置
pop()删除末尾
pop(i)删除指定位置
赋值给对应下标直接把对应下标值替换掉
list里面的元素类型可以不一样 L = [‘app’, 111, True]
list元素可以是一个list M = [[1, ‘bb’], ‘aaa’, L]
26、tuple 和list类似,但是一旦初始化就不能修改
classmates = (‘aa’, ‘bb’, ‘cc’)
只有一个元素的tuple,要用clss = (1,) 切记一定要加逗号,否则会被当成计算结果的
cla = (‘A’, ‘B’, [C, D]) tuple里面的list的值是可以变的 也就是cla[2][0] cla[2][1]可变,所谓的不可变是指向不可变,但是list本身可变,所以还是可以变化
由于tuple不可变,所以代码更安全,能用tuple代替list就代替
27、判断 if elif else,切记后面都要加冒号
if age >= 6:
do something
elif age >18:
do something
else:
do something
28、input()返回的都是str,所以如果是输入的int类型的,那就要用int(s)转一下
s = input(‘birth:’)
birth = int(s)
29、循环
for x in names:
range(n) 生成从0 到 n-1的序列
while 条件:
30、break提前跳出循环 ,continue跳过本次,直接开始下一次
31、dict 字典,其他语言中的map,使用键值(key-value)存储
d = {‘AA’:11, ‘BB’:22, ‘CC’:33}
d[‘DD’] = 44 直接就把新的key加进去了
d.get(‘AA’) 不存在返回None 可以指定当不存在时候的返回值 d.get(‘AA’, -1)
pop(key) 删除指定key-value对
dict内部存放的顺序和key放入的顺序无关
32、dict 比较 list 优点,查找插入快,不会随着key增加而变慢,缺点是占用内存大
dict 空间换时间,可以用在需要高速查找的地方
dict的key是不可变对象,因此可以用字符串、整数做key,不能用list做key
33、set 和dict类似,一组key的集合
创建,需要提供list作为输入集合 s = set([1,2,3]) key是不能重复的,加了重复的相当于没加
add(key)可以添加元素到set
s = set([1,2,3])
s.add(4)
remove(key) 删除元素
set相当于集合,可以做交、或
s1 = set([1,2,3])
s2 = set([2,3,4])
s1 & s2
s1 | s2
34、不可变对象
对于不变对象来说,调用对象自身的任意方法,都不会改变对象自身的内容,相反,这些方法会创建新的对象并返回,所以不可变对象永远不可变
35、数据类型转换 int() float() str() bool()
36、函数名也可以赋值给一个变量 如 a = abs a(-1) 相当于给函数起了个别名
37、定义一个什么事情都不做的空函数,可以用pass语句
def nop():
pass
38、isinstance() 可以判断第一个参数是不是第二个参数里面的类型,第二个参数可以是个tuple
eg: isinstance(x, (int, float))
39、python返回多个值的时候,其实是返回的一个tuple,只是语法上一个tuple可以省略括号
40、函数执行完毕,也没有return 则 自动 return None
42、可以指定默认参数,必须必选参数在前,默认参数在后
def power(x, y=2, z=4)
也可以不按顺序提供部分默认参数
power(1, z=5)
43、默认参数大坑,一定不能指向可变的参数,如list
eg:def add_end(L = []):
L.append(‘END’)
return
可以更改成如下:
def add_end(L = None):
if L is None:
L = []
L.append(‘END’)
return L
44、不变对象的优势
不能改,发生错误的可能大大降低
多任务的时候,可以同时读
45、可变参数,定义参数的个数可变的函数
def calc(*number): 这样就可以了
46、如果已经有了一个list或者tuple,直接调用calc(*nums) 即可
47、关键字参数 ** 可以提供dict类型的参数
48、命名关键字参数
def person(name, age, *, city, job): 只接收city和job作为关键字的参数
49、任意函数,都可以通过类似func(*args, **kw)形式调用,无论参数如何定义
50、*args是可变参数,接收tuple
**kw是关键字参数,接收dict
51、切片 L = [‘AA’, ‘BB’, ‘CC’]
L[0:3] 从0开始取,但是不包括3 获取的是0 1 2
0可以省略,同时也可以倒数取值 L[-2:]
倒数第一个元素的索引是-1
所以后10个是L[-10:]
还可以前10个,每两个取一个 L[:10:2]
L[::5] 所有的每五个取一个
L[:] 原样赋值
52、使用切片写trim() 去除头尾的空格
def trim(s):
while(s[:1] == ‘ ’):
s = s[1:]
while(s[-1:] == ‘ ’):
s = s[:-1]
return s
53、迭代
给定一个list或者tuple,我们通过for循环遍历,这种遍历称为迭代
54、dict的迭代
dict默认迭代的是key for key in d:
dict想迭代value for value in d.values()
dict想两个都迭代 for k,v in d.items()
55、判断一个对象是可迭代对象,用collections 的Iterable类型判断
from collections import Iterable
isinstance(‘abc’, Iterable)
56、list想同时迭代索引(下标)和元素本身
for i,v in enumerate([‘A’, ’B’, ’C’])
print(i, v)
输出的结果会是 0 A\n1 B\n2 C(回车用\n代替了)
57、列表生成式List Comprehensions,可以创建list的生成式
[x * x for x in range(1,11)] 能生成 [1,4,9,…,100]
注意:range是不包括最右边的边界的
58、可以加上if判断,筛选出你想要的
[x * x for x in range(1,11) if x%2 == 0] 这个结果是仅偶数的平方
59、两层循环生成全排列
[x+y for x in ‘ABC’ for y in ‘XYZ’]
60、列出当前目录下所有文件和目录名
import os
[d for d in os.listdir(‘.’)]
61、列表生成式也可以使用两个变量生成list
d = {‘x’: ‘A’, ‘y’:’B’}
[x + ‘=’ + y for x, y in d.items()]
62、所有list变小写
L = [‘Hello’, ‘World’]
[s.lower() for s in L]
63、L2 = [s.lower() for s in L1 if isinstance(s, str)] 只处理是str的防止出错
64、生成器,一边循环一边计算的机制 generator
65、生成器创建方法一
生成式的中的[] 变为()
打印每一个元素使用next() ,eg:next(a) 最后抛出StopIteration错误无法继续
或者for循环,因为generator也是可迭代对象
66、yield 定义generator的另一种方法,函数定义中包含yield-》generator
调用的时候还是用for循环
67、可以直接作用于for循环的对象统称为可迭代对象Iterable
list tuple dict set str 都是Iterable
68、可以被next()函数调用并不断返回下一个值的对象成为迭代器Iterator
生成器都是Iterator对象,但是list dict str虽然是Iterable,但不是Iterator
变成Iterator 可以用iter()函数
69、Iterator对象表示的是一个数据流,是惰性的,只有需要返回下一个数据的时候才计算
70、python的for循环本质上是通过不断调用next()函数实现的
71、函数名也是变量
f = abs
f(-1)
72、abs函数实际上是定义在import builtins模块,更改abs后,想让abs变量的指向在其他模块也生效
用import builtins;builtins.abs = 10
73、传入函数,一个函数接收另一个函数作参数,这种函数称为高阶函数
def add(x,y,f):
retrun f(x) + f(y)
74、编写高阶函数,就是让函数的参数能够接收别的函数
75、把函数作为参数传入,这样的函数成为高阶函数,函数式编程就是指这种高度抽象的编程范式
76、map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的参数一次作用到序列的每个元素,并把结果作为新的Iterator返回
map()第一个参数是f,即函数对象本身,返回的是Iterator,所以用list()函数转换下,可以把结果返回成list
def f(x):
return x * x
r = map(f, [1,2,3])
list(r)
77、map()作为高阶函数,把运算规则抽象了,比如把list所有数字转字符串
list(map(str, [1, 3, 4]))
78、reduce() 作用在一个序列[x1, x2, … ]上,函数接收两个参数,reduce把结果序列和序列的下一个元素累计
reduce(f, [x1, x2, x3]) = f(f(x1, x2), x3)
79、序列求和
from functools import reduce
def add(x, y):
return x+y
reduce(add, [1, 3, 5, 7, 9])
80、[1, 3, 5, 7]转成整数1357
from functools import reduce
def fn(x, y):
return x * 10 + y
reduce(fn, [1, 3, 5, 7])
81、str转int
from functools import redece
def fn(x, y):
return x * 10 + y
def char2int(s):
digits = {'0': 0, '1': 1, '2': 2, '3': 3,'4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
return digits[s]
reduce(fn,map(char2int, ‘123675’))
82、上面的整理成函数(函数里面可以嵌套函数)
from functools import reduce
DIGIT = {'0': 0, '1': 1, '2': 2, '3': 3,'4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
def str2int(s):
def fn(x,y):
return x * 10 + y
def char2int(c):
return DIGIT[c]
reduce(fn, map(char2int, s))
上面还可以用lambda函数做一个简化
83、**表示乘方
eg 10 **3 #表示10的3次方
84、filter()用于过滤序列,也接收一个函数,一个序列,作用于每个元素,根据True还是False决定留还是丢,如下删掉偶数
def is_odd(n):
return n%2 == 1
list(filter(is_odd, [1, 2, 3, 4]))
85、删掉空字串
def not_empty(s):
return s and s.strip()
list(filter(not_empty, [‘A’,’ ’, ‘C’, ‘ ’]))
86、生成素数
首先生成所有从3开始的奇数
def _odd_iter():
n = 1
while True:
n = n + 2
yield n
定义一个筛选函数
def _not_divisible(n):
return lambda x:x %n > 0
最后,定义一个生成器,生成素数
def primes():
yield 2 #先生成个2,因为素数队列是从3开始的
it = _odd_iter() #初始序列
while True:
n = next(it)
yield n
it = filter(_not_divisible(n), it)
87、判断回数
def is_palindrome(n):
return str(n) == str(n)[::-1] #取反操作,牛掰
89、排序算法sorted(),也是高阶函数,可以接收一个key函数来实现自定义的排序
sorted([-1, 2,6,-3], key=abs)
结果[-1, 2, -3 ,6]
key指定的函数会作用于list的每一个元素上,并根据key函数返回结果排序,然后用sorted()函数按照新的list排序,然后按照对应关系返回list相应的元素
90、实现忽略大小写的排序
sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower)
91、反向排序,加上第三个参数reverse=True
sorted(['bob', 'about', 'Zoo', 'Credit'], key = str.lower, reverse=True)
92、函数作为返回值
def lazy_sum(*args):
def sum():
ax = 0
for n in args:
ax = ax + n
return ax
return sum #直接把函数返回了
使用的时候, f = lazy_sum([1,2,3,7,9]) 这时候不计算,只是返回个函数
调用f() 才计算
内部函数可以引用外部的参数和局部变量,每次调用都会返回新的函数
93、函数中定义函数,内部函数可以引用外部函数的参数和局部变量,当外部函数返回内部函数时,相关的参数和变量都保存在返回的函数中,这种程序结构称为闭包
94、返回闭包的时候,要牢记一点,返回函数不要引用任何循环变量,或者后续会发生变化的变量(因为返回的函数是到调用的时候才执行的,如果之前变量有变化,那结果也会变)
95、如果非得调用变量,那么再定义一个函数,把参数绑定到循环变量当前的值
def count():
def f(j):
def g():
return j * j
return g
fs = []
for i in range(1, 3):
fs.append(f(i))
return fs #返回一个函数的list
96、匿名函数lambda,限制是只能有一个表达式,不用写return
好处是不用担心函数名冲突
可以把匿名函数赋值给一个变量,后续可以调用变量
可以把匿名函数作为返回值返回
def build(x,y):
return lambda: x*x + y*y #这里就不用加参数了
97、在代码运行期间动态增加功能的方式,称为“装饰器” Decorator,就是重新定义这个函数
def log(fn):
@functools.wraps(fn)
def wrapper(*args, **kw):
print(“%s run” % fn.__name__)
return fn(*args, **kw)
return wrapper
98、偏函数Partial (偏爱,把偏爱的参数给固定死)把一个函数的某些参数固定住(设置上默认值),返回一个新的函数
import functools
int2 = functools.partial(int, base=2) #直接就变成了int 2默认2进制转换。
99、模块
一个abc.py文件就是一个名字叫abc的模块,xyz.py文件是一个名字叫xyz的模块
如果这两个模块和其他的模块名冲突了,我们可以通过包来组织模块,避免冲突,方法为选择一个顶层包名,按照如下目录存放:
mycompany
|-- __init__.py #必须存在,否则,Python会把目录当成普通目录,而不是包
|-- abc.py
|-- xyz.py
引入包后,只要顶层包名不和别人冲突,那所有模块都不会冲突
abc.py模块名变为mycompany.abc
xyz.py模块名变为mycompany.xyz
__init__.py 本身就是一个模块,模块名为mycompany ,可以是空文件
自己创建的模块不能和Python自带的模块名称冲突,检查方法直接在Python交互环境执行import abc,若成功则说明系统存在此模块
100、要添加自己的搜索目录,两种方法
第一种直接修改sys.path,该方法运行时修改,运行结束失效
import sys
sys.path.append(‘/users/Michael/my_py_scripts’)
第二种设置环境变量PYTHONPATH