标签:
函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段。
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内置函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。
如
def fun(形参): "内容" return True fun(实参)
定义函数时,申明的是形式参数简称形参,调用函数时,传递的参数是实际参数简称实参。而形参又可以分为四种
必备参数须以正确的顺序传入函数。调用时的数量必须和声明时的一样
def f1(a): print("OK") f1() def f2(a,b) print(a+b) f2(3+4)
返回结果:OK和7
注:调用必备参数时,必须实参和形参位置对应,否则会报错。
关键字参数和函数调用关系紧密,函数调用使用关键字参数来确定传入的参数值。
使用关键字参数允许函数调用时参数的顺序与声明时不一致,因为 Python 解释器能够用参数名匹配参数值。
def info(name,age): print("Name %s"%name) print("Age %s"%age) info("flash",18) info("aa",19)
输出结果
Name flash Age 18 Name aa Age 19
调用函数时,缺省参数的值如果没有传入,则被认为是默认值。
def info(name,age,sex="male"): print("Name %s"%name) print("Age %s"%age) print("Sex %s"%sex) info("flash",18) info("aa",19,sex="female")
输出结果对比
Name flash Age 18 Sex male Name aa Age 19 Sex female
你可能需要一个函数能处理比当初声明时更多的参数。这些参数叫做不定长参数(又称动态参数),和上述2种参数不同,声明时不会命名。一种是无名名字参数,另一种是有命名参数。
无命名参数(输出的是元组) def add(*args): sum = 0 for i in args: sum += i print(sum) add(1,2,3,4,5) 有命名参数(输出的是字典) def fun(**kwargs): for i in kwargs: print("%s:%s"%(i,kwargs[i])) fun(name="flash",age=22)
定义一个函数只给了函数一个名称,指定了函数里包含的参数,和代码块结构。
这个函数的基本结构完成以后,你可以通过另一个函数调用执行,也可以直接从Python提示符执行。
最简单的例子
def fun(): print("OK") fun()
return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的return语句返回None。
一个程序的所有的变量并不是在哪个位置都可以访问的。访问权限决定于这个变量是在哪里赋值的。变量的作用域决定了在哪一部分程序你可以访问哪个特定的变量名称。
大致可以分为四种情况
total = 0; # 这是一个全局变量 # 可写函数说明 def sum( arg1, arg2 ): #返回2个参数的和." total = arg1 + arg2; # total在这里是局部变量. print "函数内是局部变量 : ", total return total; #调用sum函数 sum( 10, 20 ); print "函数外是全局变量 : ", total
特性
递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
举个简单例子,求5的阶乘
def f(i): if i == 1: return 1 return i * f(i-1) print(f(5))
小结
高阶函数英文叫Higher-order function。
变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。
举个例子如
def f(n): return n *n def f1(a,b,f): set = f(a) + f(b) return set print(f1(1,2,f))
返回值为 5
什么是闭包函数,看一个简单的例子
def foo(): x = 5 def func(): print(x) return func foo()()
#返回值是5
我们会想,x = 5是属于foo函数的局部变量,为什么可以调用?这就是闭包的闭包的特性。
定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。
所以对上述例子中,func()就是闭包函数。
通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]
改成()
,就创建了一个generator:
L = [x * x for x in range(10)]#list g = (x * x for x in range(10))#生成器
生成器保存的是算法,如果调用元素中的只,最好的办法就是使用for循环,因为生成器也是一个可迭代的对象。
g = (x * x for x in range(10)) for n in g: print(n)
如果算法过去复杂庞大,我们可以使用函数调用来实现。比如斐波那契数列
def fib(max): n, a, b = 0, 0, 1 while n < max-1: #print(b)
yield b a, b = b, a + b n = n + 1 return fib(6)
#这就是定义generator的另一种方法。如果一个函数定义中包含yield
关键字,那么这个函数就不再是一个普通函数,而是一个generator:
我们已经知道,可以直接作用于for
循环的数据类型有以下几种:
list
、tuple
、dict
、set
、str
等。generator
,包括生成器和带yield
的generator function。这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
如何去判断一个对象是不是一个可迭代的对象,可以使用内置函数进行判断
>>>from collections import Iterable >>> isinstance([], Iterable) True #如果是返回True,否返回False
注:
for
循环的对象都是Iterable
类型;next()
函数的对象都是Iterator
类型,它们表示一个惰性计算的序列;list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象。这里我们也许会问,都已经是可迭代的了,为什么还不是Iterator?这是因为Python的Iterator
对象表示的是一个数据流,Iterator对象可以被next()
函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration
错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()
函数实现按需计算下一个数据,所以Iterator
的计算是惰性的,只有在需要返回下一个数据时它才会计算。
Iterator
甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
什么是装饰器?
装饰器本质上是一个函数,该函数用来处理其他函数,它可以让其他函数在不需要修改代码的前提下增加额外的功能,装饰器的返回值也是一个函数对象。本质就是将原函数封装到另外一个函数里面,让其等于一个新函数,在执行新函数的内容。
首先举个简单的例子,在我们事先写好的许多函数中,如果我们想要添加一个新的功能,不可能往每个函数写一遍,这是一个不明智的做法。这里我们就会用到装饰器。例如
def f1(fd): def f(): print("OK") fd() print("OK") # return r return f @f1 def f2(): print("F2") f2()
这是一个最简单的装饰器。其中@符号是python中表示装饰器的语法。
当然装饰器还可以指定参数去更方便的执行例如
import time def logger(flag = "True"): def show_time(f): def func(): start = time.time() f() end = time.time() if flag =="True": print("打印日志") print(end - start) return func return show_time @logger("true") def foo1(): print("OK!!!!!!!!!!!!!") time.sleep(1) foo1() def foo2(): print("OK!!!!!!!!!!!!!") time.sleep(2) foo2()
也可以传入不定长参数做简单的计算
import time def show_time(f): def func(*args,**kwargs): start = time.time() f(*args,**kwargs) end = time.time() print(end - start) return func @show_time def foo1(*args,**kwargs): Sum = 0 for i in args: Sum += i print(Sum) time.sleep(1) foo1(1,2,3)
小结:
在面向对象(OOP)的设计模式中,decorator被称为装饰模式。OOP的装饰模式需要通过继承和组合来实现,而Python除了能支持OOP的decorator外,直接从语法层次支持decorator。Python的decorator可以用函数实现,也可以用类实现。
标签:
原文地址:http://www.cnblogs.com/flash55/p/5843996.html