标签:表达式 字段 栈帧 rgs 没有 city 一个 syntax value
三、函数
1.调用函数
abs(100)
abs(-20)
max(1,2)
max(2,3,1,-5)
数据类型转换
int(‘123‘)
int(12.34)
float(‘12.34‘)
str(1.23)
str(100)
bool(1)
2.定义函数
return是返回值,一般放在函数的最后,一旦执行到return时,函数就执行完毕并将结果返回,且return语句块结束之后后面的代码是不执行的,即一旦遇到return结束整个函数。
def my_abs(x):
if x>=0:
return x
else:
return -x
my_abs(-1) #1
如果没有return语句,函数执行完毕后也会返回结果,只是结果为none
返回多个值
def ret_demo1(): return 1,2,3,4 def ret_demo2(): return 1,[‘a‘,‘b‘],3,4 ret1 = ret_demo1() ret2 = ret_demo2() print(ret1) print(ret2)
(1, 2, 3, 4) (1, [‘a‘, ‘b‘], 3, 4)
def ret_demo2(): return 1,[‘a‘,‘b‘],3,4 a, b, c, d = ret_demo2() print(a, b, c, d) #返回多个值,可以用一个或多个值来接收 print(a)
1 [‘a‘, ‘b‘] 3 4 1
添加了参数检查的函数,数据类型检查可以用内置函数isinstance()实现
def my_abs(x):
if not isinstance(x,(int,float)):
raise TypeError(‘bad operand type‘)
if x>=0:
return x
else:
return -x
求根
import math
math.sqrt(10)
3.函数的参数
位置参数
def power(x):
return x*x
def power(x,n):#x的n次方
s = 1
while n>0:
n = n-1
s = s*x
return s
默认参数
def power(x,n=2): #其中n=2是默认参数,x的平方
s = 1
while n>0:
n = n-1
s = s*x
return s
默认参数可以简化函数的调用:
1、必选参数在前,默认参数在后,否则python的解释器会报错
2、当函数有多个参数,把变化大的参数放前面,变化小的参数放后面,变化小的参数就可以作为默认参数
def enroll(name, gender, age=6, city=‘Beijing‘):
print(‘name:‘,name)
print(‘gender:‘,gender)
print(‘age:‘,age)
print(‘city:‘,city)
enroll(‘Bob‘,‘M‘,7)
enroll(‘Bob‘,‘M‘,city=‘tianjing‘)
name: Bob gender: M age: 7 city: Beijing name: Bob gender: M age: 6 city: tianjing
def add_end(L=[]):
L.append(‘END‘)
return L
add_end()
add_end(L=[])
add_end(L=[1,2,3])
add_end([1,2,3,4])
[‘END‘] [‘END‘] [1, 2, 3, ‘END‘]
[1, 2, 3, 4, ‘END‘]
多次循环add_end()END会逐次增加,原因在于:Python函数在定义的时候,默认参数L
的值就被计算出来了,即[]
,因为默认参数L
也是一个变量,它指向对象[]
,每次调用该函数,如果改变了L
的内容,则下次调用时,默认参数的内容就变了,不再是函数定义时的[]
了。更改如下,要用None这个不可变对象来实现。
def add_end(L=None): #这里的None也可以是任何其他的东西
if L is None:
L = []
L.append(‘END‘)
return L
add_end(L=[])
def add_end(L=a): #比如,这里的None也可以是a
if L is a:
L = []
L.append(‘END‘)
return L
add_end()
add_end([])
add_end([1,2,3])
可变参数
可变参数就是传入的参数的个数是可变的,可以是1,2,3,4...还可以是0个
def calc(numbers): #同理,numbers可以用其他的东西代替
sum = 0
for n in numbers:
sum = sum + n * n #n方相加
return sum
calc([1,2,3])#参数里面没有加*,那么只能是list或参数calc([1,2,3]),calc((1,2,3)) #14
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n*n
return sum
calc(1,2,3)#加了参数,就可以直接是calc(1,2,3) #14
def calc(*numbers):
sum = 0
for n in numbers:
sum = sum + n*n
return sum
num = [1,2,3]
calc(*num) #可以通过这样的方式直接将list的所有元素作为可变参数传进去 #14
可变参数都是加* 的,不加的话就要作为list或者tuple
关键字参数
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple,而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict
def person(name,age,**kw):
print(‘name:‘,name,‘age:‘,age,‘other:‘,kw)
person(‘Michael‘,30)#name,age为必选参数,kw为关键字参数,在调用该函数时,可以值传入必选参数 #结果:name: Michael age: 30 other: {}
也可以传入任意个数的关键字参数
def person(name,age,**kw):
print(‘name:‘,name,‘age:‘,age,‘other:‘,kw)
person(‘Bob‘,35,city=‘Beijing‘)#必须是A = ‘B‘的形式,可以是多个
person(‘Adam‘,45,gender=‘M‘,city=‘Tianjin‘)
name: Bob age: 35 other: {‘city‘: ‘Beijing‘} name: Adam age: 45 other: {‘gender‘: ‘M‘, ‘city‘: ‘Tianjin‘}
用处:比如做一个用户注册的功能,除了用户和年龄是必填,其他选填,利用关键字参数来定义就可以满足
def person(name,age,**kw):
print(‘name:‘,name,‘age:‘,age,‘other:‘,kw)
#可以先组装出一个dict,然后把其转换成关键字参数传进去
extra = {‘city‘:‘Beijing‘,‘job‘:‘Engineer‘}
person(‘Jack‘,24,city=extra[‘city‘],job=extra[‘job‘]) #**必须是‘‘=‘‘的格式,之后变成了字典的形式
name: Jack age: 24 other: {‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘}
简化方法
person(‘Jack‘,24,**extra)
name: Jack age: 24 other: {‘city‘: ‘Beijing‘, ‘job‘: ‘Engineer‘}
命名关键字参数
限制关键字参数的名字,就可以用命名关键字参数,例如,只接收city和job作为关键字段
def person(name,age,*,city,job):
print(name,age,city,job)
person(‘Jack‘,24,city=‘Beijing‘,job=‘Engineer‘) #Jack 24 Beijing Engineer #和上面的不一样,上面的是{}形式,这里只是字典的value值
person(‘Jack‘,24,city=‘Beijing‘,job=‘Engineer‘,sex=‘F‘) #SyntaxError: invalid character in identifier
如果函数定义中已经有了一个可变参数,后面跟着的就变成了命名关键字参数,此时就不再需要一个特殊分隔符*
def person(name,age,*args,city,job):
print(name,age,args,city,job)
person(12,23,24,‘ddd‘,‘fff‘,city=‘Beijing‘,job=‘E‘)
12 23 (24, ‘ddd‘, ‘fff‘) Beijing E
由于命名关键字参数city具有默认值,调用时,可不传入city参数
def person(name,age,*,city=‘Beijing‘,job):
print(name,age,city,job)
person(‘Jack‘,24,job=‘Engineer‘)
Jack 24 Beijing Engineer
def f1(a,b,c=0,*args,**kw):
print(‘a=‘,a,‘b=‘,b,‘c=‘,c,‘args=‘,args,‘kw=‘,kw)
def f2(a,b,c=0,*,d,**kw):
print(‘a=‘,a,‘b=‘,b,‘c=‘,c,‘d=‘,d,‘kw=‘,kw)
f1(1,2)
f1(1,2,c=3)
f1(1,2,3,‘a‘,‘b‘)
f1(1,2,3,‘a‘,‘b‘,x=99)
f1(1,2,d=99,ext=‘None‘)
a= 1 b= 2 c= 0 args= () kw= {} a= 1 b= 2 c= 3 args= () kw= {} a= 1 b= 2 c= 3 args= (‘a‘, ‘b‘) kw= {} a= 1 b= 2 c= 3 args= (‘a‘, ‘b‘) kw= {‘x‘: 99} a= 1 b= 2 c= 0 args= () kw= {‘d‘: 99, ‘ext‘: ‘None‘}
args = (1,2,3,4)
kw = {‘d‘:99,‘x‘:‘#‘}
def f1(a,b,c=0,*args,**kw):
print(‘a=‘,a,‘b=‘,b,‘c=‘,c,‘args=‘,args,‘kw=‘,kw)
f1(*args,**kw)
args = (1,2,3)
kw = {‘d‘:88,‘x‘:‘#‘}
def f2(a,b,c=0,*,d,**kw):
print(‘a=‘,a,‘b=‘,b,‘c=‘,c,‘d=‘,d,‘kw=‘,kw)
f2(*args,**kw)
a= 1 b= 2 c= 3 args= (4,) kw= {‘d‘: 99, ‘x‘: ‘#‘} a= 1 b= 2 c= 3 d= 88 kw= {‘x‘: ‘#‘}
4.递归函数
使用递归函数需要注意防止栈溢出,在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层帧,每当函数返回,栈就会减一层栈帧,由于栈的大小不是无限的,所以,递归函数用的次数过多,会导致栈溢出。
def fact(n):
if n==1:
return 1 #如果return 1,整个函数就结束了
return n*fact(n-1) #因为引入了乘法表达式,所以不是尾递归
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看作是一种特殊的尾递归也是可以的
尾递归是指,在函数返回的时候,调用自身本身,并且return语句不能包含表达式,这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次都只占用一个栈帧,不会出现溢出情况
def fact(n):
return fact_iter(n,1)
def fact_iter(num,product):
if num == 1:
return product
return fact_iter(num-1,num*product)#仅指递归函数本身,num-1和num*product在函数调用前就会被计算,不影响函数调用 #结果:阶乘
标签:表达式 字段 栈帧 rgs 没有 city 一个 syntax value
原文地址:https://www.cnblogs.com/blogbo/p/11747028.html