博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数草稿
阅读量:7033 次
发布时间:2019-06-28

本文共 31353 字,大约阅读时间需要 104 分钟。

1 什么是函数?2 为什么要用函数?3 函数的分类:内置函数与自定义函数4 如何自定义函数  语法  定义有参数函数,及有参函数的应用场景  定义无参数函数,及无参函数的应用场景  定义空函数,及空函数的应用场景5 调用函数    如何调用函数    函数的返回值    函数参数的应用:形参和实参,位置参数,关键字参数,默认参数,*args,**kwargs6 高阶函数(函数对象)7 函数嵌套8 作用域与名称空间9 装饰器10 迭代器与生成器及协程函数11 三元运算,列表解析、生成器表达式12 函数的递归调用13 内置函数14 面向过程编程与函数式编程
本节课程重点
一:为何用函数之不使用函数的问题     #组织结构不清晰     #代码冗余     #无法统一管理且维护难度大 二:函数分类:     1. 内置函数     2. 自定义函数 三:为何要定义函数     函数即变量,变量必须先定义后使用,未定义而直接引用函数,就相当于在引用一个不存在的变量名     代码演示? 四:定义函数都干了哪些事?     只检测语法,不执行代码 五:如何定义函数(函数名要能反映其意义)     def ... 六:定义函数的三种形式     无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印     有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值     空函数:设计代码结构 七 :函数的调用     1 先找到名字     2 根据名字调用代码      函数的返回值?   0->None   1->返回1个值   多个->元组   什么时候该有?     调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值     通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果   什么时候不需要有?     调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值     通常无参函数不需要有返回值 八:函数调用的三种形式   1 语句形式:foo()   2 表达式形式:3*len('hello')   4 当中另外一个函数的参数:range(len('hello')) 九:函数的参数:  1 形参和实参定义  2 形参即变量名,实参即变量值,函数调用则将值绑定到名字上,函数调用结束,解除绑定  3 具体应用     位置参数:按照从左到右的顺序定义的参数         位置形参:必选参数         位置实参:按照位置给形参传值     关键字参数:按照key=value的形式定义实参         无需按照位置为形参传值         注意的问题:                 1. 关键字实参必须在位置实参右面                 2. 对同一个形参不能重复传值     默认参数:形参在定义时就已经为其赋值         可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)         注意的问题:                 1. 只在定义时赋值一次                 2. 默认参数的定义应该在位置形参右面                 3. 默认参数通常应该定义成不可变类型     可变长参数:         针对实参在定义时长度不固定的情况,应该从形参的角度找到可以接收可变长实参的方案,这就是可变长参数(形参)         而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参也应该有两种解决方案,分别是*args,**kwargs         ===========*args===========         def foo(x,y,*args):             print(x,y)             print(args)         foo(1,2,3,4,5)         def foo(x,y,*args):             print(x,y)             print(args)         foo(1,2,*[3,4,5])         def foo(x,y,z):             print(x,y,z)         foo(*[1,2,3])         ===========**kwargs===========         def foo(x,y,**kwargs):             print(x,y)             print(kwargs)         foo(1,y=2,a=1,b=2,c=3)         def foo(x,y,**kwargs):             print(x,y)             print(kwargs)         foo(1,y=2,**{'a':1,'b':2,'c':3})         def foo(x,y,z):             print(x,y,z)         foo(**{'z':1,'x':2,'y':3})         ===========*args+**kwargs===========         def foo(x,y):             print(x,y)         def wrapper(*args,**kwargs):             print('====>')             foo(*args,**kwargs)     命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递         可以保证,传入的参数中一定包含某些关键字         def foo(x,y,*args,a=1,b,**kwargs):             print(x,y)             print(args)             print(a)             print(b)             print(kwargs)         foo(1,2,3,4,5,b=3,c=4,d=5)         结果:             1             2             (3, 4, 5)             1             3             {'c': 4, 'd': 5}   十 阶段性练习

1、写函数,,用户传入修改的文件名,与要修改的内容,执行函数,完成批了修改操作

2、写函数,计算传入字符串中【数字】、【字母】、【空格] 以及 【其他】的个数

3、写函数,判断用户传入的对象(字符串、列表、元组)长度是否大于5。

4、写函数,检查传入列表的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

5、写函数,检查获取传入列表或元组对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者。

6、写函数,检查字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者。

dic = {"k1": "v1v1", "k2": [11,22,33,44]}
PS:字典中的value只能是字符串或列表

#题目一def modify_file(filename,old,new):    import os    with open(filename,'r',encoding='utf-8') as read_f,\        open('.bak.swap','w',encoding='utf-8') as write_f:        for line in read_f:            if old in line:                line=line.replace(old,new)            write_f.write(line)    os.remove(filename)    os.rename('.bak.swap',filename)modify_file('/Users/jieli/PycharmProjects/爬虫/a.txt','alex','SB')#题目二def check_str(msg):    res={        'num':0,        'string':0,        'space':0,        'other':0,    }    for s in msg:        if s.isdigit():            res['num']+=1        elif s.isalpha():            res['string']+=1        elif s.isspace():            res['space']+=1        else:            res['other']+=1    return resres=check_str('hello name:aSB passowrd:alex3714')print(res)#题目三:略#题目四def func1(seq):    if len(seq) > 2:        seq=seq[0:2]    return seqprint(func1([1,2,3,4]))#题目五def func2(seq):    return seq[::2]print(func2([1,2,3,4,5,6,7]))#题目六def func3(dic):    d={}    for k,v in dic.items():        if len(v) > 2:            d[k]=v[0:2]    return dprint(func3({
'k1':'abcdef','k2':[1,2,3,4],'k3':('a','b','c')}))
View Code

 

=======================本节课新内容==========================     一:函数对象:函数是第一类对象,即函数可以当作数据传递     1 可以被引用     2 可以当作参数传递     3 返回值可以是函数     3 可以当作容器类型的元素         #利用该特性,优雅的取代多分支的if         def foo():             print('foo')         def bar():             print('bar')         dic={
'foo':foo, 'bar':bar, } while True: choice=input('>>: ').strip() if choice in dic: dic[choice]() 二:函数的嵌套 1 函数的嵌套调用 def max(x,y): return x if x > y else y def max4(a,b,c,d): res1=max(a,b) res2=max(res1,c) res3=max(res2,d) return res3 print(max4(1,2,3,4)) 2 函数的嵌套定义 def f1(): def f2(): def f3(): print('from f3') f3() f2() f1() f3() #报错 三 名称空间和作用域: 名称空间:存放名字的地方,三种名称空间,(之前遗留的问题x=1,1存放于内存中,那名字x存放在哪里呢?名称空间正是存放名字x与1绑定关系的地方) 加载顺序是? 名字的查找顺序?(在全局无法查看局部的,在局部可以查看全局的)
# max=1         def f1():             # max=2             def f2():                 # max=3                 print(max)             f2()         f1()         print(max)
作用域即范围        - 全局范围:全局存活,全局有效        - 局部范围:临时存活,局部有效           - 作用域关系是在函数定义阶段就已经固定的,与函数的调用位置无关,如下
      x=1       def f1():           def f2():               print(x)           return f2       def f3(func):           x=2           func()       f3(f1())
查看作用域:globals(),locals()         global         nonlocal         LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__         locals 是函数内的名字空间,包括局部变量和形参         enclosing 外部嵌套函数的名字空间(闭包中常见)         globals 全局变量,函数定义所在模块的名字空间         builtins 内置模块的名字空间     四:闭包:内部函数包含对外部作用域而非全局作用域的引用        提示:之前我们都是通过参数将外部的值传给函数,闭包提供了另外一种思路,包起来喽,包起呦,包起来哇         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()     4     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')     5 装饰器语法:         被装饰函数的正上方,单独一行         @deco1         @deco2         @deco3         def foo():             pass         foo=deco1(deco2(deco3(foo)))   6 装饰器补充:wraps
from functools import wrapsdef deco(func):    @wraps(func) #加在最内层函数正上方    def wrapper(*args,**kwargs):        return func(*args,**kwargs)    return wrapper@decodef index():    '''哈哈哈哈'''    print('from index')print(index.__doc__)

 

  7 装饰器练习

一:编写函数,(函数执行的时间是随机的)

二:编写装饰器,为函数加上统计时间的功能
三:编写装饰器,为函数加上认证的功能

四:编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),要求登录成功一次,后续的函数都无需再输入用户名和密码

注意:从文件中读出字符串形式的字典,可以用eval('{"name":"egon","password":"123"}')转成字典格式

五:编写装饰器,为多个函数加上认证功能,要求登录成功一次,在超时时间内无需重复登录,超过了超时时间,则必须重新登录

六:编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果

七:为题目五编写装饰器,实现缓存网页内容的功能:

具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件中读取网页内容,否则,就去下载,然后存到文件中

扩展功能:用户可以选择缓存介质/缓存引擎,针对不同的url,缓存到不同的文件中

八:还记得我们用函数对象的概念,制作一个函数字典的操作吗,来来来,我们有更高大上的做法,在文件开头声明一个空字典,然后在每个函数前加上装饰器,完成自动添加到字典的操作

九 编写日志装饰器,实现功能如:一旦函数f1执行,则将消息2017-07-21 11:12:11 f1 run写入到日志文件中,日志文件路径可以指定

注意:时间格式的获取
import time
time.strftime('%Y-%m-%d %X')

#题目一:略#题目二:略#题目三:略#题目四:db='db.txt'login_status={
'user':None,'status':False}def auth(auth_type='file'): def auth2(func): def wrapper(*args,**kwargs): if login_status['user'] and login_status['status']: return func(*args,**kwargs) if auth_type == 'file': with open(db,encoding='utf-8') as f: dic=eval(f.read()) name=input('username: ').strip() password=input('password: ').strip() if name in dic and password == dic[name]: login_status['user']=name login_status['status']=True res=func(*args,**kwargs) return res else: print('username or password error') elif auth_type == 'sql': pass else: pass return wrapper return auth2@auth()def index(): print('index')@auth(auth_type='file')def home(name): print('welcome %s to home' %name)# index()# home('egon')#题目五import time,randomuser={
'user':None,'login_time':None,'timeout':0.000003,}def timmer(func): def wrapper(*args,**kwargs): s1=time.time() res=func(*args,**kwargs) s2=time.time() print('%s' %(s2-s1)) return res return wrapperdef auth(func): def wrapper(*args,**kwargs): if user['user']: timeout=time.time()-user['login_time'] if timeout < user['timeout']: return func(*args,**kwargs) name=input('name>>: ').strip() password=input('password>>: ').strip() if name == 'egon' and password == '123': user['user']=name user['login_time']=time.time() res=func(*args,**kwargs) return res return wrapper@authdef index(): time.sleep(random.randrange(3)) print('welcome to index')@authdef home(name): time.sleep(random.randrange(3)) print('welcome %s to home ' %name)index()home('egon')#题目六:略#题目七:简单版本import requestsimport oscache_file='cache.txt'def make_cache(func): def wrapper(*args,**kwargs): if not os.path.exists(cache_file): with open(cache_file,'w'):pass if os.path.getsize(cache_file): with open(cache_file,'r',encoding='utf-8') as f: res=f.read() else: res=func(*args,**kwargs) with open(cache_file,'w',encoding='utf-8') as f: f.write(res) return res return wrapper@make_cachedef get(url): return requests.get(url).text# res=get('https://www.python.org')# print(res)#题目七:扩展版本import requests,os,hashlibengine_settings={ 'file':{
'dirname':'./db'}, 'mysql':{ 'host':'127.0.0.1', 'port':3306, 'user':'root', 'password':'123'}, 'redis':{ 'host':'127.0.0.1', 'port':6379, 'user':'root', 'password':'123'},}def make_cache(engine='file'): if engine not in engine_settings: raise TypeError('egine not valid') def deco(func): def wrapper(url): if engine == 'file': m=hashlib.md5(url.encode('utf-8')) cache_filename=m.hexdigest() cache_filepath=r'%s/%s' %(engine_settings['file']['dirname'],cache_filename) if os.path.exists(cache_filepath) and os.path.getsize(cache_filepath): return open(cache_filepath,encoding='utf-8').read() res=func(url) with open(cache_filepath,'w',encoding='utf-8') as f: f.write(res) return res elif engine == 'mysql': pass elif engine == 'redis': pass else: pass return wrapper return deco@make_cache(engine='file')def get(url): return requests.get(url).text# print(get('https://www.python.org'))print(get('https://www.baidu.com'))#题目八route_dic={}def make_route(name): def deco(func): route_dic[name]=func return deco@make_route('select')def func1(): print('select')@make_route('insert')def func2(): print('insert')@make_route('update')def func3(): print('update')@make_route('delete')def func4(): print('delete')print(route_dic)#题目九import timeimport osdef logger(logfile): def deco(func): if not os.path.exists(logfile): with open(logfile,'w'):pass def wrapper(*args,**kwargs): res=func(*args,**kwargs) with open(logfile,'a',encoding='utf-8') as f: f.write('%s %s run\n' %(time.strftime('%Y-%m-%d %X'),func.__name__)) return res return wrapper return deco@logger(logfile='aaaaaaaaaaaaaaaaaaaaa.log')def index(): print('index')index()
View Code

 

 

 

六:迭代器         迭代的概念:重复的过程称为迭代,每次重复即一次迭代,并且每次迭代的结果是下一次迭代的初始值             # while True: #只满足重复,因而不是迭代             #     print('====>')             #迭代             l=[1,2,3]             count=0             while count < len(l): #只满足重复,因而不是迭代                 print('====>',l[count])                 count+=1         为何要有迭代器?         可迭代的对象?         哪些是可迭代对象?         迭代器?             l={'a':1,'b':2,'c':3,'d':4,'e':5}             i=l.__iter__() #等于i=iter(l)             print(next(i))             print(next(i))             print(next(i))         StopIteration?         for循环         迭代器的优缺点:             优点:                 提供统一的且不依赖于索引的迭代方式                 惰性计算,节省内存             缺点:                 无法获取长度                 一次性的,只能往后走,不能往前退         迭代器协议   练习:判断以下对象哪个是可迭代对象,哪个是迭代器对象

s='hello'

l=[1,2,3,4]
t=(1,2,3)
d={'a':1}
set={1,2,3}
f=open('a.txt')

七 生成器    yield:     把函数做成迭代器     对比return,可以返回多次值,挂起函数的运行状态     # def foo():     #     return 1     #     return 2     #     return 3     #     # res=foo()     # print(res)     def foo():         yield 1         yield 2         yield 3     res=foo()     print(res)     from collections import Iterable,Iterator     print(isinstance(res,Iterator))     print(next(res))     print(next(res))     print(next(res))     应用一:         def counter(n):             print('start')             i=0             while i < n:                 yield i                 i+=1             print('end')         c=counter(5)         # print(next(c)) #0         # print(next(c)) #1         # print(next(c)) #2         # print(next(c)) #3         # print(next(c)) #4         # print(next(c)) #5 --->没有yield,抛出StopIteration         for i in counter(5):             print(i)     应用二:管道tail -f a.txt |grep 'python'     import time     def tail(filepath):         with open(filepath,encoding='utf-8') as f:             f.seek(0,2)             while True:                 line=f.readline()                 if line:                     yield line                 else:                     time.sleep(0.5)     def grep(pattern,lines):         for line in lines:             if pattern in line:                 yield line     for i in grep('python',tail('a.txt')):         print(i)     #协程函数         def eater(name):             print('%s说:我开动啦' %name)             food_list=[]             while True:                 food=yield food_list                 food_list.append(food)                 print('%s 吃了 %s' %(name,food))         e=eater('egon')         e.send(None) #next(e) #初始化装饰器,         e.close() #关闭     面向过程编程:         import os         def init(func):             def wrapper(*args,**kwargs):                 g=func(*args,**kwargs)                 next(g)                 return g             return wrapper         def search(file_dir,target):             for par_dir,_,files in os.walk(file_dir):                 for file in files:                     filepath='%s\%s' %(par_dir,file)                     target.send(filepath)         @init         def opener(target):             while True:                 filepath=yield                 with open(filepath) as f:                     target.send((f,filepath))         @init         def cat(target):             while True:                 res=False                 f,filepath=yield res                 for line in f:                     print(line,end='')                     res=target.send((line,filepath))                     if res:                         break         @init         def grep(pattern,target):             res = False             while True:                 line,filepath=yield res                 res=False                 if pattern in line:                     res=True                     target.send(filepath)         @init         def printer():             while True:                 filepath=yield                 print(filepath)         search(r'C:\Users\Administrator\PycharmProjects\test\字符编码\a',                opener(cat(grep('python',printer()))))
#注意:target.send(...)在拿到target的返回值后才算执行结束import osdef init(func):    def wrapper(*args,**kwargs):        g=func(*args,**kwargs)        next(g)        return g    return wrapper@initdef search(target):    while True:        search_dir=yield        for par_dir,_,files in os.walk(search_dir):            for file in files:                file_abs_path=r'%s\%s' %(par_dir,file)                # print(file_abs_path)                target.send(file_abs_path)@initdef opener(target):    while True:        file_abs_path=yield        with open(file_abs_path,encoding='utf-8') as f:            target.send((file_abs_path,f))@initdef cat(target):    while True:        file_abs_path,f=yield        print('检索文件',file_abs_path)        for line in f:            tag=target.send((file_abs_path,line))            print('检索文件的行: %s' %line)            if tag:                break@initdef grep(pattern,target):    tag=False    while True:        file_abs_path,line=yield tag        tag=False        if pattern in line:            tag=True            target.send(file_abs_path)@initdef printer():    while True:        file_abs_path=yield        print('过滤出的结果=========>',file_abs_path)search_dir=r'C:\Users\Administrator\PycharmProjects\test\函数备课\a'e=search(opener(cat(grep('python',printer()))))e.send(search_dir)
备注

 

八:三元表达式,列表推导式,生成器表达式

==============================#三元表达式
name='alex'
name='linhaifeng'
res='SB' if name == 'alex' else 'shuai'
print(res)

 

==============================列表推导式

------------------1:引子
生一筐鸡蛋
egg_list=[]
for i in range(10):
egg_list.append('鸡蛋%s' %i)

egg_list=['鸡蛋%s' %i for i in range(10)] #列表解析

------------------2:语法

[expression for item1 in iterable1 if condition1
for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
]
类似于
res=[]
for item1 in iterable1:
if condition1:
for item2 in iterable2:
if condition2
...
for itemN in iterableN:
if conditionN:
res.append(expression)

------------------3:优点

方便,改变了编程习惯,声明式编程

------------------4:应用
l1=[3,-4,-1,5,7,9]

[i**i for i in l1]

[i for i in l1 if i >0]

s='egon'

[(i,j) for i in l1 if i>0 for j in s] #元组合必须加括号[i,j ...]非法

 

==============================生成器表达式

------------------1:引子
生一筐鸡蛋变成给你一只老母鸡,用的时候就下蛋,这也是生成器的特性
egg_list=[]
for i in range(10):
egg_list.append('鸡蛋%s' %i)

chicken=('鸡蛋%s' %i for i in range(10))
>>> chicken
<generator object <genexpr> at 0x10143f200>
>>> next(chicken)
'鸡蛋5'

------------------2:语法

语法与列表推导式类似,只是[]->()

(expression for item1 in iterable1 if condition1

for item2 in iterable2 if condition2
...
for itemN in iterableN if conditionN
)

------------------3:优点

省内存,一次只产生一个值在内存中

------------------4:应用

读取一个大文件的所有内容,并且处理行
f=open('a.txt')
g=(line.strip() for line in f)

list(g) #因g可迭代,因而可以转成列表

------------------5:示例

#一
with open('a.txt') as f:
    print(max(len(line) for line in f))
    print(sum(len(line) for line in f)) #求包换换行符在内的文件所有的字节数,为何得到的值为0?

#二

print(max(len(line) for line in open('a.txt')))
print(sum(len(line) for line in open('a.txt')))

#三

with open('a.txt') as f:
    g=(len(line) for line in f)
print(sum(g)) #为何报错?

 

 

 

 

==============================声明式编程

文件a.txt内容
apple 10 3
tesla 100000 1
mac 3000 2
lenovo 30000 3
chicken 10 3

 

f=open('a.py')

#求花了多少钱
g=(line.split() for line in f)

sum(float(price)*float(count) for _,price,count in g)

模拟数据库查询
>>> f=open('a.txt')
>>> g=(line.split() for line in f)
>>> goods_l=[{'name':n,'price':p,'count':c} for n,p,c in g]

过滤查询

>>> goods_l=[{'name':n,'price':p,'count':c} for n,p,c in g if float(p) > 10000]

 

 

 

 

  九:匿名函数lambda

匿名就是没有名字
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)
#让其有名字就没有意义

 

有名函数:循环使用,保存了名字,通过名字就可以重复引用函数功能

匿名函数:一次性使用,随时随时定义

应用:max,min,sorted,map,reduce,filter

 

 

  十 内建函数

注意:内置函数id()可以返回一个对象的身份,返回值为整数。这个整数通常对应与该对象在内存中的位置,但这与python的具体实现有关,不应该作为对身份的定义,即不够精准,最精准的还是以内存地址为准。is运算符用于比较两个对象的身份,等号比较两个对象的值,内置函数type()则返回一个对象的类型

字典的运算:最小值,最大值,排序salaries={    'egon':3000,    'alex':100000000,    'wupeiqi':10000,    'yuanhao':2000}迭代字典,取得是key,因而比较的是key的最大和最小值>>> max(salaries)'yuanhao'>>> min(salaries)'alex'可以取values,来比较>>> max(salaries.values())>>> min(salaries.values())但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键>>> max(salaries,key=lambda k:salary[k])'alex'>>> min(salaries,key=lambda k:salary[k])'yuanhao'也可以通过zip的方式实现salaries_and_names=zip(salaries.values(),salaries.keys()) 先比较值,值相同则比较键>>> max(salaries_and_names)(100000000, 'alex')salaries_and_names是迭代器,因而只能访问一次>>> min(salaries_and_names)Traceback (most recent call last):  File "
", line 1, in
ValueError: min() arg is an empty sequencesorted(iterable,key=None,reverse=False)
View Code
#字符串可以提供的参数 's' None>>> format('some string','s')'some string'>>> format('some string')'some string'#整形数值可以提供的参数有 'b' 'c' 'd' 'o' 'x' 'X' 'n' None>>> format(3,'b') #转换成二进制'11'>>> format(97,'c') #转换unicode成字符'a'>>> format(11,'d') #转换成10进制'11'>>> format(11,'o') #转换成8进制'13'>>> format(11,'x') #转换成16进制 小写字母表示'b'>>> format(11,'X') #转换成16进制 大写字母表示'B'>>> format(11,'n') #和d一样'11'>>> format(11) #默认和d一样'11'#浮点数可以提供的参数有 'e' 'E' 'f' 'F' 'g' 'G' 'n' '%' None>>> format(314159267,'e') #科学计数法,默认保留6位小数'3.141593e+08'>>> format(314159267,'0.2e') #科学计数法,指定保留2位小数'3.14e+08'>>> format(314159267,'0.2E') #科学计数法,指定保留2位小数,采用大写E表示'3.14E+08'>>> format(314159267,'f') #小数点计数法,默认保留6位小数'314159267.000000'>>> format(3.14159267000,'f') #小数点计数法,默认保留6位小数'3.141593'>>> format(3.14159267000,'0.8f') #小数点计数法,指定保留8位小数'3.14159267'>>> format(3.14159267000,'0.10f') #小数点计数法,指定保留10位小数'3.1415926700'>>> format(3.14e+1000000,'F')  #小数点计数法,无穷大转换成大小字母'INF'#g的格式化比较特殊,假设p为格式中指定的保留小数位数,先尝试采用科学计数法格式化,得到幂指数exp,如果-4<=exp
>> format(0.00003141566,'.1g') #p=1,exp=-5 ==》 -4<=exp
>> format(0.00003141566,'.2g') #p=1,exp=-5 ==》 -4<=exp
>> format(0.00003141566,'.3g') #p=1,exp=-5 ==》 -4<=exp
>> format(0.00003141566,'.3G') #p=1,exp=-5 ==》 -4<=exp
>> format(3.1415926777,'.1g') #p=1,exp=0 ==》 -4<=exp
>> format(3.1415926777,'.2g') #p=1,exp=0 ==》 -4<=exp
>> format(3.1415926777,'.3g') #p=1,exp=0 ==》 -4<=exp
>> format(0.00003141566,'.1n') #和g相同'3e-05'>>> format(0.00003141566,'.3n') #和g相同'3.14e-05'>>> format(0.00003141566) #和g相同'3.141566e-05'
format(了解即可)

 

https://docs.python.org/3/library/functions.html?highlight=built#ascii 

 

 

  十一:内建函数补充(结合lambda)

字典的运算:最小值,最大值,排序
salaries={
'egon':3000,
'alex':100000000,
'wupeiqi':10000,
'yuanhao':2000
}

迭代字典,取得是key,因而比较的是key的最大和最小值

>>> max(salaries)
'yuanhao'
>>> min(salaries)
'alex'

可以取values,来比较

>>> max(salaries.values())
100000000
>>> min(salaries.values())
2000
但通常我们都是想取出,工资最高的那个人名,即比较的是salaries的值,得到的是键
>>> max(salaries,key=lambda k:salary[k])
'alex'
>>> min(salaries,key=lambda k:salary[k])
'yuanhao'

 

也可以通过zip的方式实现

salaries_and_names=zip(salaries.values(),salaries.keys())

先比较值,值相同则比较键

>>> max(salaries_and_names)
(100000000, 'alex')

salaries_and_names是迭代器,因而只能访问一次
>>> min(salaries_and_names)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: min() arg is an empty sequence

 

sorted(iterable,key=None,reverse=False)

 

  #eval与compile

eval(str,[,globasl[,locals]])

eval('1+2+max(3,9,100)+1.3')

my_globals={'x':1}

my_locals={'x':2}
eval('1+x',my_globals,my_locals)

exec('for i in range(10):print("i")')
同样可以指定自己的名称空间

compile(str,filename,kind)
filename:用于追踪str来自于哪个文件,如果不想追踪就可以不定义
kind可以是:single代表一条语句,exec代表一组语句,eval代表一个表达式

s='for i in range(10):print(i)'code=compile(s,'','exec')exec(code)s='1+2+3'code=compile(s,'','eval')eval(code)

 

 

 

  十二:函数的递归调用

图解:递推和回溯         # salary(5)=salary(4)+300         # salary(4)=salary(3)+300         # salary(3)=salary(2)+300         # salary(2)=salary(1)+300         # salary(1)=100         #         # salary(n)=salary(n-1)+300     n>1         # salary(1) =100                n=1         def salary(n):             if n == 1:                 return 100             return salary(n-1)+300         print(salary(5))

函数在调用时,直接或间接调用了自身,就是递归调用

def fac(n):#阶乘运算

if n == 1:return 1
else:return n*fib(n-1)

递归效率低,需要在进入下一次递归时保留当前的状态,见51cto博客
解决方法是尾递归,即在函数的最后一步(而非最后一行)调用自己
但是python又没有尾递归,且对递归层级做了限制

1. 必须有一个明确的结束条件

2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少

3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

尾递归优化:http://egon09.blog.51cto.com/9161406/1842475

>>> sys.getrecursionlimit()
1000

>>> n=1
>>> def test():
... global n
... n+=1
... print(n)
... test()
...
>>> test()

>>> sys.setrecursionlimit(10000)
>>> test() #可以递归10000层了

虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归

 

  十三 阶段性练习:

1 文件内容如下,标题为:姓名,性别,年纪,薪资

egon male 18 3000

alex male 38 30000
wupeiqi female 28 20000
yuanhao female 28 10000

要求:

从文件中取出每一条记录放入列表中,
列表的每个元素都是{'name':'egon','sex':'male','age':18,'salary':3000}的形式

2 根据1得到的列表,取出薪资最高的人的信息

3 根据1得到的列表,取出最年轻的人的信息
4 根据1得到的列表,将每个人的信息中的名字映射成首字母大写的形式
5 根据1得到的列表,过滤掉名字以a开头的人的信息
6 使用递归打印斐波那契数列(前两个数的和得到第三个数)
0 1 1 2 3 4 7...

7 l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]

  一个列表嵌套很多层,用递归取出所有的值

#1with open('db.txt') as f:    items=(line.split() for line in f)    info=[{
'name':name,'sex':sex,'age':age,'salary':salary} \ for name,sex,age,salary in items]print(info)#2print(max(info,key=lambda dic:dic['salary']))#3print(min(info,key=lambda dic:dic['age']))# 4info_new=map(lambda item:{
'name':item['name'].capitalize(), 'sex':item['sex'], 'age':item['age'], 'salary':item['salary']},info)print(list(info_new))#5g=filter(lambda item:item['name'].startswith('a'),info)print(list(g))#6#非递归def fib(n): a,b=0,1 while a < n: print(a,end=' ') a,b=b,a+b print()fib(10)#递归def fib(a,b,stop): if a > stop: return print(a,end=' ') fib(b,a+b,stop)fib(0,1,10)#7l=[1,2,[3,[4,5,6,[7,8,[9,10,[11,12,13,[14,15]]]]]]]def get(seq): for item in seq: if type(item) is list: get(item) else: print(item)get(l)
View Code

 

 

 

  十四:二分法

l=[1,2,10,2,30,40,33,22,99,31]         def search(num,l):             print(l)             if len(l) > 1:                 mid=len(l)//2                 if num > l[mid]:                     #in the right                     l=l[mid:]                     search(num,l)                 elif num < l[mid]:                     #in the left                     l=l[:mid]                     search(num,l)                 else:                     print('find it')             else:                 if num == l[0]:                     print('find it')                 else:                     print('not exists')         search(100,l)
def search(seq,num):    print(seq)    if len(seq) == 1:        if num == seq[0]:            print('you find it')        else:            print('not exist')        return    mid=len(seq)//2    if num > seq[mid]:        #in the right        seq=seq[mid:]        search(seq,num)    elif num < seq[mid]:        #in the left        seq=seq[:mid]        search(seq,num)    else:        print('find it')search(l,3)
View Code

 

 

 

  十五:面向过程编程,函数式编程

峰哥原创面向过程解释:

函数的参数传入,是函数吃进去的食物,而函数return的返回值,是函数拉出来的结果,面向过程的思路就是,把程序的执行当做一串首尾相连的函数,一个函数吃,拉出的东西给另外一个函数吃,另外一个函数吃了再继续拉给下一个函数吃。。。

面向过程:机械式思维,流水线式编程

例如:
用户登录流程:前端接收处理用户请求-》将用户信息传给逻辑层,逻辑词处理用户信息-》将用户信息写入数据库
验证用户登录流程:数据库查询/处理用户信息-》交给逻辑层,逻辑层处理用户信息-》用户信息交给前端,前端显示用户信息

 

 

函数式编程:http://egon09.blog.51cto.com/9161406/1842475

array=[1,3,4,71,2]ret=[]for i in array:ret.append(i**2)print(ret)#如果我们有一万个列表,那么你只能把上面的逻辑定义成函数def map_test(array):ret=[]for i in array:ret.append(i**2)return retprint(map_test(array))#如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样def add_num(x):return x+1def map_test(func,array):ret=[]for i in array:ret.append(func(i))return retprint(map_test(add_num,array))#可以使用匿名函数print(map_test(lambda x:x-1,array))#上面就是map函数的功能,map得到的结果是可迭代对象print(map(lambda x:x-1,range(5)))
map
from functools import reduce#合并,得一个合并的结果array_test=[1,2,3,4,5,6,7]array=range(100)#报错啊,res没有指定初始值def reduce_test(func,array):l=list(array)for i in l:res=func(res,i)return res# print(reduce_test(lambda x,y:x+y,array))#可以从列表左边弹出第一个值def reduce_test(func,array):l=list(array)res=l.pop(0)for i in l:res=func(res,i)return resprint(reduce_test(lambda x,y:x+y,array))#我们应该支持用户自己传入初始值def reduce_test(func,array,init=None):l=list(array)if init is None:res=l.pop(0)else:res=initfor i in l:res=func(res,i)return resprint(reduce_test(lambda x,y:x+y,array))print(reduce_test(lambda x,y:x+y,array,50))
reduce
movie_people=['alex','wupeiqi','yuanhao','sb_alex','sb_wupeiqi','sb_yuanhao']def tell_sb(x):return x.startswith('sb')def filter_test(func,array):ret=[]for i in array:if func(i):ret.append(i)return retprint(filter_test(tell_sb,movie_people))#函数filter,返回可迭代对象print(filter(lambda x:x.startswith('sb'),movie_people))
filter
#当然了,map,filter,reduce,可以处理所有数据类型name_dic=[{
'name':'alex','age':1000},{
'name':'wupeiqi','age':10000},{
'name':'yuanhao','age':9000},{
'name':'linhaifeng','age':18},]#利用filter过滤掉千年王八,万年龟,还有一个九千岁def func(x):age_list=[1000,10000,9000]return x['age'] not in age_listres=filter(func,name_dic)for i in res:print(i)res=filter(lambda x:x['age'] == 18,name_dic)for i in res:print(i)#reduce用来计算1到100的和from functools import reduceprint(reduce(lambda x,y:x+y,range(100),100))print(reduce(lambda x,y:x+y,range(1,101)))#用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sbname=['alex','wupeiqi','yuanhao']res=map(lambda x:x+'_sb',name)for i in res:print(i)
总结

 

转载于:https://www.cnblogs.com/llhtjwq/p/8306408.html

你可能感兴趣的文章
微软把UWP定位成业务线应用程序开发平台
查看>>
2018腾讯云+未来峰会互联网专场:腾讯云智能物联解决方案亮相
查看>>
Python数据可视化的10种技能
查看>>
关于有效的性能调优的一些建议
查看>>
微软发起Java on Azure调查,呼吁Java社区积极参与
查看>>
搭建svn仓库
查看>>
JavaScript arguments 对象详解
查看>>
[elixir! #0002] [译] 在Phoenix中实现动态表单 by José Valim
查看>>
【windows docker & centos 6 .7搭建】
查看>>
Firefox插件开发:夜间模式
查看>>
这是我第一次遇到判断ios系统版本的问题
查看>>
漏洞战争: 软件漏洞发展趋势
查看>>
数人云CTO解读Docker 1.12和金融业容器化
查看>>
PyMongo 连接问题
查看>>
切图崽的自我修养-合理组织CSS结构
查看>>
【编码】Font Size-微软实习笔试编程题(一)-2016.04.06
查看>>
PHP|PHP引用的简单解释
查看>>
gulp之JS、CSS、HTML、图片压缩以及版本更新
查看>>
实录分享|一篇文章看CNTV的容器化探索和平台搭建
查看>>
[到codewars打怪兽]乘不成
查看>>