Python学习记录——函数

一.函数的作用

1.减少重复代码

2.方便修改,易于扩展

3.保持代码一致性,增强可读性

二.函数的使用和结构

1.函数的创建:

def 函数名(<参数>):

  函数体

2.函数的调用:函数名(<参数>)

3.函数的命名规则:和变量一样

4.函数和变量类似,故函数名也可以进行赋值,如f1=f2,则f2函数与f1函数功能一样

5.函数的参数:

(1)形参:

形式参数,不是实际存在,是虚拟变量。在定义函数和函数体的时候使用形参,目的是在函数调用时接收实参(实参个数,类型应与实参一一对应)

(2)实参:

实际参数,调用函数时传给函数的参数,可以是常量,变量,表达式,函数,传给形参   

(3)区别:

形参是虚拟的,不占用内存空间,.形参变量只有在被调用时才分配内存单元,实参是一个变量,占用内存空间,数据传送单向,实参传给形参,不能形参传给实参

6.实例:

import time

times=time.strftime('%Y--%m--%d')  #取出当前时间

def f(time):

  print('Now  time is : %s'%times)  #利用格式化输出,将变化内容作为参数

f(times)

三.函数的参数

1.必备参数

(1)备注:必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样。

(2)示例:

def f(name,age):

  print('Name:%s Age:%d' %(name,age))

f('zhou',20)

2.关键字参数

(1)备注:关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。

(2)示例:

def f(name,age):

  print('Name:%s Age:%d' %(name,age))

f(age=20,name='zhou')

3.默认参数

(1)备注:调用函数时,缺省参数的值如果没有传入,则被认为是默认值。一般放在其他参数的后面。

(2)示例:

def f(name,age,sex='male'):

  print('Name:%s   Age:%d   Sex:%s'  %(name,age,sex))

f('zhou',20)

f('lin',20,'female')

4.不定长参数

(1)备注:一个函数能处理比当初声明时更多的参数,这样的参数叫做不定长参数,和上述2种参数不同,声明时不会命名。

(2)示例1:(加法器)

def add(*args):  #*代表参数不定长,且参数为元组形式

  sum=0

  for i in args:

    sum+=i

  print(sum)

add(1,2,3)

(3)示例2:(个人信息显示)

def f(*args,**kwargs):  #**代表参数不定长,且参数为字典形式

  print('Name:%s   Age:%d   Sex:%s'  %(args[0],args[1],args[2]))

  for i in kwargs:

    print(%s:%s %(i,kwargs[i]))

f('zhou',20,'male',Hobby='invention',Job='student')  #前三个没有键的存入args成为元组,后两个有键的存入kwargs成为字典

(4)示例3:(将一个列表/字典拆分传输)

def f(*args/**kwargs):

  print(args/kwargs)

f(*[1,2,3]/**{'name':'zhou'})  #此时打印结果为1,2,3/{'name':'zhou'}单个元素而不是整个列表/字典

(5)参数优先级:关键参数>默认参数>*args>**kwargs,必须按照此顺序排列实参

四.函数的返回值

(1)要想获取函数的执行结果,就可以用return语句把结果返回

(2)函数在执行过程中只要遇到return语句,就会停止执行并返回结果,所以也可以理解为 return 语句代表着函数的结束

(3)如果未在函数中指定return,那这个函数的返回值为None  

(4)return多个对象,解释器会把这多个对象组装成一个元组作为一个一个整体结果输出。

(5)函数返回值既可以是一个变量,也可以是一个函数,例如:

def f():

  def inner():

    return 6

  return inner

f()  #此时返回的是一个地址,即储存函数代码的地址

五.函数的作用域

1.作用域介绍

(1)L:local,局部作用域,即函数中定义的变量;

(2)E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;

(3)G:globa,全局变量,就是模块级别定义的变量;

(4)B:built-in,系统固定模块里面的变量,比如int, bytearray等。

(5)搜索变量的优先级顺序依次是:局部作用域>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB(从小到大)

(6)示例:

x = int(2.9)  # int built-in

g_count = 0  # global

def outer():

  o_count = 1  # enclosing

  def inner():

    i_count = 2  # local

2.作用域产生

在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)不会引入新的作用域

3.变量的修改

(1)局部作用域只能读取全局作用域的变量,但不能修改:(下面的程序会报错)

x=1

def a():

  print(x)#此时拿到的是全局变量10

  x=2  #错误的原因在于print(x)时,解释器会在局部作用域找,会找到x=2(函数已经加载到内存),但x使用在声明前了,所以报错

a()

(2)要想修改全局作用域中的变量,需在局部变量前加global

(3)要想修改嵌套作用域中的变量,需在局部变量前加nonlocal

 六.高阶函数

1.高阶函数需要满足的条件(至少其中之一):

(1)接受一个或多个函数作为输入

(2)输出一个函数

2.示例:

def f(n):

  return n*n

def F(a,b,func)

  print(f(a)+f(b))

F(1,2,f)  #输出5

七.递归函数

1.定义:在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。

2.递归函数的优点:定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。

3.递归特性:

(1)必须有一个明确的结束条件

(2)每次进入更深一层递归时,问题规模相比上次递归都应有所减少

(3)递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)

八.内置函数

1.内置函数大全:https://docs.python.org/3.5/library/functions.html#repr

2.重要的内置函数:

(1)filter(function, sequence)  #将sequence中的item一个一个传入function

示例:

  str = ['a','b','c','d']

  def fun1(s):

    if s != 'a':

      return s

  ret = filter(fun1, str)

  print(list(ret))  #ret是一个迭代器对象

解释:对sequence中的item依次执行function(item),将执行结果为True的item做成一个filter object的迭代器返回。可以看作是过滤函数。

(2)map(function, sequence)

示例1:

  str = ['a','b','c']

  def fun2(s):

    return s+‘zhou’

  ret = map(fun2, str)

  print(list(ret))  #['azhou', 'bzhou', 'czhou']

解释:对sequence中的item依次执行function(item),将执行结果组成一个map object迭代器返回。

示例2:

  ef add(x,y):

    return x+y

  print (list(map(add, range(10), range(10))))##[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

解释:map也支持多个sequence,这就要求function也支持相应数量的参数输入

(3)reduce(function, sequence, starting_value)

示例:

  from functools import reduce

  def add1(x,y):

    return x + y  #若为x*y则可以用来做阶乘

  print (reduce(add1, range(1, 101)))  # 5050 (注:1+2+...+99+100)

  print (reduce(add1, range(1, 101), 20))  # 4970 (注:1+2+...+99+20)

解释:对sequence中的item顺序迭代调用function,如果有starting_value,还可以作为初始值调用。

(4)lambda  #匿名函数

匿名函数的命名规则:

  用lamdba 关键字标识,冒号(:)左侧表示函数接收的参数(a,b) ,冒号(:)右侧表示函数的返回值(a+b)。

普通函数与匿名函数的对比:

#普通函数

  def add(a,b):

    return a + b

  print(add(2,3))

#匿名函数

  add=lambda a,b : a + b, [2,3]

  print(add(2,3))  #一行即可实现上面多行内容,用于代码简化

#输出

  5

  5

匿名函数使用范围:当函数名不重要而只用其内容时,可以用lambda将函数体直接引用,省去定义函数的代码

3.结合使用功能更加强大:

(1)阶乘:(reduce+lambda)

  from functools import reduce

  print (reduce(lambda x,y: x*y, range(1,6)))

(2)平方:(map+lambda)

  squares = map(lambda x : x*x ,range(9))

  print (squares)  #<map object at 0x10115f7f0>迭代器

  print (list(squares))  #[0, 1, 4, 9, 16, 25, 36, 49, 64]

原文地址:https://www.cnblogs.com/zhoujianlin/p/8511973.html