资讯详情

Python函数复习

python函数

一、python 函数

1.函数

1.1函数定义

python 函数由几个句块、函数名称和参数列表组成。它是组织代码最小的单元.

具有一定的完成功能.**

2.2函数的作用

结构化编程包装最基本的代码,并根据功能组织代码

封装是为了重用,冗余代码较少

代码更简单,更容易理解

3.3函数分类

内建函数 如max() min() reversed()

函数库如math.ceil()

自定义函数 使用def() 定义

2.函数定义

def 函数名 (参数列表)

函数体(代码块)函数体

[return 返回值]

函数名称为函数标识符,命名要求相同

句块必须缩进,python要求严格缩进句子

如果没有函数return然后默认返回none空

定义中的参数列表是一种形式参数,即形式参数

3.函数调用

函数定义是指声明函数尚未调用,不能执行,只能调用

调用方式 即在函数后面添加() ,有必要在()中添加参数

调用时写入的参数为实际参数,即实际参数

def add(x,y): #函数定义     result = x   y  #代码块     return result #返回值 out = add(5,6) #调用函数 print (out) #打印输出值  #调用函数时占用内存  

解析:

定义函数名称add其形状参考函数x,y

计算函数 x y 并赋值结果result,提供返回值

调用时需要提供两个实参赋值y, 本案实际参与 5和 6

函数名也是标识符

返回值也是值,默认不提供return那么会返回none

定义时必须有函数,否则会爆炸NameError

函数是可调对象,因此可以被调用callable(add) 回车 true

4.函数参数

函数定义是定义形参,调用时调用实参。一般来说,形参与实参对应(可变形参除外)

4.1 实参传参

1.位置传参

定义时(x,y,z),调用时(1,2,3)

2.关键字传参

定义时(x,y,z)调用时(x=1,z=2,y=3) 如果将形参名称传入实参,位置无所谓

def add(x,y):     print (x)     print (y)     print ('_' * 30)   add(4,5) add(5,4) add(x=4,y=5) add(x=[4],y=(5,)) add(x=4.1,y=5.1) dd(x=5,4)
add(y=4,5)

#测试以上实验都是什么结果 为什么?

切记: 传参是指调用时穿的实参,就两种方式,一个是位置一个是关键字不可混用

4.2形参缺省值

给予形参一个缺省值,

def  add(x=1,y=2):
    print (x)
    print (y)
    print ('_' * 10 )
add(3)
add(2,3)
add(x=3,y=4)
#各输出什么?
# 定义一个函数login,参数名称为host、port、username、password


def mysqllogin(host='mysql_login.com',port='3306',username='admin',password='123456'):
    print ('mysql://{2}:{1}@{0}:{3}'.format(host,port,username,password))
    
mysqllogin()   
mysqllogin('127.0.0.1')     
mysqllogin('127.0.0.1','3307','mysql_user','mysql_password') 
#会输出什么?

当给予形参默认值时,当调用函数传入实参时只给部分实参,那么就会使用形参缺省值

4.3可变参数

*args 打包输出元组, *kwargs是打包输出字典

需求: 需要写一个函数对多个数字进行求和

def sum(k):
    s = 0 
    for  i in k : 
        s += i
    return s 
print (sum([1,2,3,4,5,6]) ) #直接替代为range(10) 可以吗?
#此方法不支持元组,因为+=不支持int和list
def sum(*nums) : 
    s = 0 
    for i in nums: 
        s +=i 
    return s 
pirnt (sum(1,2,3,4,5,6))

传入可迭代参数,并且累加每一个参数

*代表可变位置参数,接受多个实参,他将收集的实参组织到一个元组中tuple\

4.3.1可变位置参数

即为*,比如以上案例使用 *nums,代表可变位置参数,接受多个实参放入tuple

4.3.2可变关键字参数

**代表可变关键字参数,接受多个关键字传参

将收集的值组织到一个字典中

def showconfig(**kwargs):
    for k,v in **kwargs : 
        print ('{}={}'.format(k,v),end=',')
showconfig(host='127.0.0.1',port='3306',username='admin',password='123456')
def showconfig(username,password,**kwargs,*args):
    for k,v in kwargs.items():
        print('{}={}'.format(k,v), end=', ')
showconfig(host='127.0.0.1', port=8080, username='wayne', password='magedu')



def showconfig(username,password,*args,**kwargs):
    for k,v in kwargs.items():
        print('{}={}'.format(k,v), end=', ')
showconfig(host='127.0.0.1', port=8080, username='wayne', password='magedu')

def showconfig(username,password,**kwargs):
    for k,v in kwargs.items():
        print('{}={}'.format(k,v), end=', ')
    print (**kwargs,username,password)
showconfig(host='127.0.0.1', port=8080, username='wayne', password='magedu')

#想想输出结果,为什么?

总结:

可变位置参数*表示, 可变关键字传参 **表示

可变位置传参将参数收集成tuple元组 可变关键字传参收集成dict 字典

在混合使用时普通形参要放到前边,可变位置参数要放到可变关键字传参前边

练习:

def comprehensive(*args,**kwargs):
    for i in args:
        print (i)
    for k,v in kwargs.items():
        print (k,v )

l1=[*range(10)]
comprehensive(l1,host='127.0.0.1',username='123')
#输出结果?

def fn(x,y,*args,**kwargs):
    print (x,y,args,kwargs,end = '\n')
fn(1,2,3,4,5,6,7,x=1,y=2,a='123',b='abc')
fn(x=1,y=2,1,2,3,4,a='abc',b='123')
#位置参数跟随关键参数!这是不被允许的!
SyntaxError: positional argument follows keyword argument

4.4 keyword-only参数

def fn(*args, x, y, **kwargs):
    print(args, x, y, kwargs, end='\n')

fn(1,2,3)
fn(1,2,3,a='123',b=2)
fn(1, 2, 3, 4, x=1, y=2, a='123', b=3)  

#TypeError: fn() missing 2 required keyword-only arguments: 'x' and 'y'

当python3 更新之后定义一个keyword-only函数,在一个*可变位置参数之后的形参都会被定义为keyword-only,必须传入.

变相思考,是不是*args可变位置参数已经获取了全部参数位置带入到tuple中,不可使用位置参数只能使用关键字传参.

那么**kwargs可以吗,可变关键字传参?

def fn(**kwagrs,x,y):
    print (kwargs,x,y)
fn(host='127.0.0.1',username='123',y='100')

#SyntaxError: invalid syntax

可变关键字传参概念:将输入的参数存储到dict,那么x,y是不是关键字?就算写入x=也无法得到值

语法不存在

如果想要所有形参都变成keyword-only

def fn(*,x,y) :
    print (x,y)
fn(x=10)
#TypeError: fn() missing 1 required keyword-only argument: 'y'

总结在*可变位置传参后所以形参都会变成必须需要传入的关键字参数.

4.5 Positional-only参数

def fn( a , / )  :
    print (1)
fn(a=10)
fn(10)
#TypeError: fn() got some positional-only arguments passed as keyword arguments: 'a'

翻译过来的意思仅能使用位置传参,所以说比较鸡肋不太使用.

4.6 参数混合使用

将 *可变位置参数 **可变关键字参数 x='abc’缺省值 *,a=1 keyword-one ,/Positional-only进行配合使用

def fn( *args,a=10, ): #可变位置传参,关键字传参
    print( args, a)

def fn2(x,*args,y=100) : #位置传参,可变位置传参,关键字传参
    print (x,args,y)

def fn3(x,y,*args,k=100,**kwargs) : #位置传参,可变位置传参,关键字传参,可变关键字传参
    print (x,y,args,k,kwargs)
    
def fn4(*args,x,y,k='abc',**kwargs): #可变位置传参,keyword-noly,关键字传参,可变关键字传传参
    print (args,x,y,k,kwargs)
    
def fn5 (x=100,y=200,k,*args,**kwargs, / ):
    print(x,y,k,args,kwargs)
    
    
fn(1)
fn(1,20,a=30)
fn2(1,1,2,3,3,4,5,6,y=30)
fn3(1,2,2,3,4,5,6,l=100,n=200,k=500)
fn4(1,2,4,4,5,6,x=100,y=200,k=600,mm='sun',gg='wangwang') #爆x,y,keyword-only关键字传参
fn5(x=200,y=300,100,1,2,3,4,56,kw=10000,wk=20000) #fn / Positional-only只支持前边是关键值传参


4.7 参数使用规则

一般来说写函数使用参数一定要简单易懂

一般的使用规则为: Positional-only,普通参数,缺省参数,可变位置参数,keyword-only(带缺省值),可变关键字参数.

def fn(a,b,/,c,d,e=200,*args,k=100,w=299,**kwargs):
    print (a,b,c,d,e,args,k,w,kwargs)
    
fn(100,200.300,400.500,1,2,3,4,5,k=200,w=300,admin='liu')


#应用
def com(host='127.0.0.1',username='admin',password='123456',port='3306',**kwargs):
    print ('mysql://{}:{}@{}:{}\{}'.format(username,password,host,port,kwargs.get('db','test')))

com(db='wordpress')
com(host="192.168.1.100",username='Administrator',password='Liujinxin@123',port='33060',db='work-01')

总结: 定义最常使用参数为普通参数,不是提供缺省值,需要客户提供,注意参数顺序.

将必须使用的参数定义为keyword-only参数,必须携带的,要求关键字必须传入

如果函数有很多的参数无法逐一定义,可以使用可变关键字传参.

5. 参数解构

def add(x,y):
    print (x,y)
    return x + y
sum=4,5
add(4,5)
# add((4,5)) 有问题 需要两个参数,但是这里只有一个
add(sum[0],sum[1])
add(*sum)
add(*(4,5))
add(*{ 
        4,5})
add(*[4,5])
add(*range(4,6))
add( *{ 
        'a' : '10' , 'b' : '20'} )
#add( **{'a' : '10' , 'b' : '20'} ) 有问题 会得到意外参数a,机构后 a=10,b=20 
add( **{ 
        'x' : '10' , 'y' : '20'} )

总结

解构时*会理解为位置传参,而**会理解为关键字传参随后匹配函数的实参

提取出来的元素回合函数的形参对比

二、函数返回值

returnn

实验返回值返回个数,返回后函数还会继续执行吗,多个返回值是否可以

def add(x,y):
    k = x + y 
    return  k 
	print ("123")
def fn1(x):
    print (x)
    return x + 1
	return x + 1
def fn2(y):
    if y = 2 :
       return y + 1
	elif y  < 3 :
        return y + 2
add(4,5)
fn1(10)
fn2(2)
#实验一下

总结:

函数都有返回值,函数使用return作为返回值

函数返回值不写,隐式调用return none

return 不一定是函数的最后一句

一个函数可以有多个return 但是只会执行一个,如果没有执行那么是隐式none

当执行return后,后续函数不再执行,

return用来结束函数调用,返回返回值

如果有必要可调用隐式return

三、函数作用域

1. 作用域

标识符可见范围作用域函数中

def foo():
    x = 100 
print (x)
#会不会访问到? NameError: name 'x' is not defined

不会被访问到,甚至会报错NameError

因为x只定义在foo函数中,而没用定义在全局

2.作用域分类

1.全局作用域

1.整个程序运行环境可见

2.全局作用域变量称之为全局变量global

2.局部作用域

1.在函数,类经常可见,

2.局部作用域中的变量,其使用范围不会超过本函数或类

3.也称之为本地作用域local

#局部变量
def fn0():
    x=10 
    return x 

def fn1():
    print (x)

print (x)
    
#name 'x' is not defined 
#全局变量
x = 10

def fn0():
    return x + 1 
fn0() 
#返回值???

3. 函数嵌套

def fn0(): 
	def too():
        print ('sum')
	too()
	print ('fn0')

fn0()
too()
#NameError: name 'too' is not defined

内部的函数不知能直接在外部使用,否则会抛出NameError异常,以为他在函数体外并不可见.

其实too就是一个标识符,函数名字而已,一个fn0函数内定义的一个变量而已.

1.嵌套解构的作用域

def other1():
    f  = 100 
    def too():
        print ('too',f,chr(f))
    too()
    print ('other',f,chr(f) )
	
other1()


#other1 返回 too 100
#too 100 d
#other 100 d

def other2():
    f = 200 
    def too():
        f = 201
        print ('too',f,chr(f))
    too()
    print ('other2',f,chr(f))
  
other2()
#other2 返回函数内部调用f = 201
#too 201 É
#other2 200 È

总结: 经此发现内部函数f = 201的作用域只在too函数中,外部是不可调用的.

如果嵌套函数外层定义一个f = 201,内层还有一个相同的变量名称,那么函数有优先调用本函数内的变量.

内建函数 函数签名 说明
chr chr(i) 通过Unicode编码返回对应字符
ord ord(i) 通过字符获得对应的unicode
print (ord('中'),hex(ord('中')),'中'.encode(),'中'.encode('gbk'))
#20013 0x4e2d b'\xe4\xb8\xad' b'\xd6\xd0'

chr(20013) #'中'
chr(97) #'a'

4.赋值语句的问题

x = 10 
def fn():
    print (x)
    
fn()

#执行正常

 

标签: fv1连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台