函数是Python中最基础、最重要的代码组织和代码复用方式。
函数声明时使用def关键字,返回时使用return关键字
def function(x,y,z=1.5):
if z>1:
return z*(x+y)
else:
return z/(x+y)
如果Python达到函数的尾部时仍然没有遇到return语句,就会自动返回None。
每个函数都可以由位置参数和关键字参数:关键字参数最常用于指定默认值挥着可选参数。在上面的示例中,x和y时位置参数,z时关键字参数。这就意味着函数可以通过 以下任何方式进行调用。
function(5,6,z=0.7)
function(3.14,7,3.5)
function(10,20)
函数参数的主要限制是关键字参数必须跟在位置参数(如果有的话)后。可以按照任意顺序指定关键字参数,也可以使用关键字参数向位置参数传参。
function(x=5,y=6,z=7)
function(y=6,x=5,z=7)
1.命名空间、作用域和本地函数
函数有两种连接变量的方式:本地、全局。在Python中另一种更贴切的描述变量作用域的名称为命名空间。在函数内部,人一边俩个都是默认分配到本地命名空间的。本地命名空间实在函数被调用时生成的,并立即由函数的参数填充。在函数执行结束后,本地命名空间就会被销毁。
def func():
a=[]
for i in range(5):
a.append(i)
当调用func()时,空的列表a就会被创建,五个元素被添加到列表中,之后a会在函数退出时被销毁。
a = []
def func():
for i in range(5):
a.append(i)
这样声明a,在函数外部给变量赋值时可以的,但是哪些变量必须使用global关键字声明为全局变量:
a = None
def func():
global a
a=[]
func()
print(a)
[]
global关键字:通常全局变量用来存储系统中的某些状态,当使用大量的全局变量,则可能表明需要面向对象编程
2.函数是对象
对于Python的函数是对象,很多在其他语言中比较难的构造在Python中非常容易实现。
假设在数据清理的过程中,需要将一些变形应用到下列字符串列表中:
states=['Alabama','Georgial','Georgia','georgia','FlOrIda','south carolina##','West virginia!']
为使这些数据整齐、可用于分析,需要进行:去除空格,移动标点符号,适当调整的大小写。
一种方式是使用内建的字符串方法,结合标准库中的正则表达式模块re:
import re
def clean(strings):
result=[]
for value in strings:
value=value.strip()
value=re.sub('[!#?]','',value)
value=value.title()
result.append(value)
return result
clean(states)
输出['Alabama', 'Georgial', 'Georgia', 'Georgia', 'Florida', 'South Carolina', 'West Virginia']
另一种方法就相当于将特定的列表操作应用于某个字符串的集合上,
import re
import string
states=['Alabama','Georgial','Georgia','georgia','FlOrIda','south carolina##','West virginia!']
def remove(value):
return re.sub('[!#?]','',value)
clean_ops=[str.strip,remove,str.title]
def clean(strings,ops):
result=[]
for value in strings:
for function in ops:
value=function(value)
result.append(value)
return result
clean(states,clean_ops)
输出:['Alabama', 'Georgial', 'Georgia', 'Georgia', 'Florida', 'South Carolina', 'West Virginia']
3.匿名函数(Lambda)
Python支持所谓的匿名或者Lambda函数。匿名函数是一种通过单个语句生成函数的方式。其结果使返回值。匿名函数使用lambda关键字定义,该关键字仅表达“我们声明一个匿名函数”的意思:
def apply_to_list(some_list,f):
return [f(x) for x in some_list]
ints=[4,0,1,5,6]
apply_to_list(ints,lambda x:x*2)
匿名函数的代码量很小,将它作为参数进行传值,比写一个完整的函数或者将匿名函数赋值给局部变量更好。
4.生成器
通过一致的方式遍历序列,是Python很重要的特性。这个特性是通过迭代器协议来实现的,迭代器协议是一种令对象可遍历的通用方式。
迭代器是一种用于在上下文向Python解释器生成对象的对象。大部分以列表或者列表型的对象为参数的方法都可以接收任意的迭代器对象。包括内建方法以及类型构造函数例如list或tuple
生成器是构造新的可遍历对象的一种非常简洁的方式。普通函数执行并一次返回单个结果,而生成器则惰性的返回一个多结果序列,在每个元素产生之后暂停,直到下一个请求,如需创建一个生成器,只需在函数中将返回关键字return替换为yield关键字:
def squares(n=10):
print('Generating squares from 1 to {0}'.format(n**2))
for i in range(1,n+1):
yield i**2
当调用生成器时,代码不会立即执行,直到请求生成器中的元素时,才会执行。
用生成器表达式来创建生成器更为简单。生成器表达式与字典、列表以及集合的推导式很类似,创建一个生成器表达式,只需要将列表推导式的中括号替换为小括号即可。
标准库中的itertools模块是适用于大多数数据算法的生成器集合,例如,groupby可以根据任意的序列和一个函数,通过函数的返回值对序列中继续的元素进行分组
import itertools
first_letter=lambda x:x[0]
names=['Alan','Adam','Wes','Will','Albert','Steven']
for letter,names in itertools.groupby(names,first_letter):
print(letter,list(names))
A ['Alan', 'Adam']
W ['Wes', 'Will']
A ['Albert']
S ['Steven']
下列为itertools函数的列表
combinations(iterable,k)
根据Iterable参数中的所有元素生成一个包含所欲可能K-元组的序列,忽略元素的顺序,也不进行替代
permutations(iterable k)
根据iterable参数中的所有元素按照顺序生成包含所有可能K元组的序列
groupby(iterable[,keyfunc])
根据每一个独一的key生成(key,subiterator)元组
product(*iterables,repeat=1)
以元组的形式,根据输入的可遍历对象生成笛卡儿积,与嵌套的for循环类似
5.错误和异常处理
处理Python异常或错误是构建稳定程序的重要组成部分。
在数据分析过程中,很多函数只能处理特定的输入。假设想在float函数运行失败时,可以优雅的返回输入参数,可以通过过将float函数写入一个try/except代码段中实现
def attempt_float(x):
try:
return float(x)
except:
return x
如果float(x)执行时抛出异常,则代码段中的except部分代码将会被执行。可以将多个异常类型写成元组的方式同时捕获多个异常。
def attempt_float(x):
try:
return float(x)
except(TypeError,ValueError):
return x
某些时刻。可能想处理一个异常,但希望一部分代码无论try代码块是否报错,都要执行。为达到这个目的,使用finally关键字。
f=open(path,'w')
try:
write_to_file(f)
finally:
f.close()
这可以让f在程序结束后总是关闭。