基础入门7---函数

一.函数
计算机中函数与数学中的函数定义上是有区别的
数学: function(功能)
编程语言中的函数: subroutine (子程序) & procedures(过程)

计算机中函数的作用:
1.减少重复代码
2.方便修改,更易扩展(减少,增加都行)
3.保持代码的一致性

函数的格式:
def 函数名(参数列表):
函数体<br><br>

1.固定形态
def f(): # 定义一个函数 define(def) , f 就是函数名只是一个变量见以下的内存地址指向值 ,(): 这2种情况,一种括号空的,一种可以调入动态参数
print('ok') # 函数体
f() # >>> ok 这个就代表打印出'ok'值的函数,调f时候一定要加()

def f():
print('ok') >>> <function f at 0x000000000259B040> #这个就是OK的内存地址
print(f)

2. 动态效果
def add(x,y): # x,y是形式参数,也叫形参
print(x*y) >>> x*y=24
print(x) >>> 4
print(y) >>> 6
add(4,6) # 分别将4,6的值赋给x,y,这个是实际参数,也叫实参,实参与形参的调入数据是一一按顺序对应

def f(n): #定义一个f的函数
print('我们是%s'%n) # 格式化输出%n >>> 打印出一个结果 '我们是中国人'
f('中国人') #调入一个参数


def f(num):
print('stamp %s'%num)
f(1) >>> stamp 1
f(2) >>> stamp 2
f(3) >>> stamp 3

def level2(a,b): #第二层调入10,40两个参数
print(a+b) # 第二层打印出10+40的结果
def action1_level1(a,b):
print('wangwei ok') >>>wangwei ok #第一层打印出这句话
level2(a,b) >>>50 #将第二层打印出来的结果函数体引入到这里
action1_level1(10,40) # 第一层调入10,40两个参数


def f_exit(n):
print('大家好,这句不变一直存在')

def f1(n):
print('第%s步做功能计算'%n)
f_exit(n)
def f2(n):
print('第%s步做功能策划'%n)
f_exit(n)
def f3(n):
print('第%s步封装数据'%n)
f_exit(n)
f1(11)
f2(22)
f3(33)
第11步做功能计算
大家好,这句不变一直存在
第22步做功能策划
大家好,这句不变一直存在
第33步封装数据
大家好,这句不变一直存在


3.函数的参数
a.必须参数
必须参数是以正确的顺序传入函数中,调用的数量必须与声明中数量一致
def info(name,age):
print('I am %s,my age is %s'%(name,age)) >>> I am wangwei,my age is 40 / I am 王极野,my age is 12
info('wangwei',40)
info('王极野',12)

b. 关键字参数
def f(name,age):
print('I am %s,my age is %s'%(name,age)) >>> I am wangwei,my age is 20
f(age=20,name='wangwei') #这个把关键字定义好,就不用担心一定按顺序传入,顺序乱了也可以正确调入

c. 默认参数
def f(name,age,ginder='male'): #在参数设定的时候先设定男性为默认参数,在参数调入时如果不是不一样的性别输入,同性为男不用再输入,计算机会默认为男性(也可以自设为女性为默入参数,自已依情况而定)
print('name:%s,age:%s,ginder:%s'%(name,age,ginder))
f('wangwei',40) >>> name:wangwei,age:40,ginder:male
f('huangjuan',35,'female') >>> name:huangjuan,age:35,ginder:female

def f(ginder='male',name,age):
print('name:%s,age:%s,ginder:%s'%(name,age,ginder))
f(name='wangwei',age=40)
f(name='huangjuan',age=35,ginder='female') >>>SyntaxError: non-default argument follows default argument
默认参数必须要跟在非默认参数后,不然会像上面例子一样一执行就会报错

* 关键字参数是在实际参数中加入,默认参数是在形参中加入,这个就是区别点

* D. 不定长参数(以上三种A/B/C固定太low了,不会根据实际变化,不定长参数就解决了这个问题)
def f(*args): # *号就是不定长标志,args就是参数
print(args) >>>(3, 5, 7)
f(3,5,7)

def f(*args):
print(args)
num=0
for i in args: # args=(1,2,3,4,5)
num+=i
print(num)
f(1,2,3,4,5)

def f(*args,**kwargs):
print(args) >>>(1, 8, 0, 1, 6) # 调入参数时将列表,元组前面加*,打印出合成一个元组结果
print(kwargs) >>>{'name': 'wangwei', 'age': 40, 'hobby': 'reading'} # 调入参数时将字典加**,打印出合成一个字典结果
f(*[1,8,0],*(1,6),**{'name':'wangwei','age':40},**{'hobby':'reading'})


有命名参数及无命名参数实例:
有命名参数,如字典的键值对参数输入,调用的函数格式 **kwargs()

def f(*args,**kwargs): # 无命名参数如数字,不是键值对形式,用*args命令。有命名参数如键值对形式格式是**kwargs
for i in kwargs: #遍历kwargs这个字典
print(i,'>>>',kwargs[i]) #打印出键值对的对应值(有命名参数) name >>> wangwei age >>> 40
print(args,kwargs) #打印出无命名参数与有命名参数 (12, 34, 66) {'name': 'wangwei', 'age': 40}
f(12,34,66,name='wangwei',age=40) #输入参数,无命名与有命名的


涉及到无命名与有命名参数位置问题:
def f(*args,**kwargs): # 这个位置必须是无命名在前,有命名在后,这个是PYTHON固定好的,不能修改
print('%s'%args) >>>positional argument follows keyword argument
print('%s'%kwargs) >>>positional argument follows keyword argument
f(name='wangwei',23) #调入参数也是一样的无命名在前,有命名在后,这个是PYTHON固定好的,不能修改.否则就会报错

def f(*args,**kwargs):
print('%s'%args)
print('%s'%kwargs)
f(name='wangwei',33) # 输入有命名在前,无命在后,就会出现报错现象 >>>positional argument follows keyword argument
f(33,name='wangwei') # 这个格式就是对的 >>> 33 {'name': 'wangwei'}

关于不定长参数位置的结论: *args放在左边或者前边,**kwargs放在右边或者后边
不定长参数位置的优先极: 关键字参数>>> 默认参数>>>*args无命名参数>>>**kwargs有命名参数

E.函数返回值 >>> return (2个作用,一个是结束函数,第二个是返回一个值)
def f(*args): #第二步将实参调入到形参中
sum = 0
for i in args: #第三步遍历
sum+=i # 第四步遍历数据相加
return sum # 第五步遍历数据相加返回一个结果

a=f(1,2,3,4,5) #第一步调入参数(1-5整型数字)
print(a) #第六步将return返回的值打印出来 >>> 15

def f(*args):
sum=1
for i in args:
sum*=i
return sum
print(f(1,5,9)) >>> 45

return的注意点: 1)函数里如果没有return,程序会默认返回一个NONE
2)如果return返回多个对象,PYTHON会帮我们把多个对象封装成一个元组返回给我们(其实返回的还是一个对象)
def f(*args,**kwargs):
return kwargs
a=f(2,[3,9],name='wangwei')
f(2,[3,9],name='wangwei')
print(a) >>> {'name': 'wangwei'}

F.* 函数的作用域(非常重要) #所谓作用域是自已可以定义一块区域,在区域内可以运行,区域外不相关
x=int(3.8) # 3.8浮点数变成整型变量,就只打印整数部份
print(x) >>> 3

作用域按从外到内包含关系划份如下:
1. built_in > 2. global > 3. enclosing > 4.local (记法: LEGB ,从小范围到大范围)

1.built_in 系统固定模块内的变量
2.global 全局变量,也叫模块级别定义的变量
3.enclosing 嵌套的父级函数的局部作用域
4.local 局部作用域

局部作用域不能对全局作用域进行修改(1.从里面到外面寻找相对应值 2.里面的执行不能修改外面的值)
num=10
def f():
num=3 #重新赋值
print(num) #打印出新值 >>> 3
f()

num=10
def f():
num+=3 #先拿外面的num=10的值,再在上面基础上加3,这样就返背了里面不能修改外面的值的原则,就出现报错现象。
print(num) >>> UnboundLocalError: local variable 'num' referenced before assignment 在赋值前局部作用域没有绑定
f()

num=10
def f():
global num # 增加一个声明的global全局变量,就可以对数据进行修改
print(num) >>> 10
num=3
print(num) >>> 3
f()


* 在局部嵌套作用域用global声明修改
* 在局部作用域用nonlocal声明修改
* 内部作用域先声明就会覆盖外部变量,不声明就会直接使用外部变量
count=10
def f():
global count >>> 引用全局变量的参数到里面
print(count) >>>10
count=100
print(count) >>> 100
f()

num=3
def f1():
global num >>>声明全局变量后,将全局num=3引入内部
print(num) >>>3
num1=8
def f2():
nonlocal num1 >>> 声明嵌套变量后,将外部num=8引入内部
print(num1) >>> 8
num1=10
print(num1) >>>10
f2()
f1()


G.高阶函数 (函数名可以赋值/函数名可以作为一个参数,还可以作为函数返回值 )
def f(n):
return n*n
print(f(2)) # 调入一个参数2,并执行2*2=4,4的值返回打印出来

def f1(a,b,f2):
return f2(a)+f2(b)
print(f1(1,2,f)) # 调入1,2,f三个参数,再分别执行上面一个n*n值 ,这个得出的就是1*1+2*2=5的值


def f1(n):
return n**2
f1(2) #调入一个参数2,返回一个2的2次方=4

def f2(a,b,f):
return f(a)+f(b)
print(f2(2,4,f1)) #调入一个函数f1的2次方形式,分别输入(2,4)=2**2+4**2=20

def f1(n):
return '我爱中国' >>># f1调入一个参数会返回打印一个“我爱中国”
def f2(a,b,f):
return f(a)+f(b) >>> #,2,4参数调入f1中各出现一个“我爱中国”
print(f2(2,4,f1)) >>>我爱中国我爱中国

def f(n):
return 'wangwei'
def f1(a,b,func):
return func(a)+func(b)
ret=f1(3,7,f) #将3,7,f三个值全部调入,其中f调入函数体并赋了3,7值,得到的结果就是2个'wangwei'
print(ret)

* 高阶函数的重点
def f1():
def f2():
return 9
return f2
print(f1()()) >>> 9 等于两步: 第一步是print(f1())把外层函数启动调用得到一个返回值就是f2(一个叫f2函数名)
第二步再加一个括号(f1()())等同于f2()把内层f2函数启动得到9,再把9值返回回去结果就是9

H.函数传输形式问题
def f(*args):
print(args)
f((1,2,3),(3,8)) >>> ((1, 2, 3), (3, 8)) 不加就是两个元组

def f(*args):
print(args)
f(*(1,2,3),*(3,8)) >>> (1, 2, 3, 3, 8) 传入数据无命名加*,有命名加**,得出来的数据就合成了一个元组

def f1(**kwargs):
print(kwargs) >>> {'name': 'wangwei', 'age': 40}
f1(name='wangwei',age=40)

def f2(**kwargs):
print(kwargs) >>> {'name': 'wangwei', 'age': 38}
f2(**{'name':'wangwei','age':38}) 加入**,就可直接传输字典格式的数据


i.递归函数
def f1(n):
ret=1
for i in range(1,n+1):
ret=ret*i
return ret
print(f1(7)) >>> 5040 # 采用for循环来解决递归问题(阶乘问题)


def f(n):
su=1
while n>=1:
su=su*n
n-=1
return su
print(f(7)) >>>5040 # 采用while 循环来解决递归问题


def f(n):
if n==1: # 这个就是结束条件
return 1 >>> 这个就是n=1的时候返回1的值就停了
return n*f(n-1) >>> 7*f(6)=7*6*f(5)一直递减到1
print(f(7)) >>>5040

def f(n):
if n<=1 :
return 1
return n+f(n-1)
print(f(100)) >>>5050

递归函数的特点:
1)调用自身函数
2)有一个结束条件
3)但凡递归可以解决的用循环都可以解决
4)递归的效率很多时候会很低,不推荐使用

j.斐波那契数列(0,1,1,2,3,5,8,13,21,34,55...)

def f(n): # 定一个函数
if n<=3: #定一个终止条件n<=3,会出现f(2)+f(1)=1+1
return 1
return f(n-1)+f(n-2)
print(f(8)) >>>13 第8个数就是13



k.内置函数
print(abs(-22)) #>>>返回一个绝对值 22
print(all([1,2,'wangwei'])) # >>>True
print(all(['',22])) #>>> False
print(eval('2+3*5')) # eval除了在字典中转化成字符串,还可以做计算器用,但是一定要加引号做为字符串
print(eval('1+2*3')) >>>7


{ abs(),all(),any(),ascii(),bin(),bool(),bytearray(),bytes(),callable(),chr(),classmethod(),
compile(),complex(),delattr(),dict(),dir(),divmod(),enumerate(),eval(),exec(),filter(),
float(),format(),frozenset(),getattr(),globals(),hasattr(),hash()...}

* 4个重要的内置函数(filter,map,
1) filter(它的作用相当把列表传入函数中,进行判断并返回值)
list1=['a','b','c','d']
def f(s):
if s!='a': #如果列表中的元素不等于‘a’,就将值返回去,那么上面列表中的元素4个就有3个返回回去
return s
filter(f,list1) # filter内置函数就是将函数名为f,及列表1的元素全部依次传进去
print(filter(f,list1)) >>><filter object at 0x000000000256AAC0> 返回了一个迭代器对象地址
print(list(filter(f,list1))) >>> ['b', 'c', 'd'] 再转成一个没有'a'的列表

list1=[2,7,8,10,7]
def f(n):
if n!=8:
return n
print(filter(f,list1)) >>><filter object at 0x000000000254AB50>
print(list(filter(f,list1))) >>>[2, 7, 10, 7]

2)map内置函数与filter基本一致,都是将列表传入函数中。差别在于map不是过滤作用,而是将新的字符串与旧的相拼接
list1=['w','a','n',]
def f(n):
return n+'gg'
print(map(f,list1)) >>><map object at 0x00000000020EAAC0> map也是一个迭代器
print(list(map(f,list1))) >>> ['wgg', 'agg', 'ngg'] 分别将新增字符串与原列表中的字符串相拼接

3) reduce(归纳)内置函数 (*前面必须要有‘from functools import reduce’ 这句话,就是从功能模块中调用reduce命令
from functools import reduce
list1=range(1,10) # 等于一个列表[1,2,3,4,5,6,7,8,9]
def f(x,y):
return x+y # 返回一个x+y值 ,1+2=3 ,再拿3+3=6,再拿6+4=10,一直依次两个等同于x+y模式
reduce(f,list1) #导入函数名及列表(1-9)
print(reduce(f,list1)) >>> 45

from functools import reduce
list1=range(1,101)
def f(x,y):
return x+y
reduce(f,list1)
print(reduce(f,list1)) >>> 5050

4)lambda (匿名函数)
格式: lambda a,b:a+b # 等同于一个匿名函数有a,b两个值,函数体是a+b,类似于f(x,y)=x+y格式

from functools import reduce # 先导入reduce模块
print(reduce(lambda x,y:x+y,range(1,101))) >>> 5050 # 直接打印结果(reduce返回值(lambda匿名函数,要做X+Y运算),数列是从(1-100)


l. 时间模块的调用
import time
time_format='%Y-%m-%d %X'
current_time=time.strftime(time_format)
print(current_time) >>> 2020-04-15 17:18:51

猜你喜欢

转载自www.cnblogs.com/525667692-2020-AP-T/p/12725511.html