< 返回索引页html
<!-- /TOC -->数组
在维基百科上函数式这样描述的:数据结构
函数在数学中为两集合间的一种对应关系:输入值集合中的每项元素皆能对应惟一一项输出值集合中的元素。
此处的函数区别于咱们数学上的函数,在编程世界中,函数(Functions)是指可重复使用的程序片断。它们容许你为某个代码块赋予名字,容许你
经过这一特殊的名字在你的程序任何地方来运行代码块,并可重复任何次数。这就是所谓的调用函数。咱们已经使用过了许多内置的函数,例如 len
和 range
。闭包
基本结构以下:app
def 函数名(参数列表): " 函数说明 " 函数体
在Python中,使用关键字def
来定义一个函数。结构以下:函数
def hello(name): " 返回字符串" return name def hello2(): pass
语法说明:学习
hello.__doc__
获取pass
来定义个空函数下面来展开一一讲述。
函数中返回值,使用关键字return
来表示,返回值能够是任意类型,当没有return
语句时函数返回None。函数返回值支持多个,返回多个时,使用逗号分隔。以下:
def say_hello(name): print(name) return 'Hello, %s' % name, name
函数的调用,上边咱们已经使用了不少次了,函数名加上须要传入的响应参数便可。这里须要注意的是,在python中,一切结尾对象,固然函数也是对象。函数名也能够做为参数传递到函数中使用。
def say_hello(name): print('hello, %s' % name) def wapper(fun): print('调用以前作一些事') fun('Dean') print('调用以后作一些事') wapper(say_hello) """ 调用以前作一些事 hello, Dean 调用以后作一些事 """
在程序设计中函数参数有2个比较通用的概念,形参和实参,在各高级语言中都会有。形参,即形式上的参数,不占用内存空间。实参,是实际真正的参数。
看下面这个实例:
def say_hello(name): print('hello, %s' % name ) say_hello('Dean')
其中,函数参数name
即为函数的形参。咱们调用函数时,传入的参数Dean
即是实参。在Python编程时,这个概念并非那么重要,此种了解便可。
在Python 函数中,多个参数按照必定的顺序依次传入函数,其值依次对应赋给函数声明时参数,这种参数叫顺序参数
。
def say_hello(name, age): print('hello, %s' % name) print('you age: %s ' % age) say_hello('Dean', 30)
如上,Dean
与30 这2个参数按照由左到右依次赋值给形参name
和age
供函数内部使用。须要注意的是,顺序参数中,形参和实参的个数须要一直,不然函数会报调用错误。
在函数声明时,能够给参数设置默认值,以下:
def say_hello(name='Tim', age=20): print('hello, %s' % name) print('you age: %s ' % age) say_hello('Dean', 30) say_hello('Dean')
当函数参数设置默认值后,该参数在调用函数时,能够省略,省略时则会使用默认值。有此能够退出,参数没有设置默认值,则是必传的。
有时候咱们在声明函数时,无法肯定函数的参数个数,或者咱们自己就想设计一种动态的参数,这种设计是否能够知足呢?Python的函数对这种状况已作了考虑,提供了可变参数
来知足这种需求。
def say_hello(*args): print(args) for name in args: print('hello, %s' % name) say_hello('Dean','Tim') ('Dean', 'Tim') hello, Dean hello, Tim
可变参数使用*
加一个形参来表示,其值为一个元组类型,元组内的元素为咱们传入的实参。
在可变参数中,咱们传入函数的参数只能按顺序或着经过下标来获取,那么可不能够给参数起一个名字呢,答案是能够的。Python 为这种状况提供了一种参数形式,叫作关键字参数
。
def say_hello(**kwargs): print('hello, %s' % kwargs['name']) print('you age: %s' % kwargs['age']) say_hello(name='Dean', age=30)
使用**
加一个形参来表示,其值为一个字典,key为咱们实参中传入的变量,value值为实参中的变量的值。
Python 函数中,以上参数可组合使用。当参数组合使用时,须要注意如下原则:
参数的经常使用排列顺序为,无默认值顺序参数、有默认值顺序参数、可变参数、关键字参数。
def say_hello(name, age=30, *args, **kwargs): print(args) print(kwargs) print('hello, %s' % name) print('you age: %s' % age) print('address: %s' % kwargs['address']) say_hello('Dean', 20, address='Beijing')
咱们在调用函数时,将实参传递给了函数的形参,供函数中逻辑代码使用。那么在这个过程当中,计算机内存是一个怎么的过程呢?咱们在学习变量时知道,Python中的变量是其内部存储值的一个内存地址或者叫作一个引用。在传入函数时,即是将这个引用传入了函数。那么咱们在函数内部修改变量的值时,是否是就修改了外部的变量的值呢?答案是不必定。
在咱们学习基本数据结构时,咱们知道有可变类型(字典、列表、集合)和不可变类型(数值、字符串、元组)。当咱们传入函数的参数为可变类型时,函数中的形参使用的内存地址同实参的内存地址,当改变形参的值时,实参的值也相应跟着修改了。当咱们传入的为不可变量时,形参会从新分配一块内存地址保存实参传给他的值,当形参修改时,实参天然不会修改。
来看下边的例子:
# func.py def say_hello1(name): '不可变类型参数' name = 'Time' print('name: %s' % name ) def say_hello2(user_dict): '可变类型参数' user_dict['name'] ='Time' print('name: %s' % user_dict['name']) name = 'Dean' print('name before:', name) say_hello1(name) print('name after:', name) user_dict = {'name':'Dean'} print('user_dict before:', user_dict) say_hello2(user_dict) print('user_dict after:', user_dict) """ # 不可变参数,值没有变 ('name before:', 'Dean') name: Time ('name after:', 'Dean') # 可变参数,值变了 ('user_dict before:', {'name': 'Dean'}) name: Time ('user_dict after:', {'name': 'Time'}) """
在第三章,咱们学习变量时,知道变量的做用域决定了在哪一部分程序能够访问哪一个特定的变量名称。在Python中,函数会从新开启一个做用域,当在函数内部定义的变量,在函数外部是没法访问的。那么该变量即是函数的局部变量
,函数外部的变量即可成为全局变量
。
total = 0 # 这是一个全局变量 # 可写函数说明 def sum( arg1, arg2 ): #返回2个参数的和. total = arg1 + arg2 # total在这里是局部变量. print ("函数内是局部变量 : ", total) return total #调用sum函数 sum( 10, 20 ) print ("函数外是全局变量 : ", total)
那么当内部的局部变量想要暴露出来给外部使用时如何实现呢?Python提供了2个关键字,gobal
和 nonlocal
。
global
将变量做用域变为函数外层全局做用域。
num = 1 def fun1(): global num # 须要使用 global 关键字声明 print(num) num = 123 print(num) fun1()
nonlocal
将变量做用域变为函数外部非全局变量,及闭包(Enclosing)做用域。
def outer(): num = 10 def inner(): nonlocal num # nonlocal关键字声明 num = 100 print(num) inner() print(num) outer()
内建函数,是Python中已经定义好的函数能够在编写代码时直接使用。咱们已经使用过内建函数,如len
、range
等。更多的内建函数,可参阅官方文档中函数说明。
匿名函数,就是不使用def
来定义的函数。Python中使用关键字lambda
来实现匿名函数。
# 语法 lambda [arg1 [,arg2,.....argn]]:表达式
语法说明:
arg
为参数,能够任意多个,使用逗号分隔表达式
为函数体,使用冒号开头表达式
的返回值即为函数的返回值实例:
# 内名函数 sum = lambda arg1, arg2: arg1 + arg2 # 调用sum函数 print ("相加后的值为 : ", sum( 10, 20 )) print ("相加后的值为 : ", sum( 20, 20 ))
函数注解,为函数和参数增长了一些说明特性。python3.0 新增的特性,见PEP3107。可经过函数的__annotations__
熟悉查看。
def f(ham: 42, eggs: int = 'spam') -> "Nothing to see here": print("Annotations:", f.__annotations__) print("Arguments:", ham, eggs) f('wonderful') ''' Annotations: {'eggs': <class 'int'>, 'return': 'Nothing to see here', 'ham': 42} Arguments: wonderful spam ''' def foo(a: 'x', b: 5 + 6, c: list) -> max(2, 9): pass
语法说明:
在Python的编程时,注解使用的比较少,以方便人们更多的使用docstring来讲明参数及返回值,另外一方面Python函数参数可进一步经过编码规范一眼就能看出什么类型。这种注释语法,反而显得啰嗦冗余。
本章咱们学习了函数及其使用,知识重点总结以下:
lambda
来实现匿名函数。def factorial(num): """ 求阶乘 :param num: 非负整数 :return: num的阶乘 """ result = 1 for n in range(1, num + 1): result *= n return result n = int(input('n = ')) factorial(n)
# 素数,在大于1的天然数中,除了1和它自己之外再也不有其余因数 def is_prime(num): for factor in range(2, num): if num % factor == 0: return False return True if num != 1 else False