Python3 函数

定义:

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。

目的:

函数能提高应用的模块性,和代码的重复利用率。

分类:

内建函数、自定义函数。

你已经知道Python提供了许多内建函数,比如print()。

但你也可以自己创建函数,这被叫做用户自定义函数。

举例:

#!/usr/bin/python3

# 计算面积函数(自定义)
def area(width, height):
    return width * height
# 打印问候(自定义) def print_welcome(name): print("Welcome", name)
print_welcome(
"Runoob") w = 4 h = 5 # 打印(内建函数) print("width =", w, " height =", h, " area =", area(w, h))

参数传递

在 python 中,类型属于对象,变量是没有类型的:

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

以上实例输出结果:

名字:  runoob
年龄:  50

默认参数

调用函数时,如果没有传递参数,则会使用默认参数。以下实例中如果没有传入 age 参数,则使用默认值:

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

输出结果:

名字:  runoob
年龄:  50
------------------------
名字:  runoob
年龄:  35

不定长参数

你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数,和上述2种参数不同,声明时不会命名。基本语法如下

加了星号(*)的变量名会存放所有未命名的变量参数。如果在函数调用时没有指定参数,它就是一个空元组。我们也可以不向函数传递未命名的变量。如下实例:

#!/usr/bin/python3
 
# 可写函数说明
def printinfo( arg1, *vartuple ):
   "打印任何传入的参数"
   print ("输出: ")
   print (arg1)
   for var in vartuple:
      print (var)
   return;
 
# 调用printinfo 函数
printinfo( 10 );
printinfo( 70, 60, 50 );
以上实例输出结果:

输出:
10
输出:
70
60
50

变量作用域

Python 中,程序的变量并不是在哪个位置都可以访问的,访问权限决定于这个变量是在哪里赋值的。

变量的作用域决定了在哪一部分程序可以访问哪个特定的变量名称。Python的作用域一共有4种,分别是:

  • L (Local) 局部作用域
  • E (Enclosing) 闭包函数外的函数中
  • G (Global) 全局作用域
  • B (Built-in) 内建作用域

以 L –> E –> G –>B 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

x = int(2.9)  # 内建作用域 B
 
g_count = 0  # 全局作用域 G
def outer():
    o_count = 1  # 闭包函数外的函数中 E
    def inner():
        i_count = 2  # 局部作用域 L

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 语句块中,但外部还是可以访问的。

如果将 msg 定义在函数中,则它就是局部变量,外部不能访问:

>>> 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_inner 未定义,无法使用,因为它是局部变量,只有在函数内可以使用。 

全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

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

#!/usr/bin/python3

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

#调用sum函数 
sum( 10, 20 );

print ("函数外是全局变量 : ", total)
print ("函数外是全局变量2 : ", total2)

以上实例输出结果:

函数内是局部变量 :  30
函数外是全局变量 :  0
函数外是全局变量2 :  30
 

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

#!/usr/bin/python3
 
def outer():
    num = 10
    def inner():
        nonlocal num   # nonlocal关键字声明
        num = 100
        print(num)
    inner()
    print(num)
outer()

以上实例输出结果:

100
100

另外有一种特殊情况,假设下面这段代码被运行:

#!/usr/bin/python3
 
a = 10
def test():
    a = a + 1
    print(a)
test()

以上程序执行,报错信息如下:

Traceback (most recent call last):
  File "test.py", line 7, in <module>
    test()
  File "test.py", line 5, in test
    a = a + 1
UnboundLocalError: local variable 'a' referenced before assignment

错误信息为局部作用域引用错误,因为 test 函数中的 a 使用的是局部,未定义,无法修改。

其他实际问题:

1、默认参数必须放在最后面,否则会报:

SyntaxError: non-default argument follows default argument
# 可写函数说明
def printinfo( age=35,name):   # 默认参数不在最后,会报错
    "打印任何传入的字符串"
    print("名字: ", name);
    print("年龄: ", age);
    return;

2、把N个关键字参数转化为字典:

>>> def func(country,province,**kwargs):
...     print(country,province,kwargs)
... 
>>> func("China","Sichuan",city = "Chengdu", section = "JingJiang")
China Sichuan {'city': 'Chengdu', 'section': 'JingJiang'}
>>> 

3、匿名函数也是可以使用"关键字参数"进行参数传递:

>>> g= lambda x,y : x**2+y**2
>>> g(2,3)
13
>>> g(y=3,x=2)
13

lambda 匿名函数也可以设定默认值

>>> g= lambda x=0,y=0 : x**2+y**2
>>> g(2,3)
13
>>> g(2)
4
>>> g(y=3)
9

4、对于变量作用域,变量的访问以 L(Local) –> E(Enclosing) –> G(Global) –>B(Built-in) 的规则查找,即:在局部找不到,便会去局部外的局部找(例如闭包),再找不到就会去全局找,再者去内建中找。

观察以下几个例子,均从内部函数输出变量 x:

1. 局部作用域

x = int(3.3)

x = 0
def outer():
    x = 1
    def inner():
        x = 2
        print(x)
    inner()

outer()

执行结果为 2,因为此时直接在函数 inner 内部找到了变量 x。

2.闭包函数外的函数中

x = int(3.3)

x = 0
def outer():
    x = 1
    def inner():
        i = 2
        print(x)
    inner()

outer()

执行结果为 1,因为在内部函数 inner 中找不到变量 x,继续去局部外的局部——函数 outer 中找,这时找到了,输出 1。

3.全局作用域

x = int(3.3)
x = 0
def outer():
    o = 1
    def inner():
        i = 2
        print(x)
    inner()

outer()

执行结果为 0,在局部(inner函数)、局部的局部(outer函数)都没找到变量 x,于是访问全局变量,此时找到了并输出。

4. 内建作用域

x = int(3.3)
g = 0
def outer():
    o = 1
    def inner():
        i = 2
        print(x)
    inner()

outer()

5、函数也可以以一个函数为其参数:

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

def execute(f):
  "执行一个没有参数的函数"
  f()

execute(hello)
输出:
Hello, world!

结束!

原文地址:https://www.cnblogs.com/huangsxj/p/8632558.html