python之函数
def get_host():
创建数据库连接
通过cursor方法获取游标
通过execute对sql进行操作
关闭游标
def get_item():
创建数据库连接
通过cursor方法获取游标
通过execute对sql进行操作
关闭游标
def get_tirggers():
创建数据库连接
通过cursor方法获取游标
通过execute对sql进行操作
关闭游标
完全可以按照上面的方式操作数据库,但是这样写存在两个问题:
1.代码重复过多
2.如果日后要更改操作数据库,比较麻烦
def con_sql(sql):
创建数据库连接
通过cursor方法获取游标
通过execute对sql进行操作
关闭游标
def get_host(host):
conn_sql(host)
def get_item(item):
conn_sql(item)
def get_tirggers(triggers):
conn_sql(triggers)
这样写可以体现出函数的好处:
1.解决了代码重用的问题
2.保持代码一致性,易维护
3.容易扩展
在此处提下函数式编程和面向过程编程的区别:
- 函数式:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
- 面向对象:对函数进行分类和封装,让开发“更快更好更强...”
函数的定义及各部分详解:
def test(x):
'''
:param x:传入参数是干啥的呀
:return: 返回的是啥呀
'''
x+=1
return x
test(4)
def:定义函数的关键字
test:函数名
():括号内可以定义形参
""" """:函数描述(建议写上)
x+=1:函数的逻辑程序
return : 定义返回值
test(4) : 函数名(参数): 调用运行,这里的x可以带参数,也可以不带的
第二:函数的三种定义方式
无参函数定义:
def hello():
print("hello world")
#调用也不需要传参
hello()
#输出结果:
hello world
有参函数定义:
def hello(x,y):
print("hello world",x,y)
#调用也不需要传参
hello("zzl","cyy")
#输出结果:
hello world zzl cyy
空函数定义:
def foo():
'''
:return:
'''
pass
foo()
空函数写不写参数是无所谓的,空函数主要用于开发大的程序的时候定义
空函数的好处是:
1.理清逻辑
2.哪一个模块有灵感就写哪一个模块
3.当你与你同事共同开发的该程序,你同事没有完成,你可以做一个判断,不影响你的工作
第三:函数的返回值
返回0个值---》None
def foo():
return
print(foo())
返回结果:
None
返回一个值---》返回的是return后定义的哪一个值
def foo():
return "hello world"
print(foo())
返回结果:
hello world
返回多个值---》返回的是一个元组
def foo():
return 1,2
print(foo())
返回结果:
(1, 2)
返回值可以是任何类型
def foo():
return 1,2,[3,4]
print(foo())
返回结果:
(1, 2, [3, 4])
第四:函数三种调用方式
作为语句形式的调用
def my_max(x,y):
return x if x > y else y
#语句形式:用于没有返回值的形式
my_max(1,2)
作为表达式形式的调用
def my_max(x,y):
return x if x > y else y
#表达式形式
res=my_max(1,2)
print(res)
结果:
2
作为参数形式的调用
def my_max(x,y):
return x if x > y else y
res=my_max(20,my_max(11,18))
print(res)
结果:
20
第五:函数的形参与实参
#形式参数:x,y,形式参数不占用内存空间,只有真正传值得时候才占用内存空间
def foo(x,y):
print(x)
print(y)
#实际参数1,2,实际参数是真正占用内存空间的
foo(1,2)
#注:在python中,名字没有任何储值的功能,任何的储值都是绑定一个名字到一个值
def foo(x,y):
return x+y
#实际参数1,2,实际参数是真正占用内存空间的
foo(1,2)
#注:在python中,名字没有任何储值的功能,任何的储值都是绑定一个名字到一个值
#参数的动态性:
print(foo(1,2))
#结果:3
print(foo('a','b'))
#结果:ab
print(foo(1,'a'))
#报错了
TypeError: unsupported operand type(s) for +: 'int' and 'str'
怎么解决这样的问题?
有一下三种方式:
第一种:加上帮助信息,这样其他人用函数的时候,就知道怎么去调用了,但是不能真正的对函数做到限定作用
def foo(x,y):
'''
:param x:int
:param y:int
:return:int
'''
return x+y
print(help(foo))
foo(x, y)
:param x:int
:param y:int
:return:int
第二种:
def foo(x,y):
if type(x) is int and type(y) is int: #给核心功能附加程序
return x+y
print(foo(1,2))
第三种:更加妖娆:
def foo(x:int,y:int)->int:
return x+y
print(foo.__annotations__)
print(foo(1,2))
结果:
{'x': <class 'int'>, 'y': <class 'int'>, 'return': <class 'int'>}
3
综合以上三种方式:用第一种方式,最后在加上异常处理为标志用法,其他两种也可以用,凭自己个人感觉哈
参数的具体使用:
实参应用:
按位置传值:
# 实参:
def foo(x,y):
print(x)
print(y)
# 按位置传值
foo(4,5)
结果:
4
5
按关键字传值:
def foo(x,y):
print(x)
print(y)
# 按关键字传值
foo(y=8,x=6)
结果
6
8
注意问题:
1.针对同一个形参,你可以按照位置或者按照关键字传值,但是只能用一种方式,不能给同一个形式参数传值
2.按关键字传值,必须在按位置传值右边
形参具体使用:
位置参数:
def foo(x,y,z):
print(x)
print(y)
print(z)
#位置参数:必须传值
foo(1,2,3)
输出结果:
1
2
3
默认参数:
#默认参数
def foo(x,y=6):
print(x)
print(y)
foo(1)
foo(1,8)
foo(x=1,y=10)
结果:
1
6
1
8
1
10
注意:默认参数可以不传值,但是也可以传值,传值得话,会覆盖默认参数的值,也可以按照关键字的方式传值。
默认参数的用途:
比如:我们部门男人很多
1.变化比较小的定义为默认参数
2.默认参数必须在位置参数和的右边
3.默认参数一定要定义成一个不可变的类型
4.默认参数在定义的时候已经被赋予了一个明确的值了,后期变化对其无效
验证1,2
def registor(user,age,gender='male'):
print(user)
print(age)
print(gender)
registor('zzl',18)
结果:
zzl
18
male
验证3:
def foo(x,l=[]):
l.append(x)
return l
print(foo(1))
print(foo(2))
print(foo(3))
结果:
[1]
[1, 2]
[1, 2, 3]
他们每一次调用都指向同一块内存地址
验证4:
name='lxh'
def foo(x,y=name):
print(x)
print(y)
name='xhb'
print(foo(1))
默认参数的好处:
1.降低了函数调用的复杂度
2.可用来扩展函数功能
*args可变参数
- *的作用是‘监听’位置参数,*args等待接收的参数必须是安位置来的
- 凡是遇到带*的参数,那么我们就把它看作是位置参数,把它打散了来看
基本形式:
def func(name,age,*args):
print(name)
print(age)
print(args)
func('cy',18,'student')
输出结果:
cy
18
('student',)
如果要求传入的参数为列表的情况
def func(name,age,*args):
print(name)
print(age)
print(args)
func('cy','18',*['student','lawyer'])
结果输出:
cy
18
('student', 'lawyer')
**kwargs关键字参数
基本形式
def foo(x,y,**kwargs):
print(x)
print(y)
print(kwargs)
foo(1,l=2,y=3,z=1,c=2)
结果输出:
1
3
{'l': 2, 'z': 1, 'c': 2}
传入的参数为字典
def foo(x,y,z):
print(x)
print(y)
print(z)
foo(**{'x':1,'z':3,'y':2}) # foo(x=1,z=3,y=2)
结果输出:
1
2
3
结合*args
def foo(x,y,*args,**kwargs):
print(x)
print(y)
print(args)
print(kwargs)
foo(1,3,*[6,8,9],c=10,l=12)
#输出结果:
1
3
(6, 8, 9)
{'c': 10, 'l': 12}
总结:以上四种参数的顺序:位置参数,*args,默认参数,**kwargs
第六:局部变量与全局变量
1 全局变量 2 msg='hello world' 3 4 def foo(): 5 print(msg) 6 7 foo() 8 9 输出结果: 10 hello world 11 12 局部变量 13 def foo(): 14 msg='hello world' 15 print(msg) 16 foo() 17 18 输出结果: 19 hello world 20 21 msg='hello msg' 22 def foo(): 23 msg='hello world' 24 print(msg) 25 foo() 26 print(msg) 27 28 输出结果: 29 hello world 30 hello msg 31 32 msg='hello msg' 33 def foo(): 34 global msg #定义的是全局变量 35 msg='hello world' 36 print(msg) 37 foo() 38 print(msg) 39 40 #输出结果: 41 hello world 42 hello world
第七:函数的递归
在函数内部,可以调用其他函数。如果一个函数在内部调用自己本省,这个函数就叫递归函数。
列举两个递归查询的例子
1 def foo(n): 2 print(n) 3 if int(n/2) == 0: 4 return n 5 return foo(int(n/2)) 6 7 foo(20) 8 9 输出结果: 10 20 11 10 12 5 13 2 14 1 15 16 def fact(n): 17 print(n) 18 if n == 1: 19 return 1 20 return n * fact(n - 1) 21 22 fact(6) 23 输出结果: 24 6 25 5 26 4 27 3 28 2 29 1
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
栈溢出示例:
View Code怎样解决这样的问题?
解决递归调用栈溢出的方法是通过尾递归优化,尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况 ,后续详解,尾调用与尾递归
第八:嵌套函数
函数的嵌套通俗的理解为函数套函数就ok了
函数嵌套的定义:
1 def func1():
2 def func2():
3 print("my name is func2")
4 func2()
5 func1()
6
7 #输出结果:
8 my name is func2
函数嵌套的调用:
def my_max1(x,y):
return x if x > y else y
def my_max2(a, b, c, d):
return my_max1(my_max1(my_max1(a,b),c),d)
print(my_max2(100,200,80,120))
输出结果:
200
#结合嵌套函数再看全局变量,与局部变量
msg='zzl'
def func1():
msg='cyy'
def func2():
msg='cy'
def func3():
print(msg)
return func3
return func2
func1()()()
输出结果:
cy
第九:函数是第一类对象
在python中所有的名字都没有储值功能
函数是第一类对象指的是:函数可以被当做数据来处理
被引用
def foo():
print("cyy")
f1=foo
f1()
# 输出结果:
cyy
可以当做参数
def foo():
print("cyy")
def func(msg):
print(msg)
msg()
func(foo)
输出结果:
<function foo at 0x00000000020D3E18>
cyy
可以当做返回值
def foo():
print("cyy")
def func(msg):
return msg
f=func(foo)
print(f)
f()
输出结果:
<function foo at 0x0000000002423E18>
cyy
可以当做容器类型的一个元素
def foo():
print("cyy")
func_dic={
'foo':foo
}
num=func_dic['foo']
num()
输出结果: cyy
第十:匿名函数
匿名函数就是不需要显式的指定函数
1.lambda
def calc(n):
return n**n
print(calc(10))
#换成匿名函数
calc = lambda n:n**n
print(calc(10))
# 输出结果:
# 10000000000
# 10000000000
2.map结合lambda
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])])
输出结果:
31121
k3
100
总结:
#当然了,map,filter,reduce,可以处理所有数据类型
name_dic=[
{'name':'zzl','age':1000},
{'name':'cyy','age':10000},
{'name':'zl','age':9000},
{'name':'cy','age':18},
]
#利用filter过滤掉1000,10000,9000
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来处理字符串列表啊,把列表中所有人都变成success,比方zzl_success
name=['zzl','cyy','zl']
res=map(lambda x:x+'_success',name)
for i in res:
print(i)
输出结果:
{'age': 18, 'name': 'cy'}
{'age': 18, 'name': 'cy'}
5050
5050
zzl_success
cyy_success
zl_success
第十一:高阶函数
满足一下一个特性都可称为高阶函数
把一个函数的内存地址当做一个参数传到另一个函数
函数的返回值是一个函数名
def add(x,y,f): print(f(x)+f(y)) add(-5,9,abs) 输出结果: 14
第十二:内置函数介绍



浙公网安备 33010602011771号