python 知识回顾
Posted 风水涣
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 知识回顾相关的知识,希望对你有一定的参考价值。
一 数据类型
1 数字
整型与浮点型
#整型int
作用:年纪,等级,身份证号,qq号等整型数字相关
定义:
age=10 #本质age=int(10)
#浮点型float
作用:薪资,身高,体重,体质参数等浮点数相关
salary=3000.3 #本质salary=float(3000.3)
#二进制,十进制,八进制,十六进制
其他数字类型(了解)
#长整形(了解)
在python2中(python3中没有长整形的概念):
>>> num=2L
>>> type(num)
<type \'long\'>
#复数(了解)
>>> x=1-2j
>>> x.real
1.0
>>> x.imag
-2.0
2 字符串
#作用:名字,性别,国籍,地址等描述信息
#定义:在单引号\\双引号\\三引号内,由一串字符组成
name=\'egon\'
#优先掌握的操作:
按索引取值(正向取+反向取) :只能取
切片(顾头不顾尾,步长)
长度len
成员运算in和not in
移除空白strip
切分split
循环
3 列表
#作用:多个装备,多个爱好,多门课程,多个女朋友等
#定义:[]内可以有多个任意类型的值,逗号分隔
my_girl_friends=[\'laoyi\',\'laoer\',\'laosan\',4,5] #本质my_girl_friends=list([...])
或
l=list(\'abc\')
#优先掌握的操作:
按索引存取值(正向存取+反向存取):即可存也可以取
切片(顾头不顾尾,步长)
长度
成员运算in和not in
追加
删除
循环
#ps:反向步长
l=[1,2,3,4,5,6]
#正向步长
l[0:3:1] #[1, 2, 3]
#反向步长
l[2::-1] #[3, 2, 1]
#列表翻转
l[::-1] #[6, 5, 4, 3, 2, 1]
4 元组
#作用:存多个值,对比列表来说,元组不可变(是可以当做字典的key的),主要是用来读
#定义:与列表类型比,只不过[]换成()
age=(11,22,33,44,55)本质age=tuple((11,22,33,44,55))
#优先掌握的操作:
按索引取值(正向取+反向取):只能取
切片(顾头不顾尾,步长)
长度
成员运算in和not in
循环
5 字典
#作用:存多个值,key-value存取,取值速度快
#定义:key必须是不可变类型,value可以是任意类型
info={\'name\':\'laoyi\',\'age\':18,\'sex\':\'male\'} #本质info=dict({....})
或
info=dict(name=\'laoyi\',age=18,sex=\'male\')
或
info=dict([[\'name\',\'laoyi\'],(\'age\',18)])
或
{}.fromkeys((\'name\',\'age\',\'sex\'),None)
#优先掌握的操作:
按key存取值:可存可取
长度len
成员运算in和not in
删除
键keys(),值values(),键值对items()
循环
#利用setdefault解决重复赋值
\'\'\'
setdefault的功能
1:key存在,则不赋值,key不存在则设置默认值
2:key存在,返回的是key对应的已有的值,key不存在,返回的则是要设置的默认值
d={}
print(d.setdefault(\'a\',1)) #返回1
d={\'a\':2222}
print(d.setdefault(\'a\',1)) #返回2222
\'\'\'
s=\'hello alex alex say hello sb sb\'
dic={}
words=s.split()
for word in words: #word=\'alex\'
dic.setdefault(word,s.count(word))
print(dic)
#利用集合,去掉重复,减少循环次数
s=\'hello laoda laoda say hello sb sb\'
dic={}
words=s.split()
words_set=set(words)
for word in words_set:
dic[word]=s.count(word)
print(dic)
6 集合
#作用:去重,关系运算,
#定义:
知识点回顾
可变类型是不可hash类型
不可变类型是可hash类型
#定义集合:
集合:可以包含多个元素,用逗号分割,
集合的元素遵循三个原则:
1:每个元素必须是不可变类型(可hash,可作为字典的key)
2:没有重复的元素
3:无序
注意集合的目的是将不同的值存放到一起,不同的集合间用来做关系运算,无需纠结于集合中单个值
#优先掌握的操作:
长度len
成员运算in和not in
|合集
&交集
-差集
^对称差集
==
>,>= ,<,<= 父集,子集
7 数据类型总结
按存储空间的占用分(从低到高)
数字
字符串
集合:无序,即无序存索引相关信息
元组:有序,需要存索引相关信息,不可变
列表:有序,需要存索引相关信息,可变,需要处理数据的增删改
字典:无序,需要存key与value映射的相关信息,可变,需要处理数据的增删改
按存值个数区分
标量/原子类型 | 数字,字符串 |
容器类型 | 列表,元组,字典 |
按可变不可变区分
可变 | 列表,字典 |
不可变 | 数字,字符串,元组 |
按访问顺序区分
直接访问 | 数字 |
顺序访问(序列类型) | 字符串,列表,元组 |
key值访问(映射类型) | 字典 |
二 匿名函数
1. 什么是匿名函数?
匿名就是没有名字
def func(x,y,z=1):
return x+y+z
匿名
lambda x,y,z=1:x+y+z #与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字
func=lambda x,y,z=1:x+y+z
func(1,2,3)
#让其有名字就没有意义
匿名函数有个限制,就是只能有一个表达式,不用写return
,返回值就是该表达式的结果。
2. 有名字的函数与匿名函数的对比
#有名函数与匿名函数的对比
有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能
匿名函数:一次性使用,随时随时定义
应用:max,min,sorted,map,reduce,filter
它语法简单,简化代码,不会产生命名冲突,污染命名空间。即用即抛。
三 闭包,装饰器、生成器、迭代器
闭包
一 什么是闭包?
#内部函数包含对外部作用域而非全局作用域的引用
#提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路
def counter():
n=0
def incr():
nonlocal n
x=n
n+=1
return x
return incr
c=counter()
print(c())
print(c())
print(c())
print(c.__closure__[0].cell_contents) #查看闭包的元素
二 闭包的意义与应用
#闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域
#应用领域:延迟计算(原来我们是传参,现在我们是包起来)
from urllib.request import urlopen
def index(url):
def get():
return urlopen(url).read()
return get
baidu=index(\'http://www.baidu.com\')
print(baidu().decode(\'utf-8\'))
装饰器
装饰器就是闭包函数的一种应用场景
1 为何要用装饰器
#开放封闭原则:对修改封闭,对扩展开放
2 什么是装饰器
装饰器他人的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。
强调装饰器的原则:1 不修改被装饰对象的源代码 2 不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加上新功能
3 装饰器的使用
import time def timmer(func): def wrapper(*args,**kwargs): start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print(\'run time is %s\' %(stop_time-start_time)) return res return wrapper @timmer def foo(): time.sleep(3) print(\'from foo\') foo()
def auth(driver=\'file\'): def auth2(func): def wrapper(*args,**kwargs): name=input("user: ") pwd=input("pwd: ") if driver == \'file\': if name == \'egon\' and pwd == \'123\': print(\'login successful\') res=func(*args,**kwargs) return res elif driver == \'ldap\': print(\'ldap\') return wrapper return auth2 @auth(driver=\'file\') def foo(name): print(name) foo(\'egon\')
4 装饰器语法
被装饰函数的正上方,单独一行
@deco1
@deco2
@deco3
def foo():
pass
foo=deco1(deco2(deco3(foo)))
5 装饰器补充:wraps
from functools import wraps
def deco(func):
@wraps(func) #加在最内层函数正上方
def wrapper(*args,**kwargs):
return func(*args,**kwargs)
return wrapper
@deco
def index():
\'\'\'哈哈哈哈\'\'\'
print(\'from index\')
print(index.__doc__)
迭代器
1 迭代的概念
#迭代是一个重复的过程,每次重复即一次迭代,并且每次迭代的结果都是下一次迭代的初始值
while True: #只是单纯地重复,因而不是迭代
print(\'===>\')
l=[1,2,3]
count=0
while count < len(l): #迭代
print(l[count])
count+=1
2 为何要有迭代器?什么是可迭代对象?什么是迭代器对象?
#1、为何要有迭代器?
对于序列类型:字符串、列表、元组,我们可以使用索引的方式迭代取出其包含的元素。但对于字典、集合、文件等类型是没有索引的,若还想取出其内部包含的元素,则必须找出一种不依赖于索引的迭代方式,这就是迭代器
#2、什么是可迭代对象?
可迭代对象指的是内置有__iter__方法的对象,即obj.__iter__,如下
\'hello\'.__iter__
(1,2,3).__iter__
[1,2,3].__iter__
{\'a\':1}.__iter__
{\'a\',\'b\'}.__iter__
open(\'a.txt\').__iter__
#3、什么是迭代器对象?
可迭代对象执行obj.__iter__()得到的结果就是迭代器对象
而迭代器对象指的是即内置有__iter__又内置有__next__方法的对象
文件类型是迭代器对象
open(\'a.txt\').__iter__()
open(\'a.txt\').__next__()
#4、注意:
迭代器对象一定是可迭代对象,而可迭代对象不一定是迭代器对象
3 迭代器对象的使用
dic={\'a\':1,\'b\':2,\'c\':3}
iter_dic=dic.__iter__() #得到迭代器对象,迭代器对象即有__iter__又有__next__,但是:迭代器.__iter__()得到的仍然是迭代器本身
iter_dic.__iter__() is iter_dic #True
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
print(iter_dic.__next__()) #等同于next(iter_dic)
# print(iter_dic.__next__()) #抛出异常StopIteration,或者说结束标志
#有了迭代器,我们就可以不依赖索引迭代取值了
iter_dic=dic.__iter__()
while 1:
try:
k=next(iter_dic)
print(dic[k])
except StopIteration:
break
#这么写太丑陋了,需要我们自己捕捉异常,控制next,python这么牛逼,能不能帮我解决呢?能,请看for循环
4 for循环
#基于for循环,我们可以完全不再依赖索引去取值了
dic={\'a\':1,\'b\':2,\'c\':3}
for k in dic:
print(dic[k])
#for循环的工作原理
#1:执行in后对象的dic.__iter__()方法,得到一个迭代器对象iter_dic
#2: 执行next(iter_dic),将得到的值赋值给k,然后执行循环体代码
#3: 重复过程2,直到捕捉到异常StopIteration,结束循环
5 迭代器的优缺点
#优点:
- 提供一种统一的、不依赖于索引的迭代方式
- 惰性计算,节省内存
#缺点:
- 无法获取长度(只有在next完毕才知道到底有几个值)
- 一次性的,只能往后走,不能往前退
生成器
1 什么是生成器
#只要函数内部包含有yield关键字,那么函数名()的到的结果就是生成器,并且不会执行函数内部代码
def func():
print(\'====>first\')
yield 1
print(\'====>second\')
yield 2
print(\'====>third\')
yield 3
print(\'====>end\')
g=func()
print(g) #<generator object func at 0x0000000002184360>
2 生成器就是迭代器
g.__iter__
g.__next__
#2、所以生成器就是迭代器,因此可以这么取值
res=next(g)
print(res)
3 生成器表达式
#1、把列表推导式的[]换成()就是生成器表达式
#2、示例:生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
>>> chicken=(\'鸡蛋%s\' %i for i in range(5))
>>> chicken
<generator object <genexpr> at 0x10143f200>
>>> next(chicken)
\'鸡蛋0\'
>>> list(chicken) #因chicken可迭代,因而可以转成列表
[\'鸡蛋1\', \'鸡蛋2\', \'鸡蛋3\', \'鸡蛋4\',]
#3、优点:省内存,一次只产生一个值在内存中
四 内置函数、高阶函数
内置函数 参考:https://docs.python.org/3/library/functions.html?highlight=built#ascii
高阶函数
sorted
排序算法
排序也是在程序中经常用到的算法。无论使用冒泡排序还是快速排序,排序的核心是比较两个元素的大小。
如果是数字,我们可以直接比较,但如果是字符串或者两个dict呢?直接比较数学上的大小是没有意义的,因此,比较的过程必须通过函数抽象出来。
通常规定,对于两个元素x和y,如果认为x < y,则返回-1,如果认为x == y,则返回0,如果认为x > y,则返回1,这样,排序算法就不用关心具体的比较过程,而是根据比较结果直接排序。 Python内置的sorted()函数就可以对list进行排序: >>> sorted([36, 5, 12, 9, 21]) [5, 9, 12, 21, 36] 此外,sorted()函数也是一个高阶函数,它还可以接收一个比较函数来实现自定义的排序。比如,如果要倒序排序,我们就可以自定义一个reversed_cmp函数: def reversed_cmp(x, y): if x > y: return -1 if x < y: return 1 return 0 传入自定义的比较函数reversed_cmp,就可以实现倒序排序: >>> sorted([36, 5, 12, 9, 21], reversed_cmp) [36, 21, 12, 9, 5] 我们再看一个字符串排序的例子: >>> sorted([\'bob\', \'about\', \'Zoo\', \'Credit\']) [\'Credit\', \'Zoo\', \'about\', \'bob\'] 默认情况下,对字符串排序,是按照ASCII的大小比较的,由于\'Z\' < \'a\',结果,大写字母Z会排在小写字母a的前面。 现在,我们提出排序应该忽略大小写,按照字母序排序。要实现这个算法,不必对现有代码大加改动,只要我们能定义出忽略大小写的比较算法就可以: def cmp_ignore_case(s1, s2): u1 = s1.upper() u2 = s2.upper() if u1 < u2: return -1 if u1 > u2: return 1 return 0 忽略大小写来比较两个字符串,实际上就是先把字符串都变成大写(或者都变成小写),再比较。 这样,我们给sorted传入上述比较函数,即可实现忽略大小写的排序: >>> sorted([\'bob\', \'about\', \'Zoo\', \'Credit\'], cmp_ignore_case) [\'about\', \'bob\', \'Credit\', \'Zoo\'] 从上述例子可以看出,高阶函数的抽象能力是非常强大的,而且,核心代码可以保持得非常简洁。
map/reduce
map()函数接收两个参数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并把结果作为新的Iterator返回。 举例说明,比如我们有一个函数f(x)=x2,要把这个函数作用在一个list [1, 2, 3, 4, 5, 6, 7, 8, 9]上,就可以用map()实现如下: 现在,我们用Python代码实现: >>> def f(x): ... return x * x ... >>> r = map(f, [1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> list(r) [1, 4, 9, 16, 25, 36, 49, 64, 81] map()传入的第一个参数是f,即函数对象本身。由于结果r是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。 L = [] for n in [1, 2, 3, 4, 5, 6, 7, 8, 9]: L.append(f(n)) print(L) map()作为高阶函数,事实上它把运算规则抽象了,因此,我们不但可以计算简单的f(x)=x2,还可以计算任意复杂的函数,比如,把这个list所有数字转为字符串: >>> list(map(str, [1, 2, 3, 4, 5, 6, 7, 8, 9])) [\'1\', \'2\', \'3\', \'4\', \'5\', \'6\', \'7\', \'8\', \'9\'] 再看reduce的用法。reduce把一个函数作用在一个序列[x1, x2, x3, ...]上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积计算,其效果就是: reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4) 比方说对一个序列求和,就可以用reduce实现: >>> from functools import reduce >>> def add(x, y): ... return x + y ... >>> reduce(add, [1, 3, 5, 7, 9]) 25 当然求和运算可以直接用Python内建函数sum(),没必要动用reduce。 但是如果要把序列[1, 3, 5, 7, 9]变换成整数13579,reduce就可以派上用场: >>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> reduce(fn, [1, 3, 5, 7, 9]) 13579 这个例子本身没多大用处,但是,如果考虑到字符串str也是一个序列,对上面的例子稍加改动,配合map(),我们就可以写出把str转换为int的函数: >>> from functools import reduce >>> def fn(x, y): ... return x * 10 + y ... >>> def char2num(s): ... return {\'0\': 0, \'1\': 1, \'2\': 2, \'3\': 3, \'4\': 4, \'5\': 5, \'6\': 6, \'7\': 7, \'8\': 8, \'9\': 9}[s] ... >>> reduce(fn, map(char2num, \'13579\')) 13579 整理成一个str2int的函数就是: from functools import reduce def str2int(s): def fn(x, y): return x * 10 + y def char2num(s): return {\'0\': 0, \'1\': 1, \'2\': 2, \'3\': 3, \'4\': 4, \'5\': 5, \'6\': 6, \'7\': 7, \'8\': 8, \'9\': 9}[s] return reduce(fn, map(char2num, s)) 还可以用lambda函数进一步简化成: from functools import reduce def char2num(s): return {\'0\'以上是关于python 知识回顾的主要内容,如果未能解决你的问题,请参考以下文章