自学python系列10:python的函数和函数式编程
1.1什么是函数
函数是对程序逻辑进行结构化或过程化的编程方法。这样能节省空间,有助于保持一致性。
函数的创建,使用,引用方法:
def foo():print 'bar'
foo
foo()
1.1.1函数vs过程
函数是布尔类型的,返回一个“是”或“否”的回答。一个非零或者零值。python的过程是函数,因为解释器会隐式返回默认值None。
1.1.2返回值和函数类型
不返回任何东西。在C中默认为"void"返回类型,在python中该值为none
>>> def hello():
print 'hello world'
print 'hello world'
>>> a=hello()
hello world
>>> print a
None
hello world
>>> print a
None
1.2调用函数
1.2.1函数操作符
用圆括号调用函数。
1.2.2关键字参数
关键字参数的概念对函数的调用。
def foo(x):
标准调用foo(): foo(42) foo('2')
关键字调用foo(): foo(x=42)
例子:
>>> def foo(x,y):
a
a
>>> foo(1,2)
1.2.3默认参数
默认参数是声明了默认值的参数。
1.2.4参数组
1.3创建函数
1.3.1def语句
def function_name(arguments):
"function_documentation_string"
function_boby_suite
例子:
def hello(who):
'something'
return str(who)
1.3.2声明与定义的比较
在某些编程语言里,函数声明和定义区分开。一个函数声明包括提供对函数名,参数的名字,但不必给出函数的任何代码,具体的代码通常属于函数定义的范畴。
1.3.3前向引用
python不允许在函数未声明之前,对其进行引用或者调用。
>>> def foo():
print 'in foo()'
bar()
bar()还没有申明
>>> foo()
in foo()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
foo()
File "<pyshell#3>", line 3, in foo
bar()
NameError: global name 'bar' is not defined
print 'in foo()'
bar()
bar()还没有申明
>>> foo()
in foo()
Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
foo()
File "<pyshell#3>", line 3, in foo
bar()
NameError: global name 'bar' is not defined
前向引用:
定义函数a,在函数b之前给出函数a的声明
>>> def a():
print'a'
>>> def b():
print'b'
a()
>>> b()
b
a
1.3.4函数属性
第一个特征:可获得每个python模块,类和函数的任意的名称空间。可在foo和bar里都有名为x的一个变量。
即使在两个模块使用了相同的变量名字,也安全。因为句点属性标识对于两个模块意味着不同的命名空间
import foo,bar:
print foo.x,bar.x
python的文档字串,以及属性
>>> def foo():
'a'
>>> def bar():
pass
>>> bar.__doc__
>>> help(foo)
Help on function foo in module __main__:
foo()
a
>>> print bar.__doc__
None
'a'
>>> def bar():
pass
>>> bar.__doc__
>>> help(foo)
Help on function foo in module __main__:
foo()
a
>>> print bar.__doc__
None
1.3.5内部/内嵌函数
在函数体内创建另外一个函数,这叫内部/内嵌函数。
>>> def a():
def b():
print'b'
print 'a'
b()
>>> a()
a
b
>>> b()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
b()
NameError: name 'b' is not defined
def b():
print'b'
print 'a'
b()
>>> a()
a
b
>>> b()
Traceback (most recent call last):
File "<pyshell#25>", line 1, in <module>
b()
NameError: name 'b' is not defined
1.3.6*函数装饰器
装饰器是在函数调用之上的修饰。
使用多个装饰器:
@deco2
@deco1
def func(arg1,arg2,...):pass
和一个组合函数等价:
def func(arg1,arg2,...):pass
func=deco2(deco1(func))
1.有参数和无参数的装饰器
无参数:
@deco
def foo():pass
等价于:foo=deco(foo)
带参数:
@deco(a)
def foo():pass
等价于:foo=deco(a)(foo)
一个含有多个装饰器的例子,其中一个装饰器带有一个参数:
@deco1(a)
@deco2
def func():pass
等价于
func=dec1(a)(deco2(func))
2.装饰器是什么
装饰器就是函数。可以用装饰器来:
引入日志
增加计时逻辑来检测性能
给函数加入事务的能力
1.4传递函数
第一个例子:
>>> def a():
print'a'
>>> b=a
>>> b()
a
print'a'
>>> b=a
>>> b()
a
第二个例子:参数可以传递
>>> def a():
print'a'
>>> def c(x):
x()
>>> c(a)
a
print'a'
>>> def c(x):
x()
>>> c(a)
a
1.5形参
1.5.1位置参数
传入函数的参数数目必须和声明的数字一致
>>> foo()
Traceback (most recent call last):
File "<pyshell#62>", line 1, in <module>
foo()
TypeError: foo() takes exactly 1 argument (0 given)
>>> foo('s')
s
Traceback (most recent call last):
File "<pyshell#62>", line 1, in <module>
foo()
TypeError: foo() takes exactly 1 argument (0 given)
>>> foo('s')
s
>>> foo('s','x')
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
foo('s','x')
TypeError: foo() takes exactly 1 argument (2 given)
Traceback (most recent call last):
File "<pyshell#64>", line 1, in <module>
foo('s','x')
TypeError: foo() takes exactly 1 argument (2 given)
1.5.2默认参数
参数名等号默认值。若没有值传递给那个参数,那么这个参数就将取默认值。
>>> def func(a=1,b=2,c=3):
return a+b+3
>>> func()
6
return a+b+3
>>> func()
6
1.6可变长度的参数
见核心编程p307
1.7函数式编程
支持很多有价值的函数式编程语言构建。四种内建函数和lambda表达式出现。
1.7.1匿名函数与lambda
lambda [arg1,arg2,...]:expression
python允许用lambda关键字创造匿名函数。一个完整的lambda"语句"代表一个表达式,这个表达式需和声明放在同一行。
上面的函数没带任何的参数并且总是返回True。如以下:
def true():return True
使用lambda的等价表达式:
lambda:True
>>> lambda:True
<function <lambda> at 0x0000000002C71F28>
<function <lambda> at 0x0000000002C71F28>
1.7.2内建函数apply(),filter(),map(),reduce()
见核心技术p312
1.8变量作用域
标识符的作业域是定义为其声明在程序里的可应用范围。变量可以是局部域或全局域
1.8.1全局变量与局部变量
声明适用的程序的范围被称为声明的作用域。在一个过程中,若干名称在过程的声明之内,它的出现则为过程的局部变量,否则出现为局部。
全局变量和局部变量:
>>> a=1
>>> def test():
b=2
>>> print a
1
>>> print b
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
print b
NameError: name 'b' is not defined
>>> def test():
b=2
>>> print a
1
>>> print b
Traceback (most recent call last):
File "<pyshell#12>", line 1, in <module>
print b
NameError: name 'b' is not defined
a是全局变量,b是局部变量
1.8.2global语句
若将全局变量声明在一个函数体内,全局变量会被局部变量覆盖掉。
>>> a='1'
>>> def foo():
global a
a='2'
b='3'
print a+b
>>> foo()
23
>>> print a
2
>>> def foo():
global a
a='2'
b='3'
print a+b
>>> foo()
23
>>> print a
2
1.8.3作用域的数字
python从语法支持多个函数嵌套。虽然而,在2.1之前的版本中,最多为两个作用域,一个函数的局部作用域和全局作用域。虽然存在多个函数的嵌套,但不能访问超过两个作用域。
貌似不行,核心编程p321
1.8.4闭包
1.8.5作用域和lambda
1.8.6变量作用域和名称空间
1.9*递归
1.10生成器