函数,递归,内置函数
一 数学定义的函数与Python中的函数
初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域
例如y=2*x
python中函数定义:函数是逻辑结构化和过程化的一种编程方法。
python中函数定义方法: def test(x): "The function definitions" x+=1 return x def:定义函数的关键字 test:函数名 ():内可定义形参 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息) x+=1:泛指代码块或程序处理逻辑 return:定义返回值 调用运行:可以带参数也可以不带 函数名()
补充:
1.编程语言中的函数与数学意义的函数是截然不同的俩个概念,编程语言中的函数是通过一个函数名封装好一串用来完成某一特定功能的逻辑,数学定义的函数就是一个等式,等式在传入因变量值x不同会得到一个结果y,这一点与编程语言中类似(也是传入一个参数,得到一个返回值),不同的是数学意义的函数,传入值相同,得到的结果必然相同且没有任何变量的修改(不修改状态),而编程语言中的函数传入的参数相同返回值可不一定相同且可以修改其他的全局变量值(因为一个函数a的执行可能依赖于另外一个函数b的结果,b可能得到不同结果,那即便是你给a传入相同的参数,那么a得到的结果也肯定不同)
2.函数式编程就是:先定义一个数学函数(数学建模),然后按照这个数学模型用编程语言去实现它。至于具体如何实现和这么做的好处,且看后续的函数式编程。
二 为何使用函数
背景提要
现在老板让你写一个监控程序,监控服务器的系统状况,当cpu\memory\disk等指标的使用量超过阀值时即发邮件报警,你掏空了所有的知识量,写出了以下代码
while True: if cpu利用率 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 硬盘使用空间 > 90%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 if 内存占用 > 80%: #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接
上面的代码实现了功能,但即使是邻居老王也看出了端倪,老王亲切的摸了下你家儿子的脸蛋,说,你这个重复代码太多了,每次报警都要重写一段发邮件的代码,太low了,这样干存在2个问题:
- 代码重复过多,一个劲的copy and paste不符合高端程序员的气质
- 如果日后需要修改发邮件的这段代码,比如加入群发功能,那你就需要在所有用到这段代码的地方都修改一遍
你觉得老王说的对,你也不想写重复代码,但又不知道怎么搞,老王好像看出了你的心思,此时他抱起你儿子,笑着说,其实很简单,只需要把重复的代码提取出来,放在一个公共的地方,起个名字,以后谁想用这段代码,就通过这个名字调用就行了,如下
def 发送邮件(内容) #发送邮件提醒 连接邮箱服务器 发送邮件 关闭连接 while True: if cpu利用率 > 90%: 发送邮件('CPU报警') if 硬盘使用空间 > 90%: 发送邮件('硬盘报警') if 内存占用 > 80%: 发送邮件('内存报警')
你看着老王写的代码,气势恢宏、磅礴大气,代码里透露着一股内敛的傲气,心想,老王这个人真是不一般,突然对他的背景更感兴趣了,问老王,这些花式玩法你都是怎么知道的? 老王亲了一口你儿子,捋了捋不存在的胡子,淡淡的讲,“老夫,年少时,师从京西沙河淫魔银角大王 ”, 你一听“银角大王”这几个字,不由的娇躯一震,心想,真nb,怪不得代码写的这么6, 这“银角大王”当年在江湖上可是数得着的响当当的名字,只可惜后期纵欲过度,卒于公元2016年, 真是可惜了,只留下其哥哥孤守当年兄弟俩一起打下来的江山。 此时你看着的老王离开的身影,感觉你儿子跟他越来越像了。。。
总结使用函数的好处:
- 解决代码重用问题
- 统一维护
- 程序的组织结构清晰,可读性强
函数需要先定义,后使用:
def foo(): 'foo function' print('from the foo') print(foo.__doc__)
语法:
''' def 函数名(arg1,arg2,arg3): '描述信息' 函数体 return 1 ''' foo() #语句 res=bar(1,2) #表达式
注意事项:
函数是弱类型,没有类型限制,使用起来非常灵活。 但是有注意事项,加上注释标记参数类型,实参一定要是不可变类型(数字、字符串、元组))。 最好不要用可变类型,不能变动函数外的值。
三 函数和过程
过程定义:过程就是简单特殊没有返回值的函数
这么看来我们在讨论为何使用函数的的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在python中有比较神奇的事情
def test01(): msg='hello The little green frog' print msg def test02(): msg='hello WuDaLang' print msg return msg t1=test01() t2=test02() print 'from test01 return is [%s]' %t1 print 'from test02 return is [%s]' %t2
总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,
所以在python中即便是过程也可以算作函数。
def test01(): pass def test02(): return 0 def test03(): return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'} t1=test01() t2=test02() t3=test03() print 'from test01 return is [%s]: ' %type(t1),t1 print 'from test02 return is [%s]: ' %type(t2),t2 print 'from test03 return is [%s]: ' %type(t3),t3
总结:
返回值数=0:返回None
返回值数=1:返回object
返回值数>1:返回tuple
四 函数参数
1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)
4.默认参数 # 在函数定义阶段就已经定义了
5.参数组
变量不能储值,只是一种绑定关系。
函数的参数介绍:
def foo(x,y): print(x) print(y)
在实参的角度来分析:
第一种:按照位置传值 foo(1,2) foo(2,1) 第二种:按照关键字传值 foo(x=1,y=2) foo(y=2,x=1) 第三种:混着用 foo(1,y=2) 问题一:按位置传值必须在按关键字传值的前面 foo(y=2,1) #报错 问题二:对于一个形参只能赋值一次 foo(1,y=2)
从形参的角度来分析
第一种:位置参数;必须传值的参数 def foo(x,y): print(x) print(y) foo(y=2,x=1) 第二种:默认参数 def foo(x,y=1) print(x) print(y) # foo(1) # foo(1,2) foo(y=2,x=2) def register(name,sex='male'): print(name) print(sex) register('luchuan') #默认参数必须注意的问题是:默认参数必须放到位置参数的后面
可变参数:
*args # 按位置调用,多余得位置参数会会被赋值给*args接收。
**kwargs # 按关键字调用,多余得关键字参数会被**kwargs接收。
# *args 参数:
#从形参的角度 def foo(*args): print(args) foo(1,2,3) #从实参的角度 def bar(x,y,z): print(x) print(y) print(z) bar(*(1,2,3)) # *args与位置参数和默认参数混用:*args要放到位置参数后面 def foo(x,*args,y=1): print(x) print(y) print(args) foo(1,2,3,4,5,6,y=1000) def my_sum(nums): #nums=(1,2,3,4,5),不带* res=0 for i in nums: res += i return res print(my_sum((1,2,3,4,5))) def my_sum(*nums): #nums=(1,2,3,4,5),带* res=0 for i in nums: res += i return res #print(my_sum((1,2,3,4,5))) print(my_sum(1,2,3,4,5))
# **kwargs 参数
#从形参的角度: def foo(**kwargs): #x=1,y=2 print(kwargs) foo(x=1,y=2,z=3) #从实参的角度 def foo(x,y,z=1): print(x) print(y) print(x) # foo(**{'x':1,'y':2,'z':3}) #foo(x=1,y=2,z=3) # foo(**{'x':1,'y':2}) #foo(x=1,y=2) # foo(**{'a':1,'y':2}) #foo(a=1,y=2) #混着用的位置问题 def foo(x,*args,**kwargs): print(x) print(args) print(kwargs) foo(1,y=1,z=2) def foo(*args,**kwargs): print(args) print(kwargs) foo(1,1,1,1,1,1,a=1,b=2) def auth(name,password,sex='male'): print(name) print(password) print(sex) def foo(*args,**kwargs): #args=('egon','123') kwargs={} print('from foo') auth(*args,**kwargs) # auth(*'egon','123'),**{})--->auth('egon','123') foo('egon','123') def auth(name,password,sex='male'): print(name) print(password) print(sex) def foo(*args,**kwargs): #args=('egon','123') kwargs={} print('from foo') auth(*args,**kwargs) # auth(*'egon','123'),**{})--->auth('egon','123') #foo('egon','123') foo('ASB','123',sex='female') foo(name='ASB',password='123',sex='female')
五 函数返回值
三种return返回值:
函数的返回值可以是任意类型
没有return--->None #没有返回值或没有指定返回值,默认返回None
return 1 --->1 #有一个返回值
return 1,2,3 --->(1,2,3) #多个返回值
#注意:函数中执行一次return就退出。
foo() #这是语句
res=bar(1,2) #这是表达式
解压变量值:
>>> a,b,c,d,e=[1,2,3,4,5] >>> a,_,_,_,e=[1,2,3,4,5] >>> a 1 >>> e 5 >>> a,*_,e=[1,2,3,4,5] >>> a 1 >>> e 5 >>> a,_,_,_,e=[1,2,3,4,5] >>> head,*_=[1,2,3,4,5] >>> head 1 >>> *_,tail=[1,2,3,4,5] >>> tail 5 >>> a,b={1,2} >>> a 1 >>> b 2 >>> a,b={'name':'egon','age':18} >>> a 'name' >>> b 'age' >>>
五 局部变量和全局变量
在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。
name='lhf' def change_name(): print('我的名字',name) change_name() def change_name(): name='帅了一笔' print('我的名字',name) change_name() print(name) def change_name(): global name name='帅了一笔' print('我的名字',name) change_name() print(name)
名称空间分为三种:
- 内置名称空间
- 全局名称空间
- 局部名称空间
C:\Users\Administrator>python
Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 08:06:12) [MSC v.1900 64 bit (AM
D64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
#内置名称空间:
#查看内置名称空间 import builtins dir(builtins) #内置名称空间
>>> import builtins >>> dir(builtins) ['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException', 'Blocki ngIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning', 'ChildProcessError ', 'ConnectionAbortedError', 'ConnectionError', 'ConnectionRefusedError', 'Conne ctionResetError', 'DeprecationWarning', 'EOFError', 'Ellipsis', 'EnvironmentErro r', 'Exception', 'False', 'FileExistsError', 'FileNotFoundError', 'FloatingPoint Error', 'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError', 'ImportWarni ng', 'IndentationError', 'IndexError', 'InterruptedError', 'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError', 'MemoryError', 'ModuleNotFoundEr ror', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented', 'NotImplement edError', 'OSError', 'OverflowError', 'PendingDeprecationWarning', 'PermissionEr ror', 'ProcessLookupError', 'RecursionError', 'ReferenceError', 'ResourceWarning ', 'RuntimeError', 'RuntimeWarning', 'StopAsyncIteration', 'StopIteration', 'Syn taxError', 'SyntaxWarning', 'SystemError', 'SystemExit', 'TabError', 'TimeoutErr or', 'True', 'TypeError', 'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEnc odeError', 'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarni ng', 'ValueError', 'Warning', 'WindowsError', 'ZeroDivisionError', '__build_clas s__', '__debug__', '__doc__', '__import__', '__loader__', '__name__', '__package __', '__spec__', 'abs', 'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'byte s', 'callable', 'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credit s', 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit', 'fi lter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', 'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', 'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview', 'min', 'next', 'object' , 'oct', 'open', 'ord', 'pow', 'print', 'property', 'quit', 'range', 'repr', 're versed', 'round', 'set', 'setattr', 'slice', 'sorted', 'staticmethod', 'str', 's um', 'super', 'tuple', 'type', 'vars', 'zip']
#全局名称空间
import time class Foo: pass x=1 def funcname() print(x) print(x) funcname() #顶头写得,没有缩进级别。 #time、Foo、x、fucname 都是全局名称空间
补充:这个也是全局名称空间
x = 1 if x == 1: y = 2 def test(): print(y) test()
#局部名称空间
def funcname(): y=100 #局部名称空间 print(y) print(x)
内置名称空间和全局名称空间又称为全局作用域
局部名称空间又称为局部作用域
注:查找顺序,遵循先定义后使用规则:
先局部名称空间再找全局名称空间,最后找内置名称空间。
名称空间的查询:
print(locals()) #查询局部名称空间 print(globals()) #查询全局名称空间
x=1 def func(): print('from func') x=2 print(locals()) print(globals()) # print(globals()) func() # print(locals())
函数嵌套:
def my_max(x,y): res = x if x > y else y return res # print(my_max(10,100)) def my_max4(a,b,c,d): res1=my_max(a,b) res2=my_max(res1,b) res3=my_max(res2,d) return res3 print(my_max4(1,20,3,4))
函数定义: #有了嵌套定义之后就有了嵌套作用域的概念。
x=11111111111111111111 def f1(): # x=1 print("-------f1 ",x) def f2(): # x=2 print("-------f2 ", x) def f3(): x=3 print("-------f3 ", x) f3() f2() f1()
函数第一类对象:
函数是第一类对象,可以被赋值、参数传递、当成返回值、容器类型的元素。
#函数可以被赋值def foo(): print('foo') f=foo print(f) f() #<function foo at 0x00000000027DB8C8> #foo
#把函数当成参数传递
def foo(): print('foo') def bar(func): print(func) func() bar(foo) #<function foo at 0x0000000001E1B8C8> #foo
#把函数当成返回值
def foo(): print('foo') def bar(func): print(func) return func f=bar(foo) print(f) f() #<function foo at 0x00000000021BB8C8> #<function foo at 0x00000000021BB8C8> #foo
闭包:
闭包定义:首先必须是内部定义的函数,该函数包含对外部作用域而不是全局作用域名字的引用
注:闭包函数有什么好处,携带一种状态,内部自带url。
def f1(): x=1 def f2(): print(x) return f2 f=f1() print(f) x=123123 f() print(f.__closure__) print(f.__closure__[0].cell_contents)
应用1:
from urllib.request import urlopen def get(url): return urlopen(url).read() print(get('http://www.baidu.com')) print(get('http://www.python.org'))
应用2:
from urllib.request import urlopen def f1(url): def f2(): print(urlopen(url).read()) return f2 python=f1('http://www.python.org') python()
六 前向引用之‘函数即变量’
def action(): print 'in the action' logger() action() 报错NameError: global name 'logger' is not defined def logger(): print 'in the logger' def action(): print 'in the action' logger() action() def action(): print 'in the action' logger() def logger(): print 'in the logger' action()
七 嵌套函数和作用域
看上面的标题的意思是,函数还能套函数?of course
name = "Alex" def change_name(): name = "Alex2" def change_name2(): name = "Alex3" print("第3层打印",name) change_name2() #调用内层函数 print("第2层打印",name) change_name() print("最外层打印",name)
此时,在最外层调用change_name2()会出现什么效果?
没错, 出错了, 为什么呢?
作用域在定义函数时就已经固定住了,不会随着调用位置的改变而改变
例一: name='alex' def foo(): name='lhf' def bar(): print(name) return bar func=foo() func() 例二: name='alex' def foo(): name='lhf' def bar(): name='wupeiqi' def tt(): print(name) return tt return bar func=foo() func()()
八 递归
def calc(n): print(n) if int(n/2) ==0: return n return calc(int(n/2)) calc(10) 输出: 10 5 2 1
#_*_coding:utf-8_*_ __author__ = 'Linhaifeng' import time person_list=['alex','wupeiqi','yuanhao','linhaifeng'] def ask_way(person_list): print('-'*60) if len(person_list) == 0: return '没人知道' person=person_list.pop(0) if person == 'linhaifeng': return '%s说:我知道,老男孩就在沙河汇德商厦,下地铁就是' %person print('hi 美男[%s],敢问路在何方' %person) print('%s回答道:我不知道,但念你慧眼识猪,你等着,我帮你问问%s...' %(person,person_list)) time.sleep(3) res=ask_way(person_list) # print('%s问的结果是: %res' %(person,res)) return res res=ask_way(person_list) print(res) 递归问路
递归特性:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
堆栈扫盲http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html
尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
data = [1, 3, 6, 7, 9, 12, 14, 16, 17, 18, 20, 21, 22, 23, 30, 32, 33, 35] def binary_search(dataset,find_num): print(dataset) if len(dataset) >1: mid = int(len(dataset)/2) if dataset[mid] == find_num: #find it print("找到数字",dataset[mid]) elif dataset[mid] > find_num :# 找的数在mid左面 print("\033[31;1m找的数在mid[%s]左面\033[0m" % dataset[mid]) return binary_search(dataset[0:mid], find_num) else:# 找的数在mid右面 print("\033[32;1m找的数在mid[%s]右面\033[0m" % dataset[mid]) return binary_search(dataset[mid+1:],find_num) else: if dataset[0] == find_num: #find it print("找到数字啦",dataset[0]) else: print("没的分了,要找的数字[%s]不在列表里" % find_num) binary_search(data,66) 二分查找
九 匿名函数
匿名函数就是不需要显式的指定函数
#这段代码 def calc(n): return n**n print(calc(10)) #换成匿名函数 calc = lambda n:n**n print(calc(10))
你也许会说,用上这个东西没感觉有毛方便呀, 。。。。呵呵,如果是这么用,确实没毛线改进,不过匿名函数主要是和其它函数搭配使用的呢,如下
l=[3,2,100,999,213,1111,31121,333] print(max(l)) dic={'k1':10,'k2':100,'k3':30} print(max(dic)) print(dic[max(dic,key=lambda k:dic[k])])
res = map(lambda x:x**2,[1,5,7,4,8]) for i in res: print(i) 输出 1 25 49 16 64
十 函数式编程
http://egon09.blog.51cto.com/9161406/1842475
11 高阶函数
满足俩个特性任意一个即为高阶函数
1.函数的传入参数是一个函数名
2.函数的返回值是一个函数名
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 ret print(map_test(array)) #如果我们的需求变了,不是把列表中每个元素都平方,还有加1,减一,那么可以这样 def add_num(x): return x+1 def map_test(func,array): ret=[] for i in array: ret.append(func(i)) return ret print(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 res print(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=init for i in l: res=func(res,i) return res print(reduce_test(lambda x,y:x+y,array)) print(reduce_test(lambda x,y:x+y,array,50)) reduce函数
#电影院聚集了一群看电影bb的傻逼,让我们找出他们 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 ret print(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_list res=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 reduce print(reduce(lambda x,y:x+y,range(100),100)) print(reduce(lambda x,y:x+y,range(1,101))) #用map来处理字符串列表啊,把列表中所有人都变成sb,比方alex_sb name=['alex','wupeiqi','yuanhao'] res=map(lambda x:x+'_sb',name) for i in res: print(i) 总结
十一 内置函数
字典的运算:最小值,最大值,排序 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 "<stdin>", line 1, in <module> ValueError: min() arg is an empty sequence sorted(iterable,key=None,reverse=False)
内置参数详解 https://docs.python.org/3/library/functions.html?highlight=built#ascii
十二 本节作业
有以下员工信息表
当然此表你在文件存储时可以这样表示
1,Alex Li,22,13651054608,IT,2013-04-01
现需要对这个员工信息文件,实现增删改查操作
- 可进行模糊查询,语法至少支持下面3种:
- select name,age from staff_table where age > 22
- select * from staff_table where dept = "IT"
- select * from staff_table where enroll_date like "2013"
- 查到的信息,打印后,最后面还要显示查到的条数
- 可创建新员工纪录,以phone做唯一键,staff_id需自增
- 可删除指定员工信息纪录,输入员工id,即可删除
- 可修改员工信息,语法如下:
- UPDATE staff_table SET dept="Market" WHERE where dept = "IT"
注意:以上需求,要充分使用函数,请尽你的最大限度来减少重复代码!