函数

1、函数定义:

定义一个函数要使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用return语句返回,不带参数值的return语句返回None。

#1、定义无参函数:
def person1():
  
print(“hello”)
  return("hello")    #调用return函数获取返回值
#2、定义有参函数: def person2(name):
  
print(“hello”,name)
  return("hello",name) #调用return函数获取返回值

#3、函数的调用
person1()
person2("ryan")
#1、函数定义:
def test():
    "the funcation details"
    print("in the test funcation")
    return 0

'''
def #定义函数的关键字
test #函数名
() #定义形参,我这边没有定义。如果定义的话,可以写成:def test(x): 其中x就是形式参数
"the funcation details" # 文档描述(非必要,但是强烈建议你为你的函数添加详细信息,方便别人阅读)
print #泛指代码块或者程序逻辑处理
return #定义返回值
'''

#2、过程定义:
#定义过程
def test_2():
    "the funcation details"
    print("in the test funcation")
    
'''
 注:从上面两个例子看出来,函数和过程,无非就是函数比过程多了一个return的返回值,其他的也没什么不一样。
 小结:不难看出,函数和过程其实在python中没有过多的界限,当有return时,则输出返回值,当没有return,则返回None
'''
函数和过程的区别

2、函数作用域

Python使用名称空间的概念存储对象,这个名称空间就是对象作用的区域,不同对象存在于不同的作用域。

每个模块都有自已的全局作用域。函数定义的对象属局部作用域,只在函数内有效,不会影响全局作用域中的对象。赋值对象属局部作用域,除非使用global关键字进行声明。在函数、类等内部可见局部作用域;局部变量使用范围不能超过其所在的局部作用域。

LGB 规则--大多数名字引用在三个作用域中查找:先局部(Local),次之全局(Global),再次之内置(Build-in)。

全局变量是位于模板文件内部的顶层的变量名;
全局变量如果在函数内部被赋值的话,必须经过声明;
全局变量在函数的内部不经过声明也可以被引用。

如想在局部作用域中改变全局作用域的对象,必须使用global关键字 。'global'声明把赋值的名字映射到一个包含它的模块的作用域中。若仍然找不到这个变量名,则引发NameError异常。

#coding=utf-8
name = "ryan"   #全局变量
def fun():
    country = "China" #局部变量
    print name
    global name     #声明全局变量
    name = "joe"    #修改全局变量
    print name
fun() 
print name

 

3、函数参数

#1、普通参数:
# ######### 定义函数 #########
# name 叫做函数func的形式参数,简称:形参
def func(name):
    print(name)
# ######### 执行函数 #########
#  'xiaoyao' 叫做函数func的实际参数,简称:实参
func('xiaoyao')

#2、默认参数:
def func(name, age = 18):
    print("%s:%s" %(name,age))
func('xiaoyao')    # 默认参数在不指定的时候,就是默认值
func('xiaoyao',20)   # 一旦指定,就不再使用默认值
#注:默认参数需要放在参数列表最后,可以有多个默认参数
#指定参数:
def func(name, age):
    print("%s:%s" %(name,age))
func(age=20,name='xiaoyao')  # 可以通过形参名称,不按顺序的传入参数

#3、动态参数(参数组):
#(*args) 功能:接收N个位置参数,转换成元组的形式
def hello(*argv):
    print argv[0]
    print argv
hello(3,3,4)
#(**kwargs) 功能:把N个关键字参数,转换成字典形式
def hello(**kargv):
    print kargv.keys()
    print kargv.values()
    print kargv
hello(a=1,b=3,c=4,d=0)

 

4、匿名函数

python 使用 lambda 来创建匿名函数。

lambda只是一个表达式,函数体比def简单很多。
lambda的主体是一个表达式,而不是一个代码块。仅仅能在lambda表达式中封装有限的逻辑进去。
lambda函数拥有自己的命名空间,且不能访问自有参数列表之外或全局命名空间里的参数。
虽然lambda函数看起来只能写一行,却不等同于C或C++的内联函数,后者的目的是调用小函数时不占用栈内存从而增加运行效率。

ambda函数的语法只包含一个语句,如下:

lambda [arg1 [,arg2,.....argn]]:expression
#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 可写函数说明
sum = lambda arg1, arg2: arg1 + arg2;
# 调用sum函数
print "相加后的值为 : ", sum( 10, 20 )
print "相加后的值为 : ", sum( 20, 20 )

5、嵌套函数

 在一个函数中定义了另外一个函数

#coding=utf-8
def outer():
    def inner():
        print('inner')
        print('outer')
    inner()
outer()

inner()    # 此句会出错,内部函数不能被外部直接使用,会抛NameError异常)
#函数有可见范围,这就是作用域的概念

 6、递归

递归调用是函数嵌套调用的一种特殊形式,如果一个函数在内部直接或间接调用自身,这个函数就是递归函数。

'''
场景:用10不断除以2,直到除不尽为止,打印每次结果。
思路:
# 10/2=5
# 5/2=2.5
# 2.5/2=1.25
# ...
'''

#用while循环实现:
n = 10
while True:
    n = int(n/2)
    print(n)
    if n == 0:
        break
''' 
#输出
5
2
1
0
'''

#非递归方式实现:
def calc(n):
    n = int(n/2)
    return n
 
r1 = calc(10)
r2 = calc(r1)
r3 = calc(r2)
r4 = calc(r3)
print(r1)
print(r2)
print(r3)
print(r4)

''' 
#输出
5
2
1
0
'''

#用递归实现:
def calc(n):
    print(n)
    if int(n/2) == 0:  #结束符
        return n
    return calc(int(n/2))  #调用函数自身
  
m = calc(10)
print('----->',m)

'''  
#输出
10
5
2
1
-----> 1 #最后返回的值
'''

#来看实现过程,我改了下代码
def calc(n):
    v = int(n/2)
    print(v)
    if v > 0:
        calc(v)
    print(n)
 
calc(10)

'''
#输出
5
2
1
0
1
2
5
10
'''

#递归层数:
import sys
print(sys.getrecursionlimit()) # 默认递归限制层数
sys.setrecursionlimit(1500) # 修改递归层数

#尾递归优化:
#调用下一层时候退出。(解决栈溢出的问题,每次只保留当前递归的数据),在C语音里有用,Python中没用
def recursion(n):
    print(n)
    return recursion(n+1)
recursion(1)

'''
递归特性:
(1)递归就是在过程或者函数里调用自身
(2)在使用递归策略时,必须有一个明确的结束条件,称为递归出口
(3)每次进入更深一层递归时,问题规模相比上次递归都应有所减少(问题规模:比如你第1次传进的是10,第2次递归应该是9...依次越来越少,不能越来越多)。
(4)递归算法解题通常显得很简洁,但递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出),所以一般不倡导使用递归算法设计程序。
'''
递归分析

递归算法一般用于解决三类问题:
(1)数据的定义是按递归定义的。(比如Fibonacci函数)
(2)问题解法按递归算法实现。(回溯)
(3)数据的结构形式是按递归定义的。(比如树的遍历,图的搜索,二分法查找等)

堆栈扫盲:http://www.cnblogs.com/lln7777/archive/2012/03/14/2396164.html

posted @ 2019-04-04 14:51  Einewhaw  阅读(161)  评论(0编辑  收藏  举报