Python之路--python基础3

python基础3
一、函数基本语法及特性
二、函数参数
三、局部变量和全局变量
四、返回值
嵌套函数
五、递归函数
六、匿名函数
七、高阶函数
八、内置函数
九、函数式编程python

在编程语言中的函数并不是数学意义上的函数(老是返回根据参数计算获得的结果),编程语言中的函数也称为过程,在使用这个函数的时候有可能不会返回一个结果或者说返回的结果不是数学意义上的函数执行的结果。程序员

1、函数基本语法及特性

一、抽象和结构

抽象是程序可以被别人理解的关键所在(不管对编写程序仍是阅读程序来讲,这都相当重要)。
程序应很是抽象,以下载网页、计算使用频率、打印每一个单词的使用频率。下面将上述简单描述转换为一个Python程序:express

page = download_page()
freqs = compute_frequencies(page)
for word, freq in freqs:
    print(word, freq)

看到这些代码,任何人都知道这个程序是作什么的。至于具体该如何作那么咱们就得在函数中得出定义。编程

在好比打印斐波那契数(一种数列,其中每一个数都是前两个数的和)app

fibs = [0,1]
for i in range(8):
    fibs.append(fibs[-2] + fibs[-1])
print(fibs)

上述代码会打印出斐波那契数的前十个,固然你也能够指定要打印数的个数:编程语言

num = int(input("How many Fibonacci numbers do you want?"))
fib = [0,1]
for i in range(num-2):
    fibs.append(fibs[-2] + fibs[-1])
print(fibs)

当咱们在其余地方想使用这些数的时候,你可能会想到我再把这个循环再写一次,对于这段代码是能够的,可是对于更加复杂的代码你还愿意去重写吗?真正的程序员会去抽象程序,把一些想要实现的功能抽象为函数,直接调用这个函数来实现指定的功能,让程序更加简洁易懂而且下降代码的重复率。真正的程序员会像下面这样作:函数式编程

num = int(input("How many Fibonacci numbers do you want?"))
print(fibs(num))

二、函数的定义

def 函数名():
    函数体

例如:函数

def hello():
    print("Hello world!")

三、给函数编写文档

要给函数编写文档,以确保其余人可以理解,可添加注释。放在函数开头的字符串成为文档字符串(docstring),将做为函数的一部分存储起来。例如:ui

def square(x):
    'Calculates the square of the number x.'
    return x * x

能够像下面这样访问文档字符串:spa

>>> square.__doc__
'Calculates the square of the number x.'

特殊的内置函数help颇有用。在交互式解释器中,可以使用它获取有关函数的信息,其中包含函数的文档字符串。

>>> help(square)
Help on function square in module __main__:
square(x)
Calculates the square of the number x.

2、函数的参数

为了让一个函数更通用,在定义函数的时候可让函数接收数据,函数接收的数据就是函数的参数。

一、参数的基本应用

(1)定义带参数的函数


示例以下:

def add(a,b):
    c = a + b
    print(c)

(2)调用带参数的函数


以上面的add函数为例,咱们调用该函数,代码以下:

def add(a,b):
    c = a + b
    print(c)
   
add(11,22)   #调用带参数的函数时,须要在小括号中传递数据

(3)调用函数时参数的顺序


>>> def test(a,b):
...     print(a,b)
... 
>>> test(1,2)
1 2
>>> test(b=1,a=2)
2 1
>>> 
>>> test(b=1,2)
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>> 
>>>

经过以上代码咱们能够看出,函数的参数在调用的过程当中是一一对应的,若是不指定那个实参是那个对应的形参时,会默认按实参的顺序将实参赋值给形参。

(4)总结


  • 定义时小括号中的参数,用来接收参数用的,称为“形参”
  • 调用时小括号中的参数,用来传递给函数的,称为“实参”

二、参数的高级应用

(1)缺省参数


调用函数时,缺省参数的值若是没有传入,则被认为是默认值。缺省参数就是给参数设定默认值,若是在传参过程当中,缺省参数传入值的话则依照传入的值,若是没有传入值则按照默认的值。以下代码:

def sum(a,b=11):
    result = a + b 
    print("%d+%d=%d"%(a,b,result))

sum(11,22)    #调用函数时会将11和22分别赋值给a和b
sum(10,)      #调用函数时,因为只给了一个实参,则10赋值给a,b则用默认的参数值11

程序运行结果以下:

clipboard.png

注意:带有默认值的参数必定要位于参数列表的最后面。

>>> def printinfo(name, age=35, sex):
...     print name
...
  File "<stdin>", line 1
SyntaxError: non-default argument follows default argument

(2)不定长参数


有时可能须要一个函数能处理比当初声明时更多的参数,这些参数叫作不定长参数,声明时不会命名。

基本语法以下:

def functionname([formal_args,] *args, **kwargs):
    "函数_文档字符串"
    function_suite
    return [expression]
加*号的变量args会存放全部未命名的变量参数,args为元组
加**号的变量kwargs会存放命名参数,即形如key=value的参数,kwargs为字典

可变参数示例:

>>> def fun(a, b, *args, **kwargs):
...     """可变参数演示示例"""
...     print "a =", a
...     print "b =", b
...     print "args =", args
...     print "kwargs: "
...     for key, value in kwargs.items():
...         print key, "=", value
...
>>> fun(1, 2, 3, 4, 5, m=6, n=7, p=8)  # 注意传递的参数对应
a = 1
b = 2
args = (3, 4, 5)
kwargs: 
p = 8
m = 6
n = 7
>>>
>>>
>>> c = (3, 4, 5)
>>> d = {"m":6, "n":7, "p":8}
>>> fun(1, 2, *c, **d)    # 注意元组与字典的传参方式
a = 1
b = 2
args = (3, 4, 5)
kwargs: 
p = 8
m = 6
n = 7
>>>
>>>
>>> fun(1, 2, c, d) # 注意不加星号与上面的区别
a = 1
b = 2
args = ((3, 4, 5), {'p': 8, 'm': 6, 'n': 7})
kwargs:
>>>
>>>

(3)引用传参


  • 可变类型与不可变类型的变量分别做为函数参数时,会有什么不一样?
  • Python有没有相似C语言中的指针传参?
>>> def selfAdd(a):
...     """自增"""
...     a += a
...
>>> a_int = 1
>>> a_int
1
>>> selfAdd(a_int)
>>> a_int
1
>>> a_list = [1, 2]
>>> a_list
[1, 2]
>>> selfAdd(a_list)
>>> a_list
[1, 2, 1, 2]

Python中函数参数是引用传递(注意不是值传递)。对于不可变类型,因变量不能修改,因此运算不会影响到变量自身;而对于可变类型来讲,函数体中的运算可能会更改传入的参数变量。

以下代码示例:

>>> def selfAdd(a):
...     """自增"""
...     a = a + a   # 咱们更改了函数体的这句话
...
>>> a_int = 1
>>> a_int
1
>>> selfAdd(a_int)
>>> a_int
1
>>> a_list = [1, 2]
>>> a_list
[1, 2]
>>> selfAdd(a_list)
>>> a_list
[1, 2]      # 想想为何没有变呢?

Python中变量之间的赋值利用到引用,只要是有"="就是引用,引用就是变量中存储的是地址,而地址指向的内存空间是存真实数据地方。a = a + a会建立一个新的内存空间,而后让变量a指向这段空间;而a += a是将a所指向的那段空间的值变为a + a。以下demo:

>>> a = [1,2]
>>> id(a)
31329224
>>> a = a + a
>>> a
[1, 2, 1, 2]
>>> id(a)
31991944
>>> b = 2
>>> id(b)
1587990368
>>> b = b + b
>>> b
4
>>> id(b)
1587990432
>>> c = [1,2]
>>> id(c)
31992072
>>> c += c
>>> c
[1, 2, 1, 2]
>>> id(c)
31992072
>>>

3、局部变量和全局变量

一、局部变量

  • 局部变量,就是定义在函数内部的变量,其做用单位只是在函数体内;
  • 不一样的函数,能够定义相同名字的局部变量,其不会产生影响;
  • 局部变量的做用:为了临时保存数据须要在函数中定义变量来进行存储。

示例:

def test1():
    a = 100     #此时的a为局部变量,做用范围只在test1函数内
def test2():
    print("a=%d"%a)
    
test1()
test2()

此时因为a是局部变量,其作做用范围只在test1函数中,至关于test2函数中没有定义变量a,因此上述程序在运行时会报以下错误:

clipboard.png

二、全局变量

(1)什么是全局变量


若是一个变量既能在函数体中使用,也能在其余函数中使用,这样的变量称为全局变量

示例:

#定义全局变量
a = 100

def test1():
    print("a=%d"%a)

def test2():
    print("a=%d"%a)

#调用函数
test1()
test2()

因为变量a是全局变量,因此在test1和test2两个函数中均可以使用变量a,运行结果以下:

clipboard.png

(2)全局变量与局部变量同名的问题


当全局变量与局部变量同名时,在定义该局部变量的函数体内以局部变量为主,以下示例:

#定义全局变量
a = 100 

def test1():
    a = 300 
    print("---test1--修改前--a=%d"%a)
    a = 200 
    print("---test1--修改后--a=%d"%a)

def test2():
    print("---test2---a=%d"%a)

test1()
test2()

此时,对于test1函数,函数体内定义了和所有变量同名的局部变量a,此时会以函数中的变量a为根据;对于test2函数,函数体内没有定义和全局变量同名的局部变量,因此若是test2函数使用变量a,则以所有变量a为根据。运行结果以下:

clipboard.png

(3)修改全局变量


既然是全局变量,就能够在全部的函数中是,那么是否能够修改呢?看以下代码:

#定义全局变量
a = 100 

def test1():
    global a
    print("---test1--修改前--a=%d"%a)
    a = 200 
    print("---test1--修改后--a=%d"%a)

def test2():
    print("---test2---a=%d"%a)

test1()
test2()

代码运行结果以下:

clipboard.png

在函数体内利用global这个关键字来声明变量为全局变量,此时在函数体内对该变量的操做就是至关于对全局变量的操做。

(4)可变类型的全局变量


看下面两个代码示例的区别:

#定义全局变量
a = 100 

def test1():
    print("---test1--修改前--a=%d"%a)
    a = 200 
    print("---test1--修改后--a=%d"%a)

def test2():
    print("---test2---a=%d"%a)

test1()
test2()

上述代码运行结果为:

clipboard.png

#定义全局变量
a = [11,22,33]

def test1():
    print("---test1--修改前--",a)
    a.append(44)
    print("---test1--修改前--",a)

def test2():
    print("---test2--修改前--",a)

test1()
test2()

上述代码运行结果为:

clipboard.png

对于上述两种状况,列表(list)、字典(dict)这种可变的类型的全局变量不用再函数体内声明全局变量,在函数体中对该变量的操做就是在对全局变量进行操做;而像数值类型(int,flaot,bool,long)、字符串(str)、元组(tuple)这种不可变类型的操做,要想在函数体内对这种全局变量进行操做,必须在函数体内声明其为全局变量。

(5)总结


  • 在函数外边定义的变量叫全局变量
  • 全局变量可以在全部的函数中进行访问
  • 若是在函数中修改全局变量,那么就须要使用global进行声明
  • 若是全局变量的名字和局部变量的名字相同,那么使用的是局部变量的,小技巧强龙不压地头蛇
  • 在函数中不使用global声明全局变量时不能修改全局变量的本质是不能修改全局变量的指向,即不能将全局变量指向新的数据
  • 对于不可变类型的全局变量来讲,因其指向的数据不能修改,因此不能使用global时没法修改全局变量
  • 对于可变类型的全局变量来讲,因其指向的数据能够修改,因此不使用global时也可修改全局变量

4、函数的返回值

“返回值”,就是程序中函数完成一件事情后,最后给调用者返回的结果。

一、带有返回值的函数

想要在函数中把结果返回给调用者,须要在函数中使用return
以下示例:

def add2num(a, b):
    c = a+b
    return c
或者
def add2num(a, b):
    return a + b

二、保存函数的返回值

在程序中,若是一个函数返回了一个数据,那么想要用这个数据,就须要用一个变量来保存函数返回的数据。示例以下:

#定义函数
def add2num(a, b):
    return a+b

#调用函数,顺便保存函数的返回值
result = add2num(100,98)

#由于result已经保存了add2num的返回值,因此接下来就可使用了
print result

三、Python返回多值
看以下代码:

def test(a,b):
    sum2 = a + b 
    mulit = a * b 
    return [sum2,mulit]

result = test(2,3)
print(result)

运行结果为:

[5,6]
def test(a,b):
    sum2 = a + b 
    mulit = a * b 
    return sum2,mulit

result = test(2,3)
print(result)

运行结果为:

(5,6)

由上述示例咱们能够得出,当有多个返回值时,利用列表将结果返回,那么函数就会返回一个列表;当将几个返回值用逗号隔开返回时,默认返回的是元组。

相关文章
相关标签/搜索