python中的函数、变量和递归函数

一、函数的定义

        初中数学函数定义:一般的,在一个变化过程中,如果有两个变量x和y,并且对于x的每一个确定的值,y都有唯一确定的值与其对应,那么我们就把x称为自变量,把y称为因变量,y是x的函数。自变量x的取值范围叫做这个函数的定义域

例如y=2*x

python中函数定义:函数是逻辑结构化和过程化的一种编程方法。

 1 python中函数定义方法:
 2  
 3 def test(x):
 4     "The function definitions"
 5     x+=1
 6     return x
 7      
 8 def:定义函数的关键字
 9 test:函数名
10 ():内可定义形参
11 "":文档描述(非必要,但是强烈建议为你的函数添加描述信息)
12 x+=1:泛指代码块或程序处理逻辑
13 return:定义返回值
14 
15 
16 调用运行:可以带参数也可以不带,根据定义时括号内是否有参数来决定
17 函数名()

例:

#定义函数
def test(x):
    y = 2 * x + 1
    return y

#调用函数
print(test)
test(3)         ##调用函数但是return的值没有接收,返回的是test函数的内存地址
a = test(2)     ##使用变量a接收函数的返回值
print(a)

输出:

注意:当函数出现重名时,调用时后边的函数会覆盖掉之前的函数,因为python语言从上到下依次解释执行

           return 不能出现多个,代码执行时碰到第一个return就会结束

例:

#定义函数
def test(x):
    y = 2 * x + 1
    return y

def test( ):
    x = 2
    y = x + 1
    return y

#调用函数
a = test()     
#b = test(2)    ##会报错
print(a)

 

二、为什么要有函数

通过下面实现同一功能的两块代码对比,就可以看出在某些合适的生产场景下使用函数的好处:

代码1:
 while True:
      if cpu利用率 > 90%:
          #发送邮件提醒
          连接邮箱服务器
          发送邮件
          关闭连接
       
      if 硬盘使用空间 > 90%:
          #发送邮件提醒
          连接邮箱服务器
          发送邮件
          关闭连接
      
      if 内存占用 > 80%:
          #发送邮件提醒
          连接邮箱服务器
          发送邮件
          关闭连接

代码2:
def 发送邮件(内容)
    #发送邮件提醒
    连接邮箱服务器
    发送邮件
    关闭连接
     
while True:
     
    if cpu利用率 > 90%:
        发送邮件('CPU报警')
     
    if 硬盘使用空间 > 90%:
        发送邮件('硬盘报警')
     
    if 内存占用 > 80%:
        发送邮件('内存报警')

 使用函数的好处

1.代码重用(减少冗余,提高代码的有效性)

2.保持一致性,易维护

3.可扩展性

 

三、函数和过程

过程定义:过程就是简单特殊没有返回值的函数,即没有return,返回值为None

这么看来我们在讨论为何使用函数的的时候引入的函数,都没有返回值,没有返回值就是过程,没错,但是在python中有比较神奇的事情

 

# 无返回值,为过程
def test01():
    msg = 'hello The little green frog'
    print(msg)


# 有返回值,为函数
def test02():
    msg = 'hello WuDaLang'
    print(msg)
    return msg


t1 = test01()

t2 = test02()

print ('from test01 return is %s' %t1)    ##返回值为None
print ('from test02 return is %s' %t2)

输出:

总结:当一个函数/过程没有使用return显示的定义返回值时,python解释器会隐式的返回None,

所以在python中即便是过程也可以算作函数。

def test01():
    pass
def test02():
    return 0

def test03():
    return 0,10,'hello',['alex','lb'],{'WuDaLang':'lb'}

t1=test01()
t2=test02()
t3=test03()


print('from test01 return is [%s]: ' %type(t1),t1)
print('from test02 return is [%s]: ' %type(t2),t2)
print('from test03 return is [%s]: ' %type(t3),t3)    ##当返回值为多个时,会将这几个值组成一个元组返回

输出:

总结:

   返回值数=0:返回None

   返回值数=1:返回object

   返回值数>1:返回tuple

 

四、函数中的参数

1.形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元,也就是说形参不占用内存空间(变量亦是如此,不会占用内存空间,只有真正的数据类型才会占用内存空间)。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量

2.实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值

 

3.位置参数和关键字(标准调用:实参与形参位置一一对应;关键字调用:位置无需固定)

  • 位置参数(必须一一对应)
def test(x,y,z):
    print(x)
    print(y)
    print(z)

test(1,2)   ##x=1,y=2,没有给z赋值,会报错

输出:

  • 关键字参数(位置不用固定,但是个数不能少)
def test(x,y,z):
    print(x)
    print(y)
    print(z)

test(y=1,z=2,x=5)

输出:

  • 位置参数与关键字参数的混合使用(位置参数必须在关键字参数的左边)
def test(x,y,z):
    print(x)
    print(y)
    print(z)

# test(3,y=5,8)   ##会报错
# test(3,5,8,y=4) ##也会报错,因为不可以重复赋值给某一形参
# test(3,8,y=5) ##也会报错,执行时默认将3赋值给x,将8赋值给y test(3,8,z=5) ##正常执行

4.默认参数

 默认参数:在调用时如果不给它赋值则它等于默认值,默认值可以为任何类型的值

def handle(x,y=None):
    print(x,type(x))
    print(y)

handle('12ed')       ##不给默认参数赋值的时候,默认参数等于默认值
handle(2,'hello')

输出:

5.参数组

非固定长度的参数(后期可以扩展):

    *      列表、元组

   **     字典

  • 列表、元组
def test(x,*args):      ##*代表非固定长度的参数值
    print(x)
    print(args)
    # print(args[1])       ##输出为空元组

test(1,12,4,5,'ds')       ##将第一个实参传给第一个形参,后边所有的实参组合成元组传给第二个形参,该例子中实参可以为任意数据类型
test(1)                   ##不给第二个形参传值也可以,但需取掉函数中的print(args[1]),否则会报错
test(1,['1',23,2,2])
test(1,*['x',12,'q21'])  ##*表示将该列表中的元素遍历,第一种调用函数的方法类似,元组也是如此

输出:

  • 字典
def test(x,**kwargs):
    print(x)
    print(kwargs)

test(1,y=2,z=3)    ##将第一个实参后的所有实参组合成一个字典赋值给第二个形参,注意只能使用key=value的形式赋值

#三个混合使用时,只能使用下面的顺序
# def test1(x,*args,**kwargs):

 

 五、局部变量与全局变量

    在子程序中定义的变量称为局部变量,在程序的一开始定义的变量称为全局变量。

    全局变量作用域是整个程序,局部变量作用域是定义该变量的子程序。
    当全局变量与局部变量同名时:
    在定义局部变量的子程序内,局部变量起作用;在其它地方全局变量起作用。
name = 'lee'    ##全局变量:顶格写,全局生效

##局部变量:在子程序中定义的变量,在该子程序之外的部分不生效,例如def自定义函数中
def  change_name():
    first_name = 'hello'
    # print('my name:',name)    ##全局变量在子程序中也生效,但是当在子函数中如果对该变量重新赋值时,调用该变量的代码块只能出现在其后,否则会报错
    print(first_name)
    name = 'mike'
    print(name)

change_name()   ##调用函数时,如果使用了变量,执行时会默认先在函数内层(即局部变量)找,如果没有再在外部(即全局变量)找
print(name)     ##局部变量无效,只有全局变量生效

 输出:

name = 'lee'    ##全局变量:顶格写,全局生效

##局部变量:在子程序中定义的变量,在该子程序之外的部分不生效,例如def自定义函数中
def  change_name():
    global name      ##将全局变量引入函数内部,在函数内如果重新定义变量的话就是改变的全局变量,注意如果使用global并且重新对变量赋值,则在函数内global之前不能调用全局变量
    name = 'mike' 
    print(name)

change_name()
print(name)  ##局部变量无效,只有全局变量生效

注意:如果函数中没有对变量重新赋值(即指定与全局变量名称相同的局部变量),但局部变量是可变对象(如列表等),可以在函数中直接使用该可变对象的内置方法(如列表的.append方法)

输出:

 

 

 

posted @ 2019-01-31 22:49  Forever_lee  阅读(811)  评论(0编辑  收藏  举报