190322函数
一、函数的定义
- 函数是逻辑结构化和过程化的一种编程方法。
def f1(x): #定义函数的关键字,x参数
"The function definitions" #函数的描述
print(x) #代码段
return x #返回值
二、函数的参数
形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量
实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值
- 形参和实参
def calc(x,y): #x,y为形参
res = x**y
return res
c = calc(2,8) #2,8为实参
print(c) #256
- 位置参数和关键字参数
- 位置参数和关键字参数混用时,位置参数必须要在关键字参数左边
def f1(x,y,z):
res = x+y+z
return res
print(f1(1,2,3)) #位置参数
print(f1(x=1,y=2,z=3)) #关键字参数
- 默认参数
def handle(x, type="mysql"):
print(type)
handle(2) #mysql
handle(2,type="oracle") #oracle
- 参数组
def t1(*args):
print(args)
t1(1,2,3) #(1, 2, 3)
t1([1,2,3]) #([1, 2, 3],)
t1(*[1,2,3]) #(1, 2, 3)
def t2(**kwargs):
print(kwargs)
t2(name="dongfei", age=18) #{'age': 18, 'name': 'dongfei'}
def t3(x,*args,**kwargs):
print(x,args,kwargs)
t3(2,4,6,5,90,name="dongfei",age=18) #2 (4, 6, 5, 90) {'age': 18, 'name': 'dongfei'}
三、全局变量和局部变量
- 如果函数的内容无global关键字,优先读取局部变量,无法对全局变量重新赋值
- 如果函数中有global关键字,变量本质上就是全局的那个变量,可读取可赋值
- 对可变类型变量,可对内部元素进行操作
- global
name = "maria" # 全局变量
name2 = "maria2"
def chang_name():
name = "jack" # 局部变量
global name2 #在函数内申请全局变量
name2 = "jack2"
print("change_name:", name)
chang_name()
print("global:", name)
print("global2:", name2)
- nonlocal
name = "old_dongfei"
def f1():
name = "dongfei"
def f2():
nonlocal name #在上一级全局,不是整个环境
name = "re_dongfei"
print(name) #dongfei
f2()
print(name) #re_dongfei
print(name) #old_dongfei
f1()
print(name) #old_dongfei
四、递归
- 必须有一个明确的结束条件
- 每次进入更深的一层递归,问题规模要有所减少
- 递归效率不高
- 汉诺塔
# 汉诺塔:问题是源于印度一个古老传说。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘,利用函数,实现N片盘的汉诺塔的移动步骤。
def Hanoi(n,a,b,c):
fro_m = a
buffer = b
to = c
m = n
if m == 1:
print("%s --> %s" % (fro_m, to))
else:
Hanoi(m-1,fro_m,to,buffer)
print("%s --> %s" % (fro_m, to))
Hanoi(m-1,buffer,fro_m,to)
Hanoi(9,"a","b","c")
- 递归除
def calc(n):
print(n)
if int(n // 2) == 0:
return n
res = calc(int(n // 2))
return res
calc(10)
- 伪递归优化:在最后一步进入下一层递归
五、函数的作用域
name = "dongfei"
def jack():
name = "jack"
def maria():
name = "maria"
print(name)
return maria
res = jack()
print(res) #<function jack.<locals>.maria at 0x0000000000B9D510>
res() #maria
name = "jack"
def a():
def b():
def c():
name = "maria"
print(name)
return c
return b
a()()() #maria
六、匿名函数
- 正常写法
def calc(x):
return x+1
res = calc(10)
print(res) #11
- 匿名函数写法
calc = lambda x:x+1 #x:形参,x+1:返回值, 如果返回值有多个值的话需要加小括号
res = calc(10)
print(res) #11
七、高阶函数
满足下列任意一点则是高阶函数。
- 返回值中包含函数名
- 函数接受的参数是一个函数名
def test1():
print("in the test1")
def test2():
print("in the test2")
return test1 #将test1函数的内存地址返回
n = test2() #in the test2
n() #in the test1
八、函数式编程(mapreduce)
- map:遍历序列中的每个元素,得到一个“列表”,该“列表”元素和位置都和原来一样
- filter:遍历序列中的每个元素,判断每个元素得到一个布尔值,如果True则留下来
- reduce:遍历一个序列,然后把序列进行合并操作
- 类似map源代码实例
l = [2,3,4,5]
def map_t(func,array):
ret = []
for i in array:
res = func(i)
ret.append(res)
return ret
print(map_t(lambda x:x+1,l)) #[3, 4, 5, 6]
- 内置函数map方法
l = [2,3,4,5]
name = "dongfei"
print(list(map(lambda x:x+1,l))) #[3, 4, 5, 6]
print(list(map(lambda x:x**2,l))) #[4, 9, 16, 25]
print(list(map(lambda x:x.upper(),name))) #['D', 'O', 'N', 'G', 'F', 'E', 'I']
- 类似filter源代码实例
people = ["Aaliyah","Aamina0","Bennett","Carl"]
def filter_t(func,array):
ret = []
for item in array:
if func(item):
ret.append(item)
return ret
res = filter_t(lambda n:n.startswith("A"),people)
print(res) #['Aaliyah', 'Aamina0']
- 内置函数filter方法
people = ["Aaliyah","Aamina0","Bennett","Carl"]
print(list(filter(lambda n:n.startswith("A"),people))) #['Aaliyah', 'Aamina0']
- 类似reduce源代码实例
num_l = [1, 2, 3, 5, 6, 77, 8, 5]
def reduce_t(func, array, init=None):
if init is None:
res = array.pop(0)
else:
res = init
for num in array:
res = func(res, num)
return res
print(reduce_t(lambda x, y: x * y, num_l, 100))
- 内置函数reduce方法
from functools import reduce
num_l = [1, 2, 3, 5, 6, 77, 8, 5]
print(reduce(lambda x,y:x*y,num_l,100))
九、python内置函数
print(abs(-88)) # 取绝对值 88
print(all([0, 2, "dongfei"])) # 将所有的元素做bool运算,所有的都为真,结果为真 False
print(any([0, 2, "dongfei"])) # 将所有的元素做bool运算,有一个为真,结果为真 True
print(bool('')) # 判断元素的bool是True还是False False
print(bytes("中文", encoding="utf-8")) # 将字符串转换为字节的形式 b'\xe4\xb8\xad\xe6\x96\x87'
print(chr(97)) # 对应ASCII码输出对应字符 a
print(ord("a")) # 与chr正好相反 97
print(dir(str)) # 打印某对象的所有方法
print(divmod(10, 3)) # 求10除3得商取余 (3, 1)
dic = {"name": "dongfei"}
dic_str = str(dic)
print(dic_str, type(dic_str)) # {'name': 'dongfei'} <class 'str'>
print(eval(dic_str)) # 将字符串中的数据结构提取出来 #{'name': 'dongfei'}
express = '1+2*(3+5)-7'
print(eval(express)) # 将字符串中的数学运算做运算 10
print(hash("dongfei")) # 将对象做hash运算,可hash的数据类型即不可变类型
print(help(dir)) # 获取某方法的帮助信息
print(bin(10)) # 十进制转二进制
print(oct(10)) # 十进制转八进制
print(hex(10)) # 十进制转十六进制
print(isinstance(123, int)) # 判断123是否为int类型
print(globals()) # 打印当前所有的全局变量
print(locals()) # 打印当前所有的局部变量
l = [1, 2, 4, 6, 9]
print(max(l)) # 9
print(min(l)) # 1
print(list(zip(('a', 'b', 'c'), (1, 2, 3)))) # 拉链[('a', 1), ('b', 2), ('c', 3)]
d = {"name": "dongfei", "age": 18, "gender": "M"}
print(list(zip(d.keys(), d.values()))) # [('age', 18), ('gender', 'M'), ('name', 'dongfei')]
p = {"yangguo": 17, "xiaolongnv": 21, "ouyangfeng": 57}
print(max(zip(p.values(), p.keys()))) # 求p字典中最大年级的key和value (57, 'ouyangfeng')
p2 = [
{"name": "yangguo", "age": 17},
{"name": "xiaolongnv", "age": 21},
{"name": "ouyangfeng", "age": 57},
]
print(max(p2, key=lambda dic: dic["age"])) # 求列表中最大年级的字典 {'age': 57, 'name': 'ouyangfeng'}
print(pow(2, 8)) # 2的8次方 256
print(pow(2, 8, 3)) # 2的8次方对3取余 1
l2 = [1, 2, 5, 6]
print(list(reversed(l2))) # 反转 [6, 5, 2, 1]
l3 = "hello"
s = slice(3, 5)
print(l3[s]) # 切片 lo
print(s.start) # 3
print(s.stop) # 5
print(s.step) # None
l4 = [3, 5, 8, 6, 9]
print(sorted(l4)) # 排序 [3, 5, 6, 8, 9]
print(sum(l4)) # 求和 31
print(type("str")) # 判断数据类型 <class 'str'>
print(vars())