DAY9 函数初识(各种参数的用法)

函数初始

为什么需要函数?

  1.合并重复,减少代码的重复率。

  2.测试方便

  3.修改方便

  4.打包

  5.映射

函数的最主要目的:封装一个功能。

 

函数的定义:

 

def 函数名(argv):
    函数体

 

   def  : 定义函数的关键字。

   函数名:自定义函数名,一般都为小写字母,与变量名一样最好具有良好的描述性。

  argv  :  参数,可以有多个,用","逗号分隔

  statement : 函数体,具体的代码

  return :函数的返回值,默认不写的话返回的是None;可以没有返回值,可以返回一个值,可以返回多个值。

 

创建函数,调用函数:

 

def mylen():
    """
    创建了一个名为mylen的函数
    计算s1的长度
    """
    s1 = "hello world"
    length = 0
    for i in s1:
        length = length+1
    print(length)

mylen()    #执行函数,函数名()表示执行函数。

 

 

函数的返回值:return

  作用:

  1.函数一旦遇到return,就会结束。

   2.给函数的执行者返回值,方便后续使用

  类型:

  1.没有返回值,默认返回的是None。

  2.返回一个值。

  3.返回多个值,以元组的形式返回。

'''没有返回值,默认返回的是None'''
def mylen():
    s1 = 'hello,world'
    length = 0
    for i in s1:
        length = length +1
    print(length)

str_len = mylen()  #因为没有设置返回值,所以默认返回None
print(str_len)
>>>None


'''返回一个值'''
def mylen():
    s1 = 'hello,world'
    length = 0
    for i in s1:
        length = length + 1
    return  length

str_len = mylen()
print(str_len)

'''返回多个值:可以返回多个,任意数据类型的值'''
def demo1():
    return 1,2,3,4

def demo2():
    return 1,['a','b'],3,4

res1 = demo1()
res2 = demo2()
print(res1)
print(type(res1))   # 元组

print(res2)
print(type(res2))   #元组

  

函数的参数:形参与实参

  形参:函数完成其工作所需要的一项信息,只是一个形式,用于接受实参。

  实参:调用函数时,实际传递给函数的信息。

'''站在实参的角度来看'''

  1.位置参数

#位置参数:调用函数时,python必须将函数调用中的实参与每一个形参关联,为此最简单的关联就是按照位置关联。因此,位置参数中,形参与实参的个数必须一样,位置一一对应。

def describe_pet(animal_type,pet_name):
    print('I have a '+ animal_type + '.')
    print('My '+ animal_type +"'s name is " + pet_name.title())
describe_pet('dog','herry')
>>>
I have a dog.
My dog's name is Herry

#如果改变参数的位置
describe_pet('dog','herry')
>>>
I have a herry.                    #animal_type这个形参接受的就是‘herry’了.
My herry's name is Dog

  2.关键字参数

# 关键字参数:用在函数调用的时候,通过关键字传值,可以不需要一一对应位置顺序。

def  mymax(x,y):
    the_max = x if x>y else y
    return the_max
max_num = mymax(y=10,x=20)    #位置不用一一对应了。
print(max_num)

  3.混合型参数(位置参数+关键字参数)

# 位置参数与关键字参数混合调用,但是关键字参数必须在位置参数之后。

def mymax(x,y):
    the_max = x if x>y else y
    return the_max

max_num = mymax(10,y=20)      #关键字参数必须在位置参数之后
print(max_num)

 

 

'''站在形参的角度来看'''

  1.位置参数,与上面的是一样的。

  2.默认参数

'''
默认参数:把变化比较小的参数可以设置成一个默认值,在传参时可以忽略不传,如果不传就使用默认值;如果传,就会覆盖掉默认值。

默认参数使用场景:“参数的值不经常改变,但是一直在用”

谨记:默认参数的陷进!!!默认参数不要设置为可变数据类型。
'''

#默认参数
def stu_info(name,sex='male'):
    print(name,sex)

stu_info('alex')    #sex可以忽略不传
>>>
alex,male

stu_info('eva_j','female') #sex的默认值会被覆盖
>>>
alex,female


#默认参数的陷进:默认参数不要为可变数据类型。
def default_para(a,l=[]):
    l.append(a)
    print(l)
default_para('alex')
# >>>['alex']
default_para('egon')
# >>>['alex', 'egon']

!!!通过查看id,发现两次调用函数列表的内存地址都是一样的,说明列表都是同一个列表!!!
#像列表这种可变类型的改进方法:

def default_para(a,L=None):
    if L is None:
        L = []
    L.append(a)
    return L

print(default_para('alex'))
>>>['alex']
print(default_para('egon'))
>>>['egon']

 3.任意参数,动态参数:在函数定义的时候,在上*代表的是聚合。

  一. *args:接受位置传值,把所有位置参数都由*args接受,聚合保存为一个元组。

#一。观察*args的表现形式
def foo(*args):
    return args,type(args)

print(foo(1,2,3,4,5))
>>>((1, 2, 3, 4, 5), <class 'tuple'>)     #所以可以观察到,*args会把接受到的位置参数组成一个元组。


#二。既然*args是一个元组的形式,那么就可以对它进行遍历。
def mysum(*args):
    the_sum = 0
    for i in args:
        the_sum = the_sum + i
    return the_sum

res = mysum(1,2,3,4)
print(res)

#三。观察位置参数,与*args接受参数
def foo2(a,b,c,*args):
    print(a)
    print(b)
    print(c)
    print(args)

foo2(1,2,3,4,5,6,7,8)
>>>
1      #根据位置参数,形参与实参一一对应,a接受了1
2      #根据位置参数,形参与实参一一对应,b接受了2
3      #根据位置参数,形参与实参一一对应,c接受了3
(4, 5, 6, 7, 8)    #*args接受了剩下的所有位置参数;*args就相当于一个大胃王,把剩余的位置参数都吃掉。

#四。如果没有给*args传值,它会报错吗???
def foo3(a,b,c,*args):
    print(a)
    print(b)
    print(c)
    print(args)  

foo3(1,2,3)    #根据形参与实参一一对应,a接受了1,b接受了2,c接受了3,*args没有参数,会如何?
>>>
1       
2       
3
()              #根据结果我们可以知道,就算没有给*args传值,它会形成一个()空元祖。

'''
从上面的代码,我们可以知道。*args就是一个胃口极大的家伙,会把多个位置参数都接受。
所以位置参数必须放置在*args的前面。
'''

  1.1 位置参数,默认参数,*args的顺序

#前提:从上面的代码,我们已经知道:
#1.位置参数需要放在默认参数的前面。
#2.位置参数需要放在*args的前面。
#那么,默认参数和*args的排序位置又是怎么样的呢?我们接下来就来分析~

#一。默认参数在*args的前面
def foo4(a,b,c,d='alex',*args):
    print(a)
    print(b)
    print(c)
    print(d)
    print(args)
foo4('he','bob','taibai','wusir','evj')
>>>
he           #a接受'he'
bob         #b接受'bob'
taibai      #c接受'taibai'
wusir       #d原本是默认参数,这里接受到了新的值,所以原值被覆盖了
('evj',)    #*args接受剩下的位置参数


##从上面看出,默认参数如果在*args的前面,原值就会被覆盖掉,所以默认参数需要放置到*args的后面##

  参数顺序: ‘位置参数  *args  默认参数’

  1.2 *args的拓展以及魔法方法

# 如果有现成的列表,可以通过“*列表名”把列表传入

#一。如果传入不加“*”
l1 = [1,2,3]
l2 = ['he','alex','wusir']
def func(*args):
    print(args)
func(l1,l2)      
>>> 
([1, 2, 3], ['he', 'alex', 'wusir'])           #会把每个列表当成一个独立的元组的元素

#魔法方法:打散
l1 = [1,2,3]
l2 = ['he','alex','wusir']
def func(*args):
    print(args)
func(*l1,*l2)
>>>
(1, 2, 3, 'he', 'alex', 'wusir')                #会把列表的元素打散,然后组成一个元组。

  二. **kwargs:keyword args,顾名思义关键词动态参数,与字典对应。

# 一。**kwargs接受关键字参数,观察其表现形式

def func(**kwargs):
    print(kwargs,type(kwargs))

func(name='he',age=23,sex='male')
>>>
{'name': 'he', 'age': 23, 'sex': 'male'} <class 'dict'>   #**kwargs接受多个关键词参数,将他们组织成一个字典的形式。

#二。所以**kwargs符合字典的所有特性。
def car(**kwargs):
    for k,v in kwargs.items():
        print(f'{k}:{v}')
car(color='red',price=20,user='he')
>>>
color:red
price:20
user:he

#三。从上面我们已经理清楚了位置参数,默认参数,*args的顺序的问题。现在,加入**kwargs会如何?
###系统规定了**kwargs放在所有参数的最后面。####
def func(a,b,*args,sex='male',**kwargs):
    print(a)
    print(b)
    print(args)
    print(sex)
    print(kwargs)
func(1,2,3,4,5,6,name='he',age=23,sex='female')

#所以,参数的位置为:位置参数,*args,默认参数,**kwargs

  参数顺序: ‘位置参数  *args  默认参数   **kwargs’ 

 2.1 **kwargs的拓展以及魔法方法

#如果现在有现成的列表,可以通过**dict把字典传入

dic = {'color':'red','price':100}
def car(**kwargs):
    print(kwargs)
car(**dic)
>>>
{'color': 'red', 'price': 100}


# 魔术方法:打散
def func(**kwargs):
    print(kwargs)

dic = {'name1':'he','age1':23}
dic1 = {'name2':'alex','age2':33}
func(**dic,**dic1)
>>>
{'name1': 'he', 'age1': 23, 'name2': 'alex', 'age2': 33}

  . 结合*args,**kwargs的函数,称为万能参数。

# *args接受所有的位置参数,**kwargs接受所哟关键字参数。
def func(*args,**kwargs);
    pass

 

posted @ 2018-08-15 15:55  hehehe1994  阅读(266)  评论(0编辑  收藏  举报