Python笔记-函数(20160319)

来源:互联网 发布:淘宝模版350 编辑:程序博客网 时间:2024/05/18 01:23
python的函数调用中:函数名其实就是指向一个对象的引用,完全可以把函数名赋值一个变量,相当于给这个函数起来一个别名。


1、空函数


如果想定义一个什么事也不做的空函数,可以用pass语句:


def nop():

    pass


pass语句什么都不做,那有什么用?实际上pass可以用来作为占位符,比如现在还没想好怎么写函数的代码,就可以先放一个pass,让代码能运行起来。

异常和错误处理 (内置函数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

def move(x, y, step, angle=0):
    nx = x + step * math.cos(angle)
    ny = y - step * math.sin(angle)

    return nx, ny


返回值是一个tuple!但是,在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便
   
小结:
函数执行完毕也没有return语句时,自动return None。

函数可以同时返回多个值,但其实就是一个tuple。

注意:

定义默认参数要牢记:默认参数必须指向不变对象(list可变)



2、可变长参数 *


def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
    
如果已经有一个list或者tuple,要调用一个可变参数怎么办?可以这样做:
这种写法当然是可行的,问题是太繁琐,所以Python允许你在list或tuple前面加一个*号,把list或tuple的元素变成可变参数传进去:

>>> nums = [1, 2, 3]
>>> calc(*nums)

14


*nums表示把nums这个list的所有元素作为可变参数传进去。这种写法相当有用,而且很常见。 

小结:可变参数允许你传入 0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple



3、关键字参数


关键字参数婿你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装成为一个dict 


def person(name, age, **kw):

    print('name:', name, 'age:', age, 'other:', kw)


函数person除了必选参数name和age外,还接受关键字参数kw。在调用该函数时,可以只传入必选参数:


>>> person('Michael', 30)

name: Michael age: 30 other: {}


也可以传入任意个数的关键字参数:


>>> person('Bob', 35, city='Beijing')
name: Bob age: 35 other: {'city': 'Beijing'}
>>> person('Adam', 45, gender='M', job='Engineer')
name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}  


关键字参数有什么用:可以扩展函数功能,比如上述你在做一个用户注册功能,除了用户名和年龄是必填外,其他都是可选择项,利用关键字参数来定义这个函数就能满足注册的需求。


**kw表示吧kw这个dict的所有key-value用关键字参数传入到函数的**kw参数,kw将获得一个dict,注意kw获得的dict是extra的一份拷贝,对kw的改动不会影响到函数外的kw



4、命名关键字参数


对于关键字参数,函数的调用者可以传入任意不受限制的关键字参数,至于传入了哪些就需要在函数内部通过kw
检查,仍然以上述为例
调用者传入的是不受限制的参数怎么办?
若要限制关键字参数的名字,就可以用命名关键字参数,例如,值接受city和job作为关键字参数,这种方式

定义如下:


def person(name ,age, *, city, job);

    print(name, age, city, job)


和关键字参数**kw不同,命名关键字参数需要一个特殊分隔符 *, *后面的参数被视为命名关键字参数。

调用如下:


>>> person('Jack', 24, city = 'Beijing', job = 'Engineer')
Jack 24 Beijing Engineer

命名关键字参数必须传入参数名,这个位置参数不容,如果没有传入参数名,调用将会报错



5、参数组合


在python中定义函数,可以用必选参数、默认参数、可变参数、关键字参数和命名关键字参数,这五种参数可以组合使用,可变参数
无法和命名关键字参数混合,注意:定义参数的顺序必须是:
必须参数,默认参数、可变参数、命名关键字参数和关键字参数。



#======

关于参数小结:


默认参数一定是不可变对象,若是可变对象,程序运行时会有逻辑错误
* args 是可变参数,args接受的是一个tuple
** kw 是关键字参数,kw接受的是一个dict
可变参数既可以直接传入:func(1, 2, 3),又可以先组装list或tuple,在通过*args传入:func(*(1, 2, 3))
关键字参数既可以直接传入:func( a = 1, b = 2),又可以先组装成dict,再通过**kw传入:func(**{'a':1, 'b': 2})
关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
定义命名关键字参数不要忘了写分隔符* ,否则定义的将是位置参数。



#======

递归函数


使用递归函数需要注意防止栈溢出,在计算机中,函数调用时通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减少一层栈帧,栈的大小不是无限的,所以递归如果次数过多,会导致栈溢出。
解决递归调用栈溢出的方法是通过尾递归化优,实际上尾递归和循环的效果是一样的,所以把循环看成是一种特殊的尾递归函数也是可以的,那么什么是尾递归呢?在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。这样编译器或者解释器就会把尾递归做优化,是递归无论调用多少次都只用占用一个栈帧,不会出现栈溢出的情况。
0 0
原创粉丝点击