学习笔记之函数上
函数的介绍
-
函数也是个对象 function
-
函数可以用来保存一些可执行的代码,并且可以在需要的时候,多次对这些代码调用.
-
语法
def 函数名(形参1,形参2…):
代码块
return [‘返回值1’,‘返回值2’…]
调用函数
函数对象(实参1,实参2…)
def fn():
print('Hello World!')
fn()
注意:fn是函数对象 fn() 调用函数。
函数的参数
形参和实参
- 在定义函数的时候,可以在函数名后面的括号中定义数量不等的形参,定义多个形参要用","隔开.
- 形参(形式参数) 定义形参就是相当于在函数内部声明了变量,不是赋值
- 实参(实际参数) 如果函数定义的时候指定了形参,那么在调用的时候也必须传递实参.实参将会赋值给对应的形参,简单来说,有几个形参就得几个实参。
#定义两个数相加
def addition(a,b):
print(a,'+',b,'=',a+b)
addition(111,222)
# 111 + 222 = 333
函数的传递方式
定义形参时,可以为形参指定默认值。指定了默认值以后,如果⽤户传递了参数则默认值不会⽣效。如果⽤户没有传递,则默认值就会⽣效。
def fn(a=10):
print('a=',a)
fn()
fn(20)
- 位置参数:位置参数就是将对应位置的实参赋值给对应位置的形参。
def fn(a,b,c):
print('a=',a)
print('b=',b)
print('c=',c)
fn(1,2,3)
- 关键字参数 :关键字参数可以不按照形参定义的顺序去传递,⽽根据参数名进⾏传递。
def fn(a,b,c):
print('a=',a)
print('b=',b)
print('c=',c)
fn(b=1,c=2,a=3)
混合使⽤位置参数和关键字参数的时候必须将位置参数写在关键字参数前⾯
def fn(b,c,a):
print('a=',a)
print('b=',b)
print('c=',c)
fn(13,a=12,c=45)
#错误示例:
def fn(a,b,c):
print('a=',a)
print('b=',b)
print('c=',c)
fn(13,a=12,c=45)
fn(a=13,b,c=45)
'''
fn(13,a=12,c=45)
TypeError: fn() got multiple values for argument 'a'
fn(a=13,12,c=45)
^
SyntaxError: positional argument follows keyword argument
'''
实参的类型
- 实参可以传递任意类型的对象。
def fn(a):
print('a=',a)
fn(123)
fn(True)
fn('111')
fn([1,2,3,4])
fn((1,2,3,4))
fn({'name':'亚瑟'})
- 函数内进行运算时,需要注意参数的类型,在程序中不同类型的参数不能进行运算。
def fn(a,b):
'''定义两个函数相加'''
print(a+b)
fn(1,'2')
'''
print(a+b)
TypeError: unsupported operand type(s) for +: 'int' and 'str'
'''
拓展
在函数中重新给形参赋值,不会影响其他的变量,如果现在的形参执行的是一个对象,当我们通过形参去修改对象时,会影响到所有指向该对象的变量。
def fn(a):
print('a=',a,id(a))
c = 10
print('调用函数前c=',c,id(c))
fn(c)
print('调用函数后c=',c,id(c))
# 调用函数前c= 10 140713040615360
# a= 10 140713040615360
# 调用函数后c= 10 140713040615360
相当于 a=c 将变量c赋值给a,a,c通过指向内存中的同一对象。
def fn(a):
a = 20 #重新给形参赋值
print('a=',a,id(a))
c = 10
print('调用函数前c=',c,id(c))
fn(c)
print('调用函数后c=',c,id(c))
#调用函数前c= 10 140713040615360
# a= 20 140713040615680
#调用函数后c= 10 140713040615360
这相当于两个过程,首先将变量c赋值给a,然后再将变量a重新赋值.
#实参是一个列表,
def fn(a):
a[0]=10 #修改对象
print('a=',a,id(a))
c = [1,2,3]
print('调用函数前c=',c,id(c))
fn(c)
print('调用函数后c=',c,id(c))
# 调用函数前c= [1, 2, 3] 1618098450048
# a= [10, 2, 3] 1618098450048
# 调用函数后c= [10, 2, 3] 1618098450048
不定长参数
通常我们所见不定长参数有两种,一种是在形参前加‘*’号,另外一种是在形参前加‘**’号。
- 定义函数时,可以在形参前⾯加⼀个*,这样这个形参可以获取到所有的实参,它会将所有的实参保存到⼀个元组中。
def fn(*args):
'''定义一个任意个数的数字相加的函数'''
r = 0 ##定义变量保存结果
for i in args: #遍历元组
r+=i # r = r + i
print(r)
fn(1,2,3,4,5,6,7,8,9)
#45
def fn(*args):
'''将任意个列表合并成一个列表的函数'''
r = [] #定义变量保存结果
for i in args: #遍历元组
r+=i # r = r + i
print(r)
fn([1,2,3],[4,5,6],[7,8,9])
#[1, 2, 3, 4, 5, 6, 7, 8, 9]
#应用1 位置参数和带一个*号不定长参数的应用
def choice(shunt,*heros):
print('你选择了'+shunt)
print(shunt+'有以下英雄:')
for i in heros:
print('-->',i)
choice('中路','安琪拉','妲己','诸葛亮','周瑜','上官婉儿')
- 带两个* 号的形参可以接收关键字参数,它会将这些统⼀保存到字典当中。字典的键(key)就是参数的名字,字典的值(value)就是参数的值。
def fn(**a):
print('a=',a)
fn(a=1,b=2,c=3,d=4)
a= {'a': 1, 'b': 2, 'c': 3, 'd': 4}
def fn(name,price,**kwargs):
s = {} #建立一个空字典来存储数据
s['name'] = name
s['price'] = price
for k,v in kwargs.items():
s[k] = v
print(s)
fn('亚瑟',450,passive_skill='圣光守护',frist_skill='誓约之盾',second_skill='回旋打击',space='圣剑制裁')
#{'name': '亚瑟', 'price': 450, 'passive_skill': '圣光守护', 'frist_skill': '誓约之盾', 'second_skill': '回旋打击', 'space': '圣剑制裁'}
注意事项:
1.在形参中只能有一个带号 * 的参数,带一个 * 号的形参只能接受位置参数,不能接受关键字参数。
2.不定长参数不一定非要写在后面,但是要注意,带 * 号后面的参数,都必须以关键字参数的形式来进行传递。
3. 带两个 * 号的形参只有⼀个,并且必须写在所有参数的后面。
函数的返回值
- 函数的返回值就是函数执行以后返回的结果,一般都是通过return来指定函数的返回结果。
'''
函数的语法:
def 函数名(形参1,形参2,....):
代码块
return 返回值
函数名(实参1,实参2,...)
'''
- 可以直接使用函数的返回值,也可以通过一个变量来接收函数的返回值。
def fn():
pass #没有执行的程序
return 'Hello World!' #指定返回值
r = fn()
print(r)
# Hello World!
- 在函数中,return没有指定返回值,或者没有return,则相当于return None.另外在return后面的代码都不会执行,函数中的return相当于结束此函数执行的指令。
def s(*arg):
r = 0 #定义变量存储数据
for i in arg:
if i == 4:
return r
else:
r+=i
a=s(1,2,3,4,5,6)
print('a=',a)
#6
函数的作用域
作用域是什么?作用域就是变量生效的区域。
作用域为分为全局变量和局部变量。
局部变量
- 某个变量只有在该函数内使用,影响范围限定在这个函数内,这个变量称为局部变量。
- 在函数调用时创建,在调用结束时销毁。
def info():
msg = '我是局部变量'
print(msg)
info()
全局变量
- 某个变量的影响范围是在整个程序,这个变量成为全局变量。
- 在程序执行时创建,在程序执行结束时销毁。
def info():
print(msg)
msg = '我是全局变量'
info()
注意事项:
- 局部变量内容无法在其他函数引用,若要引用,则需要转化为全局变量。方法:在程序头加一行 global 变量名.
- 局部变量内容无法在主程序调用。
def info():
global msg #将局部变量转换为全局变量
msg = '局部变量'
print(msg)
msg = '全部变量'
info()
print(msg)
文档字符串
文档字符串在程序内用三引号’’‘内容’’'表示.通过用来说明这个函数的作用,参数的说明,返回值,让人很容易使用和理解这函数。查看方法help(函数名)。
def fn(a:int=1,b:float=1.0,c:str='Hello'):
'''
这是一个文档字符串的实例
:param a: 作用 类型 默认值 说明
:param b: 作用 类型 默认值 说明
:param c: 作用 类型 默认值 说明
:return: 返回值是多少
'''
return 0
help(fn)
递归函数
- 递归是什么?递归是一种解决问题的思想 ,整体思想是将一个大问题分解为一个一个的小问题,直到问题无法分解时,再去解决问题。
- 递归式的函数需要2个条件:
- 基线条件:问题可以被分解成最小问题,当满足基线条件时,递归就不在执行了。
- 递归条件:问题可以继续被分解。
求10的阶乘的方法。
'''
思路:
1! = 1
2! = 2 * 1
3! = 3 * 2 * 1
10 ! = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
'''
方法一:
s = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
方法二:
n = 1
for i in range(10,1,-1):
n *=i
print(n)
#或者
n=1
for i in range(0,10):
n*=i
print(n)
使用递归的方法求10的阶乘
def fn(n):
if n ==1:
return 1
else:
return n*fn(n-1)
s=fn(10)
print(s)
小练习:检查一个任意的字符串是否是回文字符串
定义一个函数,用来检查一个任意的字符串是否是回文字符串,如果是返回True,不是返回False。回 文字符串从前往后念和从后往前念是一样的。例如 TNT。
思路:根据输入的字符串判断从前往后念和从后往前念是一样的,即n[i]==[-i-1]。
#不使用递归方法
def fn(n:str):
''' 这个函数用于判断输入字符串是否是回文字符串
:param n: 参数 字符串
:return: True or False
'''
for i in range(len(n)):
if n[i] == n[-i-1]: #判断条件
continue #继续下一次判断
else:
return False #不满足就退出函数,并返回False
return True #条件都满足后,退出函数返回True
if __name__=='__main__': #主函数
n = str(input('输入一个需要判断的字符串:')) #输入字符串
if n != '': #输入不能为空,空无法判断
s = fn(n) #调用函数
print(s) #显示结果
else:
print('输入有误')
想递归方法的时候,发现还可以使用函数可以省略循环。
def fn(n,m):
n.reverse() #倒序
#n=n[::-1] #使用切片的方式倒序
if n == m: #倒序和正序一样就是回文字符串
return True
else:
return False
if __name__=='__main__': #主函数
n = list(str(input('输入一个需要判断的字符串:')))#输入字符串
m=n.copy() #注意不能使用 m=n,重新在内存中建立数据
if n : #输入不能为空,空无法判断
s = fn(n,m) #调用函数
print(s) #显示结果
else:
print('输入有误')
#使用递归方法:
def fn(n):
num = len(n)
if num == 0:
return True
elif num == 1:
return True
else:
if n[0] == n[-1]:
#n.pop() #删除列表最后一位
#n.reverse() #颠倒列表
#n.pop() #删除列表最后一位
n=n[1:-1] #切片去除首位和最后一位
return fn(n)
else:
return False
if __name__=='__main__': #主函数
n = list(str(input('输入一个需要判断的字符串:'))) #输入字符串
if n : #输入不能为空,空无法判断
s=fn(n) #调用函数
print(s) #显示结果
else:
print('输入有误')
总感觉递归写的有问题,但是不知道问题出在哪里。