函数
可读性强 复用性强
def 函数名():
函数体
return 返回值
函数名() 调用函数不接受返回值; 函数名就是函数的内存地址,加上括号就等于调用了
返回值 = 函数名() # 接受返回值
所有的函数 只定义不调用就一定不执行
要先定义后调用
# 定义函数 def mylen(s): # 定义一个函数 在这里s是形参 n = 0 for i in s: n += 1 return n # 返回值 mylen() # 调用函数 print(mylen('dfgsdf')) # 这里里面的值是实参
'''
返回值 #
没有返回值:默认返回None
不写return 函数内的代码执行完毕自动结束
只写return 结束一个函数
或 return None
可以返回一个值:结束了函数且返回一个值,可以是任意的值
return value
可以返回多个值:多个值之间用逗号隔开,接受的时候可以用一个变量接受(元祖),也可以用等量的多个变量接收
return ...
参数
形参:定义函数的时候
实参:调用函数的时候
没有参数
定义和调用的时候括号里不写内容
有一个参数
传什么就是什么
有多个参数
站在实参角度
按照位置传参
按照关键字传参
混着传参 位置传参>关键字传参
不能给同一个参数传多个值
站在形参
位置传参:必须传,且有几个参数就传几个值
默认参数:可以不传,就用默认的,如果传了实参,就用实参
动态参数:可以任意接受多个参数
参数名前加* , 习惯参数名*args :接受的是按照位置传参的值,组织成一个元祖
全部不知多少的关键字传参:**kwargs :接受的是按照关键字传参的值,组织成一个字典
def func(*args,**kwargs) 既可以接受位置又可以关键字 ,顺序不可互换
顺序: 位置参数 > *args > 默认参数 > **kwargs
def func(*args): # 站在形参的角度上,给变量加上*,就是组合所有传来的值 print(args) l = [1,2,3,4,5] func(*l) # 站在实参的角度上,给一个序列加上*,就是将这个序列按照顺序分各个元素 def func2(**kwargs): print(kwargs) d = {'a':1,"b":2} func2(**d) # 同样 **d # 函数的注释 def func(): ''' 这个函数实现了什么功能 参数1: 参数2: return:是字符串或者列表的长度 ''' pass
# 默认陷阱 def fun(l = []): # 当参数是个可变数据类型,那么每一次调用函数的时候,如果不传值就公用这个数据类型的资源 l.append() print(l)
命名空间
内置命名空间:python解释器
就是python解释器启动就可以使用的名字储存空间
内置的名字在启动解释器的时候被加载进内存里
eg:print()
全局命名空间:我们写的代码但不是函数中的代码
是在程序从上到下被执行的过程中依次加载进内存的
放置了我们设置的所有变量名和函数名
局部命名空间:函数
就是函数内部定义的名字
当调用函数的时候 才会产生这个名称空间,随着函数执行结束,这个命名空间就又消失了
在局部:可以使用全局,内置
在全局:可以使用内置 但不能使用局部
在内置:不能使用全局和局部
依赖倒置原则
在正常情况下,直接使用内置的名字
当我们在全局定义了和内置名字空间中同名的名字时,会使用全局的名字
如果没有就找上一级要,上级没有在找上一级要,如果内置的名字空间都没有,就会报错
多个函数应该拥有多个独立的局部名字空间,不互相共享
作用域
全局作用域 -->内置和全局名字空间中的名字都属于全局作用域 -- globals()查看
局部作用域 -->函数 局部命名空间中的名字属于局部作用域 -- locals()查看
a = 1 # 这个定义在全局 def func(): global a a += 1 print(a) print(globals()) # 永远打印全局的名字 print(locals()) # 本地的 输出什么 根据locals所在的位置
对于不可变数据类型 在局部可查看局部作用域中的变量,但不能直接修改
如果想要修改 需要在程序的一一开始添加global声明 谨慎使用会让 代码不安全
如果在一个局部内声明一个global变量,那么这个变量在局部的所有操作将对全局的变量有效
nonlocal 只能用于局部变量 找上层中离当前函数最近一层的局部变量
def max(a,b): return a if a>b else b def the_max(x,y,z): # 函数嵌套调用 c = max(x,y) return max(c,z) print(the_max(1,2,3))
# 函数嵌套定义 # 内部函数可以使用外部函数变量 def outer(): a = 1 def inner(): b = 2 print(a) def inner1(): nonlocal a # 声明了一个上层局部的第一个变量 a = a+1 print(b) inner1() print(a) inner() outer()
def func(): print(123) # func() # 函数名就是内存地址 func2 = func # 函数名可以赋值 func2() l = [func,func2] # 函数名可以作为容器类型的元素 print(l) for i in l: i() def hel(f): f() return f # 函数名可以作为函数的返回值 hel(func) # 函数名可以作为函数的参数 v = hel(func) v()
# 闭包 :嵌套函数,内部函数调用外部函数的变量 def outer(): a = 1 def inner(): print(a) print(inner.__closure__) return inner # 我返回这个函数值 outer() print(outer.__closure__) inn = outer() # 全局的变量指向了一个内部函数地址 inn() # 在一个函数外部调用里面函数 延长了 a=1 的生存空间 #>> (<cell at 0x000002AE11EA1888: int object at 0x00007FF9FC5CE350>,) 只要cell什么 证明就是闭包 #>> None 不是闭包 import urllib from urllib.request import urlopen def get_url(): url = 'https://www.douban.com/' def get(): ret = urlopen(url) print(ret) return get hai = get_url() hai()
几道题
1、写函数,检查获取传入列表或元祖对象的所有奇数位索引对应的元素,并将其作为新列表返回给调用者
def func(l): return l[1::2] # 切片
2.写函数 判断用户传入的值(字符串、列表、元祖)长度是否大于5
def funlen(x): return len(x)>5
3.写函数 检查传入列表的长度,如果大于2那边仅保留前两个长度的内容,并将新内容返回给调用者
def lentwo(l): if len(l)>2: return l[:2]
4.写函数 计算传入字符串中数字、字母、空格、以及、其他的个数,并返回结果
def er(s): dic = {'num':0,'alpha':0,'space':0,'other':0} for i in s: if i.isdigit(): dic['num']+=1 elif i.isalpha(): dic['alpha']+=1 elif i.isspace(): dic['space']+=1 else: dic['other']+=1 return dic print(er('jsdhfjs lksjdf654654 ds-0='))
5.写函数,检查用户传入的对象(字符串、列表、元祖)的每一个元素是否含有空内容,并返回结果
def ou(x): if type(x) is str and x: # 参数是字符串 for i in x: if i == ' ': return True elif x and type(x) is list or type(x) is tuple: # 参数是列表或者元祖 for i in x: if not i: return True elif not x: # 直接就是空了 return True print(ou(''))
6.写函数,检查传入字典的每一个value的长度,如果大于2,那么仅保留前两个长度的内容,并将新内容返回给调用者
die = {'k1':'vlvl','k2':[11,22,33,44]} # 字典中的value只能是字符串或列表 def di(dic): for k in dic: if len(dic[k])>2: dic[k] = dic[k][:2] return dic print(di(die))
7.写函数,接受两个数字参数,返回比较大的那个数字
def mymax(a,b): return a if a>b else b # 三元运算 print(mymax(3,3)) #三运运算 # 条件返回True的结果 if 条件 else 条件返回False的结果 # 必须要有结果 # 必须要有if和else # 只能是简单的情况
8.写函数,用户传入修改的文件名,与要修改的内容,执行函数,完成整改文件的批量修改操作(进阶)(文件名要输入绝对路径)
def file(filename,old,new): with open(filename,encoding='utf-8',) as f, open('%s.bak'%filename,'w',encoding='utf-8') as f1: for i in f: if old in i: i = i.replace(old,new) f1.write(i) import os os.remove(filename) os.rename('%s.bak'%filename,filename)
参考:http://www.cnblogs.com/Eva-J/articles/7125925.html