python3之函数

开始认知

Posted by WEW on April 11, 2019

函数

函数是用来完成可组织的,重复功能或相关联的单一功能的代码段,它可以提高应用的模块化,提高代码的可在用性 减少代码的重复率。

函数定义

def 函数名(参数):
    函数体
    
    return 表达式  #该条语句可以没有

参数

函数可使用的正式参数有以下四种类型:

1.必需参数

2.关键字参数

3.默认参数

4.不定长参数

必需参数

必需参数要求必须和函数声明的顺序保持严格一致,否则会引发异常

关键字参数

关键字参数与函数的调用紧密相关,它使得在函数调用时,具体的参数顺序可以和声明的函数参数顺序不一致,因为 python中可以按照关键字自动匹配相关参数

#!/usr/bin/python3
def printinfo( name, age ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
#调用printinfo函数
printinfo( age=50, name="runoob" )
    
名字:  runoob
年龄:  50

默认参数

def printinfo( name, age = 35 ):
   "打印任何传入的字符串"
   print ("名字: ", name)
   print ("年龄: ", age)
   return
    
#调用printinfo函数
printinfo( age=50, name="runoob" )
print ("------------------------")
printinfo( name="runoob" )
    
名字:  runoob
年龄:  50
------------------------
名字:  runoob
年龄:  35

不定长参数

python3中你可以调用比函数声明时多的额外的参数,那些为定义的参数会统一以元组的形式存储在*号开头的参数中

def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print ("输出: ")
   print (arg1)
   print (vartuple)
 
# 调用printinfo 函数
printinfo( 70, 60, 50 )
    
输出: 
70
(60, 50)

还有一种是带两个的参数,那些未定义的参数会以字典的形式存储在开头的参数中

def printinfo( arg1, **vardict ):
   "打印任何传入的参数"
   print ("输出: ")
   print (arg1)
   print (vardict)
 
# 调用printinfo 函数
printinfo(1, a=2,b=3)
输出: 
1
{'a': 2, 'b': 3}

值得注意的是,声明函数时 号可以单独出现,但是号后面的参数必须以关键字参数传入

>>> def f(a,b,*,c):
...     return a+b+c
... 
>>> f(1,2,3)   # 报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 2 positional arguments but 3 were given
>>> f(1,2,c=3) # 正常
6

参数传递

函数传递参数的方式和参数本身是可变类型还是不可变类型有关,如果参数为数字、元组、字符串,则触发值传递,如果参数为 可变类型如列表,字典等,则发生引用传递

匿名函数

python3允许匿名函数的存在,顾名思义,这样的函数不在使用def关键字进行明显声明,而是使用lambda进行声明,它的定义有点类似于C++的宏定义

sum = lambda arg1, arg2: arg1 + arg2
# 调用sum函数
print ("相加后的值为 : ", sum( 10, 20 ))
print ("相加后的值为 : ", sum( 20, 20 ))
    
相加后的值为 :  30
相加后的值为 :  40

变量作用域

python3中并不是那个变量在任何位置都可以访问的,访问权限决定于这个变量在哪里赋值的,变量的作用域决定了那一段程序段可以访问哪些变量,python中 变量的作用域一共分为四种:

1.L (local) 局部作用域

2.E (Enclosing)闭包函数外的函数中

3.G (global)全局作用域

4.B (built-in)内置作用域 (一般值模块内)

Python 中只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如 if/elif/else/、try/except、for/while等)是不会引入新的作用域的,也就是说这些语句内定义的变量,外部也可以访问,如下代码:

>>> if True:
...  msg = 'I am from Runoob'
... 
>>> msg
'I am from Runoob'
>>> 

msg在if语句内定义的但是在外部依然可以访问到

>>> def test():
...     msg_inner = 'I am from Runoob'
... 
>>> msg_inner
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'msg_inner' is not defined

msg定义在函数内,则不能访问

局部变量和全局变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域,局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。 调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
    #返回2个参数的和."
    total = arg1 + arg2 # total在这里是局部变量.
    print ("函数内是局部变量 : ", total)
    return total
 
#调用sum函数
sum( 10, 20 )
print ("函数外是全局变量 : ", total)
    
函数内是局部变量 :  30
函数外是全局变量 :  0

global 和 nonlocal关键字

当内部作用域想修改外部作用域的变量时,就要用到global和nonlocal关键字了。

num = 1
def fun1():
    global num  # 需要使用 global 关键字声明
    print(num) 
    num = 123
    print(num)
fun1()
print(num)
    
1
123
123

如果要修改嵌套作用域(enclosing 作用域,外层非全局作用域)中的变量则需要 nonlocal 关键字了,如下实例:

def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()
    
100
100