python笔记9

来源:互联网 发布:上海兴安得力软件 编辑:程序博客网 时间:2024/05/21 17:04

2017/10/13

函数传参

 

1.函数传参

定义:函数是可以重复执行的代码块,可以重复使用

作用:定义用户级的函数(非系统库内,用户子集定义,子集拿来使用执行)

语法:

    def 函数名(参数列表):

        语句块(代码块)...

语法说明:

    (1)函数名是语句块的名称;

    (2)函数名的命名规则与变量名相同(变量名是一个标识符);

    (3)函数的名字是一个变量,是绑定代码块的名称(不要给函数名赋值,否则函数代码无效);

    (4)函数有自己的名字空间,要让函数处理外部数据需要用参数给函数传入一些数据,如果不需要传入参数,参数列表可以是空(即使在外部给形参绑定了变量,最终函数还是会传入实参,对外部的变量充耳不闻);

    (5)语句块部分不能为空,如果为空需要填充pass语句

 

 

实例1:

def say_hello():                    #必须有括号,冒号,表示与语句块的分离,函数名称定义完毕

    print('hello world!')           #必须缩进

    print('hello xiaoyuxiu!')

    print('long time no see')

 

实例2:

def mysum(a,b):

    print('调用 mysum(%s,%s)' % (a,b))   #使用了占位符

 

实例3:

def nothing():

    pass                            #语句块为空的时候一定要添加pass语句

 

函数的调用:

   函数名(实际参数)

 

回顾:

    表达式:用于语句中,表达式一定会返回一个值

    语句:表达式,表达式的组合,可单独执行

 

 

函数调用说明:

    (1)函数调用是一个表达式,可作为加减乘除一部分;

    (2)如果没有return语句,函数执行完毕返回None值对象(如果函数没有返回值,会自动返回一个None值。实例1中返回的是print打印语句,实例4中执行了,但是没有返回值,所以默认返回了一个None值);

    (3)如果函数需要返回其他的值对象需要用return语句

 

 

实例4:

def h():

    print("hello")

print(h())

>>>

hello

None          @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

其中print(h())相当于以下三行:

_temp = h()   #_temp = None,None是函数的返回值

print(_temp)  #None

del _temp

 

 

总结函数定义和调用的注意事项:

    (1)连续定义两个函数是,python推荐之间空两行;

    (2)函数内定义的变量是局部变量,不是全局变量,外部是不会使用执行的;

    (3)不要给函数名赋值,否则函数代码无效;

    (4)即使在外部给形参绑定了变量(为形参赋值),最终函数还是会在调用的时候传入实参,对外部的变量充耳不闻

 

 

2.return语句

语法:

    return[表达式]   #表达式一定会返回一个值

 

作用:

    结束当前函数的执行,返回到调用(定义函数时,实际也是调用表达式,定义函数在执行完后一定会返回一个值)

 

实例5:

def fun1:

    print("fun1 被调用!")

 

r = fun1()   #函数调用时调用表达式,一定会返回一个值  fun1() 执行完所有的语句时返回一个值

print(r)     #返回None

 

实例6-实例1的本质:

def fun1:

    print("fun1 被调用!")

    return None        #实际在定义的函数中,该封装语句块中默认返回None,比如max()函数就返回最大值,而不是None

r = fun1()   

print(r)  

 

实例7:

def fun1:

    print("fun1 被调用!")

    return 123

r = fun1()   

print(r)  

 

实例8:

def fun1:

    print("fun1 被调用!")

    return 123

    print("真是函数的最后一行")  #由于执行了return语句,结束了函数调用,将'123'返回给了r ,这行语句不会执行

r = fun1()   

print(r)

总结:执行 print("fun1 被调用!"),fun1()函数执行后返回一个值 123 给r

 

 

说明:

    (1)return语句后跟表达式可以省略,省略后相当于return None;

    (2)如果函数内部没有return语句,则函数执行完最后一条语句后返回None(相当于在最后加了一条return None语句);

    (3)函数的调用可以返回一个值或一组值

 

实例9:

def fun2():

    return          #return后没有内容表示 return None

    print("123")

r = fun2()

print('r = ',r)

 

实例10:

def fun3():

    return [1,2,3]

x,y,z = fun3()

print(x,y,z)        #打印 1,2,3

 

------------------------------------------------------------------------------------------------------------

 

 

3.函数的参数传递:

传递方式:

    1.位置传参

    2. *  序列传参(列表)

    3. ** 关键字传参

 

(a)位置传参:

    实际参的对应关系与形式参数的对应关系是以位置来依次对应的

说明:

    (1)实际参数和形式参数通过位置进行对应和传递;

    (2)实参和形参的个数必须完全相同

 

 

实例11:

def sum3(a,b,c):

    retrun a+b+c

x = sum3(1,2,3)

 

(b)序列传参(列表,元组,字符串):

    序列的元素个数必须与列表的个数相同(解决列表,元组,字符串传参先取出后赋值的繁琐操作,见实例12)

实例12:

def myfun(a,b,c):

    print("a-->",a)

    print("b-->",b)

    print("c-->",c)

 

myfun(100,200,300)    #位置传参

s1 = [11,22,33]       #序列传参

myfun(*s1)            #等同于s1 = myfun(s1[0],s1[1]s1[2])

 

s2 = (1.1 2.2 3.3)

myfun(*s2)

 

s3 = "abcd"

myfun(*s3)

 

 

(c)关键字传参:

    按照形参的名称给形参赋值;

    实际参数和形参按名称进行匹配。

 

 

实例13:

def myfun(a,b,c):

    print("a-->",a)

    print("b-->",b)

    print("c-->",c)

 

myfun(100,200,300)    #位置传参

 

s1 = [11,22,33]       #序列传参

myfun(*s1)

 

myfun(a=1,b=2,c=3)    #关键字传参

myfun(c=10,a=20,c=30) #关键字传参,可以不按形参的顺序进行传递

 

 

实例14:

def myfun(a,b,c):

    print("a-->",a)

    print("b-->",b)

    print("c-->",c)

myfun(c=10,a=20,b=30,d=78,e=90) #实参个数比形式参数多

bug:TypeError: myfun() got an unexpected keyword argument 'd'

 

 

 

(d)字典关键字传参:

    实参和形参通过字典进行传递和匹配,字典的值传递给键对应的形参

实例15:

def myfun(a,b,c):

    print("a-->",a)

    print("b-->",b)

    print("c-->",c)

d = {'c':33,'a':11,'b':22}  

myfun(**d)

 

说明:

    字典传参的键名和形参名必须一致;

    键名必须为字符串;@@@@@@@@@@@@@@@@@@@@@@@@

    键名要在形参中存在。

 

 

(e)综合传参:

实例:

def myfun(a,b,c):

    print("a-->",a)

    print("b-->",b)

    print("c-->",c)

 

myfun(100,*(200,300))  #位置传参,序列(元组,序列,字符串)传参一起使用

myfun(*[10,30],20)     #正确

myfun(*[11],22,*(33,)) #正确

myfun(1,b=2,c=3)       #正确

myfun(101,**{'b':202,'c':303})     #正确

myfun(**{'c':33,'a':11},b=22)      #正确,关键字传参,不一定按照原来的顺序

myfun(c=3,b=2,1)       #错误,1元素位于第3个位置  如果没有关键字就是位置传参,与c=3冲突

 

拓展:

print("nihao1",end='',sep=' ') #end 和 sep实际就是关键字传参

 

------------------------------------------------------------------------------------------------------------

 

4.创建函数(函数的定义,指的是函数形参)

 

(a)函数的缺省参数

语法:

    def 函数名(形参1=默认参数1,形参2=默认参数2,...):

    语句

 

实例15:

def info(name,age=1,addr='不详'):  

    print('姓名',name,'年龄',age,'住址',addr)

info('xiao',23,'多伦多')

info('Tarena',15)

info('张飞')

 

实例16:

函数sum4(a,b,c,d)来计算4个参数的和,可以用如下方法调用:

print(sum(1,2))

print(sum4(1.1,2.2,3,3))

print(sum4(100,200,300,400))

 

def sum4(a,b,c=0,d=0):           #全部默认赋值也是可以的

    return sum((a,b,c,d))

print(sum4(1,2))

print(sum4(1.1,2.2,3.3))

print(sum4(100,200,300,400))

 

缺省参数说明:

    (1)缺省参数必须自右至左依次存在,如果一个参数有缺省值,则其右侧的所有参数都必须有缺省参数(缺省值)(即倒数第1个有缺省,倒数第2个才有缺省,倒数第3个才有缺省...);

    (2)缺省参数可以有0个或多个,甚至全部是有缺省参数

 

错误实例17:

def fn(a,b=10,c):pass    #错误,c必须有缺省;如果只有一行语句,可以放在冒号后面,但不推荐  

def fn(a=10,b,c):pass    #错误,b c 必须有缺省;如果只有一行语句,可以放在冒号后面,但不推荐

 

 

5.函数的不定长参数:

包括星号元组形参 和 双星号字典形参

类比max() min() 函数,min(1,2) min(2,1,3) min(1,2,3,4)

 

(a)星号元组形参:

语法:

def 函数名(*元组形参名):

    语句块

 

实例18:

def myfun(*args):                      #这里的参数是个元组

    print("实参个数是",len(args))

    print(args)                        #打印的是一个元组

myfun(1,2)

myfun('100',200,'Three',4.4)

>>>

实参个数是 2

(1, 2)

实参个数是 4

('100', 200, 'Three', 4.4)  #打印出的是元组,有序列,可以查找元素的位置

 

实例19:

def myfun(*args):

    print("实参个数是",len(args))@@@@@@@@@@@@ @@@@@@@@@@@@@

    print(args)                          #打印的是一个元组

    i = 1

    for i in args:                       #这里出错

        print('第',i,'个参数是:',x)

        i += 1                          #i是元组中的元组,不能进行加减

myfun(1,2)

print('-'*20)

myfun('100',200,'Three',4.4)            #打印报错  

 

bug修改:

 

def myfun(*args):

    print("实参个数是",len(args))

    print(args)

    i = 1

    for i in range(len(args)):

        print('第',i+1,'个参数是:',args[i])

        i += 1

myfun(1,2)

print('-'*20)

myfun('100',200,'Three',4.4)

 

 

(b)命名关键字形参(named)

语法:

    def 函数名(*,命名关键字形参名)

        语句块

 

    def 函数名(*args,命名关键字形参名)

        语句块 

 

实例20:

def myfun1(a,b,*,c)   #*表示空,c为命名关键字形参,*作为分隔符,后面的位置形参已经不再是位置形参,而必须通过关键字传递参数

    print(a,b,c)

myfun1(1,2,c=3)    #正确

myfun1(11,22,33)   #错误

 

 

实例21:

def myfun2(a,*args,b,c):  c为命名关键字形参,b c 只能用关键字传参

    print(a,b,c,args)

myfun2(1,2,3,4)         #错误,*后面的参数全是命名关键字参数,不能再按照位置传参

 

myfun2(1,2,c=3,d=4)     #正确

>>>1 4 3 (2,)

 

myfun2(11,b=22,c=33)    #正确

>>>11 22 33 ()

 

 

 

(c)双星号元组形参:

语法:

def 函数名(**字典形参名):

    语句

 

实例22:

def func(**kwargs):

    print("参数个数:",len(kwargs))

    for k,v in kwargs.items():     #对应字典的键和值 @@@@@

        print(k,'->>',v)

    print(kwargs)                  #打印生成的字典

 

func(name='tarena',age=15)           #调用

func(a=1,b='BBB',c=[1,2,3],d=True)

func(1,2,3)                        #错误,这是序列传参,不是字典传参

 

 

(d)函数的参数列表顺序:

    位置形参,缺省参数,星号元组形参,双星号元组形参,命名关键字参数可以混合使用

函数参数自左至右的顺序为:

    位置形参,星号元组形参,命名关键字参数,双星号字典形参

实例:

def fn(a,b,*args,c,**kwargs):

    pass

fn(100,200,300,400,c='C',d='D',e='E')

 

详细语法:

    见 -->> help('def')

 

 

------------------------------------------------------------------------------------------------------------

 

练习:

1.

定义两个函数:sum3(a,b,c)返回三个数的和,pow3(x)返回x的立方,用以上两个函数计算:1的立方 + 2的立方 + 3的立方的和;1+2+3的和的立方。

解:

 

def sum3(a,b,c):

    return sum((a,b,c))

def pow(d):

    return d**3

x1 = sum3(1,2,1)

x2 = pow(1)

x3 = pow(2)

x4 = pow(3)

x5 = x2 + x3 + x4

print(x5)

x6 = pow(x1)

print(x6)

 

bug总结:

第二行写为return sum(a,b,c) 将报错

分析: sum()函数只能对一个序列或者元组求和,如果内部没有括号,计算机无法明确序列的个数,因为a,b,c可能均绑定了一个列表

正确写法:

return sum((a,b,c)) 或者 return sum([a,b,c])

不能写为:return sum({a,b,c}),实参重复时会去重

 

改进:

def sum3(a,b,c):

    return sum((a,b,c))

def pow(d):

    return d**3

x5 = pow(1)+ = pow(2)+ pow(3)

print(x5)

x6 = pow(sum3(1,2,3))

print(x6)

 

 

 

2.

函数sum4(a,b,c,d)来计算4个参数的和,可以用如下方法调用:

print(sum(1,2))

print(sum4(1.1,2.2,3,3))

print(sum4(100,200,300,400))

 

解:

def sum4(a,b,c=0,d=0):           #全部默认赋值也是可以的

    return sum((a,b,c,d))

print(sum4(1,2))

print(sum4(1.1,2.2,3.3))

print(sum4(100,200,300,400))

 

曾出现的bug:

return sum(a,b,c,d)   #这个括号是sum函数的括号,它只能对一个列表,元组,字典的值进行加处理出来

return sum(1,2,3)     #这个括号是sum函数的括号,它只能对一个列表,元组,字典的值进行加处理出来

修改为:

return sum((a,b,c,d))   

return sum((1,2,3))

 

 

3.

写一个函数minmax有不定长个参数,返回这些参数的最大值和最小值(形成元组,最小在前,最大在后)

调用此函数,得到最大值和最小值并打印出来

 

解:

def minmax(*args):

    a = max(args)

    b = min(args)

    T = (b,a)

    print(T)

minmax(1,2,3,4,5,6)

 

另:

def minmax(*args):

    a = max(args)

    b = min(args)

    T = (b,a)

    return(b,a)

x,y = minmax(20,23,5,89,1,12,25)

print('最大值:',a)

print('最小值:',b)

 

另:元组排序,首尾的数

 

 

新解法:

def minmax(*t)

    if len(t) < 2:

        print("too short")

    min_v = t[0]

    for i in range(1,len(t)):

        if min_v > t[i]:

            min_v = t[i]

    max_v = t[0]

    for i in range(1,len(t)):

        if max_v < t[i]:

            max_v = t[i]

    return(min_v,max_v)

 

x,y = minmax(20,23,5,89,1,12,25)

print('最大值:',x)

print('最小值:',y)

 

 

4.

prime(质数/素数)

(1)写一个函数isprime(x),判断x是否为素数,如果为素数,返回Ture,否则返回False

(2)与一个函数prime_m2n(m,n) 返回从m开始,到n结束范围内的质数,返回这些质数的列表,并在主程序中打印

如:

  L = prime_m2n(5,10)

  print(L) #[5,7]

(3)写一个函数primes(n),返回指定范围内的全部素数的列表,并在主程序中打印这些素数

  L = primes(100)

  pirnt(L) # [2,3,5,7,.......,97]

 

解法1:

(1)

def isprime(x):

    L = []

    for i in range(2,x):

        L.append(x%i)

    if 0 not in L:

        print('True')

    if 0 in L:

        print('False')

n = int(input('please enter a num > 2:'))

isprime(n)

 

(2)

def isprime(x):

    L = []

    for i in range(2,x):

        L.append(x%i)

    if 0 not in L:

        return x

begin = int(input('please enter begin num:'))

end = int(input('please enter ending num:'))

k = []

for i in range(begin,end+1):

    if isprime(i)!=None:

       k.append(isprime(i))                          

print(k)

 

(3)

def isprime(x):

    L = []

    for i in range(2,x):

        L.append(x%i)

    if 0 not in L:

        return x

end = int(input('please enter ending num:'))

k = []

for i in range(2,end+1):

    if isprime(i)!=None:

       k.append(isprime(i))                          

print(k)

 

总结:

我自己的解法1中,第(1)和(2)没有实质的关系,因为我没有将第1题已经定义的函数直接拿到下面来用,而是将第1题中的代码块拿到第2题中进行修改,重新运用。

 

 

 

改进和优化(参照陈璐):

def isprime(x):

    L = []

    for i in range(2, x):

        L.append(x % i)

    if 0 not in L:

        return True

    if 0 in L:

        return False

n = int(input('please enter a num > 2:'))

print(isprime(n))

 

#-----------------------------------------------------

 

begin = int(input('please enter begin num:'))

end = int(input('please enter ending num:'))

def prime_m2n(begin, end):

    l = []

    for i in range(begin, end+1):

        if isprime(i) == True:               #关键点在这里,这里在定义的函数体重引入了1题定义的函数,变成函数的嵌套体,仅对函数的返回结果做了判断,然后进行一系列的赋值操作

            l.append(i)

    return l

print(prime_m2n(begin, end))

 

#-----------------------------------------------------

 

ending = int(input('please enter ending num:'))

def primes(ending):

    l = []

    for i in range(2, ending):

        if isprime(i) == True:

            l.append(i)

    return l

print(primes(ending))

 

 

 

新的解法:

#-------------------------------

 

def isprime(x):

    if x <= 1:

        return False

    for i in range(2,x):  

        if x % i == 0:

            return False

    return True

 

#-------------------------------

 

def prime_m2n(m,n):

    L = []

    for x in range(m,n+1):

        if isprime(x):

            L.append(x)

    return L

 

L2 = prime_m2n(5,100)

print(L2)

 

#-------------------------------

 

def primes(n):

    return prime_m2n(1,n)

 

L3 = primes(100)

print(L3)