奋斗小糖果
1. 函数的实参
(1)调用函数时,解析器是不会检查实参的类型,所以函数的实参可以是任何类型的对象。因此必须注意调用实参的类型。
#错误问题1
TypeError: unsupported operand type(s) for +: 'int' and 'str'
不支持整数与字符串的相加
(2)在函数中重新给形参赋值时,不会影响其他变量。
def fn(a):
a=20#函数内部重新给形参赋值
print('a='a)
c=10
fn(c)
a=20
c=10#重新给函数中的形参赋值,不会影响其他变量,c依然是=10。
(3)如果现在的形参执行的是一个对象时,当我们通过形参去修改对象时,会影响到所有指向该对象的变量。
#为了明显看出结论(3),我使用了一个字符串修改形参的值。
def fn(a):
a[0]=10
print(f'a={a}')
c=list(range(1,10))
fn(c)
print(f'c={c}')
a= ['A', 2, 3, 4, 5, 6, 7, 8, 9]
b= ['A', 2, 3, 4, 5, 6, 7, 8, 9]
2. 不定长参数
-
不定长参数:
在定义函数的时候,可以在形参前面加上星号,加星号的形参就可以获取的所有实参,同时获取的所有实参将会放到一个以形参为对象的元组中。 -
不定长参数分类
(1)形参前加一个星号的不定长参数
不定长参数不一定非要写在后面,但是要注意,带*号后面的参数,都必须以关键字参数的形式来进行传递,同时关键字的位置必须和形参位置对应否则出现下面的报错。
#举例
def fn(*b,a):
print('a=',a)
print('b=',b)
fn(1,a=2,3,4,5,6,7,8,9)#由于星号形参在前,未加星号的形参在后,则按上面的总结,a=9按关键字传入给形参a,但是我现在传递为形参a的位置是属于b的位置,所以出现以下报错。
SyntaxError: positional argument follows keyword argument
#解决问题的办法是,a进行位置关键字传入a=9
def fn(*b,a):
print('a=',a)
print('b=',b)
fn(1,2,3,4,5,6,7,8,a=9)
a= 9
b= (1, 2, 3, 4, 5, 6, 7, 8)
#一星号的不定长参数案例
def fn(a,*b):
print('a=',a)
print('b=',b)
fn(1,2,3,4,5,6,7,8,9)
a= 1
b= (2, 3, 4, 5, 6, 7, 8, 9)#加星号的形参就可以获取的所有实参,同时获取的所有实参将会放到一个以形参为对象的元组中
(2)形参前加两个星号的不定长参数
**形参
2.1 两种不定长参数的区别
(1)一个星号的形参只能接受位置参数
(2)两个星号的参数可以接受关键字形参,并将这些参数以字典的方式保存。形参名就是字典的键key,字典的值value就是形参的值;两个星号的形参只能有一个,而且只能放在所有参数的后面。
def fn(a,**b):
print('a=',a)
print('b=',b)
fn(a=1,b=2,c=3,d=4,e=5,f=6,g=7,h=8)
a= 1
b= {'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6, 'g': 7, 'h': 8}
3. 函数的返回值
函数返回值就是返回函数执行的结果,一般使用return来指定返回函数的值。
注意:函数返回值也可以通过一个变量来接收函数的返回值。
def fn(a,b):
return a+b#返回值为a+b
y=fn(1,10)#用一个变量y接收函数返回值
print(y)#打印返回值
11
3.1 return的介绍
(1)return后面可以跟任意对象。
(2)一个函数没有写return ,或者仅仅写了一个return 那么就相当于 return None
(3)在函数中,return后面的代码都不会执行。return一旦执行函数自动结束
def fn2():
print('haha')
return
print('heihei')
r=fn2()
print(r)
haha#return下面的代码不执行
None#return后面没有跟其他东西,返回值为None
- #拓展:1-1函数与循环的结合
def fn():
for i in range(5):
if i ==3:
break#break循环语句中,直接结束整个循环
print(i)
print('执行完毕')
fn()#一定要调用函数,我总是无奈忘记
0
1
2
执行完毕
3.2 拓展
- 1-2 return后面的代码直接不执行
这就是为什么别人在做模型时 经常用return,而我看不懂的原因。
一定要记住函数中的 return不仅可以作为接收返回值 也可以控制结束。
def fn():
for i in range(5):
if i ==3:
return#函数中的return后面的代码不执行
print(i)
print('执行完毕')
fn()#一定要调用函数,我总是无奈忘记
0
1
2
3.2 函数元组的遍历
def fn(*a):
r=0
for i in a:
r+=i
return r
r=fn(1,2,3,4,5,6)#用一个变量接收返回值
print(r)
21
def fn(*a):
r1=0
for i in a:
r1+=i
return r1
print(fn1(1,2,3,4,5,6))#没有使用变量接收返回值
注意上述两个函数接收返回指定方式,接不接受返回值,根据自己的需求而定。
假如返回值需要用于后续计算则需要用变量接收返回值。
4. 函数的作用域
4.1 作用域的分类
- 作用域分为全局作用域和局部作用域
(1)函数的作用域:
在函数内部的称为局部作用域,只在函数内部发生作用或被访问;
在不存在函数嵌套时,函数外部的定义的变量称为全局作用域变量,全局变量可以在程序的任意位置进行访问。
如果在函数中存在函数嵌套,那么最外层函数的变量定义可以在函数中任意位置使用,但是函数内层的定义变量(局部变量)不能被它外层的函数使用。代码走你理解
def fn():
a=10
def fn1():
a=20
print('fn1中a =',a)
fn1()
print('fn中的a=',a)
fn()
fn1中a = 20
fn中的a= 10
#案例中:
第一:在函数fn1内部我们定义了一个变量a=20,在fn1外部函数fn中冶定义了a=10,但是我们的函数fn1调用的是a=20,没用调用a=10.函数的全局变量和局部变量,函数只调距离函数位置的进的变量。
第二:函数fn调用的是a=10的变量,未调用a=20的变量,是因为a=20是函数fn中函数fn1的局部变量,外部函数fn不能调用内部函数的局部变量。
- 怎么修改函数内部从而修改全局变量,使用global关键字来声明变量,通过global声明的变量就是全局变量。
案例走起:
a=30
def fn():
global a#global 放在局部变量之前 否则报错
a=10
print('a=',a)
fn()
print('外部变量a=',a)
fn中的内部变量a= 10
5. 递归函数
(1)-运行原理
递归函数是函数调用函数自己
(2)思想
- 整体思想是将一个大问题分解为一个一个的小问题,直到问题无法分解时,再去解决问题。
(3)递归函数的组成或者两个条件 - (1)基线条件
问题可以被分解为最小的问题,当满足基线问题时,递归就不执行了。 - (2)递归条件
将问题继续分解的条件
从递归函数的思想和基本条件来看,可以将将其运用于RAS算法或者求解最小熵或最大熵的中。
具体怎么运用,需要继续学习。。。。。。。。
5.1 递归函数的案例
- 案例1-1
求解10的阶乘,10!
该过程可以分解为:
即10的阶乘可以分解为10乘以9的阶乘,依次类推,直到满足1的阶乘是他本身位置。
分析:基线条件时1!=1,返回
递归条件就是问题被分解的条件
def fn(n):
if n ==1:#基线条件
return n
return n*fn(n-1)#递归条件
print(fn(10))
3628800
- 案例1-2
定义一个函数做任意数字的幂运算ni,
假设105的运算。
分解条件:
def fn(i,n):
if n==1:
return n#这里是返回n,不是打印n 自己总忘记
return i*fn(i,n-1)
print(fn(10,5))
10000
注意满足基线条件时,返回的是对应的值,不是1,如果返回的是1.不便于利用该方法进行灵活运算。