python总结4-函数

本文是对python中的函数语法的一个简单总结回顾,主要包括命名空间和作用域,匿名函数  闭包 等 。

目录

命名空间和作用域

匿名函数

闭包

扩展调用语法和args 、**kwargs

内置函数

enumerate

zip函数

id函数

sorted函数



函数是Python中最主要也是最重要的代码组织和复用手段。
函数使用def关键字声明,用return关键字返回值; 同时拥有多条return语句也是可以的。如果到达函数末尾时没有遇到任何一条return语句,则返回None。

def my_function(x, y, z=1.5):
    if z > 1:
        return z * (x + y)
    else:
        return z / (x + y)   
# 函数可以有一些位置参数(positional)和一些关键字参数(keyword)。关键字参数通常用于指定默认值或可选参数。在上面的函数中,x和y是位置参数,而z则是关键字参数。
print(my_function(5,6,z=20))
print(my_function(3.14,7,3.5))
print(my_function(10,20))

 

命名空间和作用域

函数可以访问两种不同作用域中的变量:全局(global)和局部(local)。Python有一种更科学的用于描述变量作用域的名称,即命名空间(namespace)。 注意命名空间描述的是变量的作用域。
任何在函数中赋值的变量默认都是被分配到局部命名空间(local namespace)中的。局部命名空间是在函数被调用时创建的,函数参数会立即填入该命名空间。在函数执行完毕之后,局部命名空间就会被销毁(会有一些例外的情况,具体请参见后面介绍闭包的那部分)。

返回多个值,python的函数可以返回多个值 。

def f():
    a,b,c=5,6,7
    
    return a,b,c
x,y,z=f()

print(x,y,z)  
# 该函数其实只返回了一个对象,也就是一个元组,最后该元组会被拆包到各个结果变量中

输出: (5, 6, 7)

由于Python函数都是对象,因此,在其他语言中较难表达的一些设计思想在Python中就要简单很多了。

案例: # 为了得到一组能用于分析工作的格式统一的字符串,需要做很多事情:去除空白符、删除各种标点符号、正确的大写格式等。

states = ['   Alabama ', 'Georgia!', 'Georgia', 'georgia', 'FlOrIda','south   carolina##', 'West virginia?']
#做法之一是使用内建的字符串方法和正则表达式re模块:   
import re 
def clean_strings(strings):
    result=[]
    for value in strings:
        value=value.strip() # 去除空白符
        value=re.sub('[!#?]','',value)  # 注意  re.sub去除里面的标点符号
        value=value.title() # 转换为标题形式的,开头大写
        result.append(value)
    return result
print(clean_strings(states))
#输出: 
['Alabama',
 'Georgia',
 'Georgia',
 'Georgia',
 'Florida',
 'South   Carolina',
 'West Virginia']

做法2:

# 其实还有另一种不错的办法 ,将需要在一组给定字符串上执行的所有运算 做成一个列表
def remove_punction(value):
    return re.sub('[!#?]','',value)
clean_ops=[str.strip,remove_punction,str.title]

def clean_strings(strings,ops):
    result=[]
    for value in strings:
        for function in ops:
            value=function(value)
        result.append(value)
    return result

clean_strings(states,clean_ops) 

函数可以作为参数传过去,因为在python 里本质上是对象。按上述做法2 相较于做法1 ,这种多函数模式使你能在很高的层次上轻松修改字符串的转换方式。此时的clean_strings也更具可复用性 。

还可以将函数用作其他函数的参数,比如内置的 map函数,它用于在一组数据上应用一个函数: 

for x in map(remove_punction,states):
    print(x)
# 输出
Alabama 
Georgia
Georgia
georgia
FlOrIda
south   carolina
West virginia

 

匿名函数

Python支持一种被称为匿名的、或lambda函数。它仅由单条语句组成,该语句的结果就是返回值。它是通过lambda关键字定义的。如:

def short_function(x):
    return x * 2

#用lambda等价表达
equiv_anon = lambda x: x * 2 # 

直接传入lambda函数比编写完整函数声明要少输入很多字(也更清晰),甚至比将lambda函数赋值给一个变量还要少输入很多字,更简洁干净。

# 假设有一组字符串,你想要根据各字符串不同字母的数量对其进行排序:

strings = ['foo', 'card', 'bar', 'aaaa', 'abab']
# 传入一个 lambda 函数到列表的 sort 方法  
strings.sort(key=lambda x: len(set(list(x))))
print(strings)

输出: ['aaaa', 'foo', 'abab', 'bar', 'card']

 

闭包

返回函数的函数   。闭包并不是什么很可怕的东西,如果用对了地方,他们其实可以很强大。简而言之,闭包就是由其他函数动态生成并返回的函数。其关键性质是: 被返回的函数可以访问其创建这的局部命名空间中的变量

示例:

def make_closure(a):
    def closure():
        print('I know the secret: %d '%a)
    return closure
closureBibao=make_closure(5)
print(closureBibao) #<function closure at 0x7f3a75adf2a8>
print(closureBibao())
#输出:
<function closure at 0x7f3a75adf410>
I know the secret: 5 
None

注意: 闭包和标准python函数之间的区别在于 : 即使其创建者已经执行完毕,闭包仍能继续访问其创建者 的局部命名空间。因此,在上面的这种情况中,对于返回的闭包只要调用将可打印出 ”I know the secret: 5 “。 虽然闭包的内部状态(在本例中,只有值a)一般都是静态的,但也允许使用可变对象(如字典、集合、列表等可以被修改的对象)。 例如下面这个函数可以返回一个能够记录其参数(曾经传入的一切参数)的函数。

# 这个函数可以返回一个能够记录其参数(曾经传入的一切参数)的函数. 注意这个例子,可以好好回味下
def make_watcher():
    have_seen={}
    def has_been_seen(x):
        if x in have_seen:
            return True 
        else: 
            have_seen[x]=True
            return False
    return has_been_seen 
# 对一组整数使用该函数,可以得到
watcher=make_watcher()
vals=[5,6,1,5,1,6,3,5]
[watcher(x) for x in vals]  # 对于闭包,可以继续调用 。仍然能访问闭包内部创建的局部命名空间 have_seen ,因此所有被传进去的值都在这个字典里 被记录下来了。
# 输出 [False, False, False, True, True, True, False, True]

#  需要注意一个技术限制  , 虽然可以修改任何内部状态对象(比如向字典添加键值对),但不能绑定外层函数作用域中的变量。一个解决办法是: 修改字典或列表,而不是绑定变量。  
def make_counter():
    count=[0]
    def counter():
        # 增加并返回当前的count
        count[0]+=1
        return count[0]
    return counter
counter=make_counter
print(counter)
# <function make_counter at 0x7f3a75adf758>

注意 闭包到底有什么用? 在实际工作中,可以编写带有大量选项的非常一般化的函数,然后再组装出更简单更专门化的函数。
 

def format_and_pad(template,space):
    def formatter(x):
        return (template %x ).rjust(space)
    return formatter
# 这样,可以创建一个始终返回15位字符串的浮点数格式化器,如下图所示  :
fmt=format_and_pad('%.4f',15)
print(fmt(1.756))
# 输出
'         1.7560'

对于闭包的调用,实际上可以通过类来实现,虽然会更啰嗦点。

 

扩展调用语法和args 、**kwargs

在python中,函数参数的工作方式其实比较简单,当编写func(a,b,c,d=some,e=value)时,位置和关键字参数其实分别是被打包成元组和字典的。函数实际接收到的是一个元组args和一个字典kwargs,并在内部完成转换。

位置参数和关键字参数示例:

def my_function(x, y, z=1.5):
    if z > 1:
        return z * (x + y)
    else:
        return z / (x + y)   
# 函数可以有一些位置参数(positional)和一些关键字参数(keyword)。关键字参数通常用于指定默认值或可选参数。在上面的函数中,x和y是位置参数,而z则是关键字参数。
print(my_function(5,6,z=20))
print(my_function(3.14,7,3.5))
print(my_function(10,20))

# 输出:
220
35.49
45.0

允许将位置参数 当成关键字参数那样进行指定(即使它们在函数定义中并不是关键字参数)  ,arg和kwargs的判定

def say_hello_then_call(f,*args,**kwargs):
    print 'arg is ',args  # args对应的是未带等于号的,(1, 2)
    print 'kwargs is ',kwargs # kwargs对应的是 带等于号的 {'z': 5.0} 
    print ("Hello ! I'm going to call %s"% f)
    return  f(*args,**kwargs)
def g(x,y,z=1,h=3):
    return (x+y)/z

# 调用
say_hello_then_call(g,1,2,z=5.)
print(say_hello_then_call(g,1,2,z=5.,h=20))
# 输出
arg is  (1, 2)
kwargs is  {'z': 5.0}
Hello ! I'm going to call <function g at 0x7f3a75adf578>
arg is  (1, 2)
kwargs is  {'h': 20, 'z': 5.0}
Hello ! I'm going to call <function g at 0x7f3a75adf578>
0.6

 

内置函数

enumerate


    enumerate(sequence, [start=0]) 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。

实例:

seasons = ['Spring', 'Summer', 'Fall', 'Winter']
print(list(enumerate(seasons)))
#输出:
[(0, 'Spring'), (1, 'Summer'), (2, 'Fall'), (3, 'Winter')]    
print(list(enumerate(seasons, start=1)) )      # 小标从 1 开始,可以指定开始的索引,start
# 输出
[(1, 'Spring'), (2, 'Summer'), (3, 'Fall'), (4, 'Winter')]  
 
seq = ['one', 'two', 'three']
for i, c in enumerate(seq): 
    print(i, c)
#输出
0 one
1 two
2 three

zip函数


    函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表对象,这样做的好处是节约了不少的内存。利用 * 号操作符,可以将元组解压为列表。
实例:

>>>a = [1,2,3]
>>> b = [4,5,6]
>>> c = [4,5,6,7,8]
>>> zipped = zip(a,b)     # 返回一个对象
>>> zipped
<zip object at 0x103abc288>
>>> list(zipped)  # list() 转换为列表
[(1, 4), (2, 5), (3, 6)]
>>> list(zip(a,c))              # 元素个数与最短的列表一致
[(1, 4), (2, 5), (3, 6)]
 
>>> a1, a2 = zip(*zip(a,b))          # 与 zip 相反,zip(*) 可理解为解压,返回二维矩阵式.zip(a,b)得到的是[(1, 4), (2, 5), (3, 6)],zip(*x)
>>> list(a1)
[1, 2, 3]
>>> list(a2)
[4, 5, 6]

id函数


    id方法的返回值就是对象的内存地址。

        mapper[id(pHead)] = nHead  #id方法的返回值就是对象的内存地址。

sorted函数


    函数sorted,可以对所有可迭代的对象进行排序操作。  形式sorted(iterable, key=None, reverse=False)
    参数: iterable,可以看到其中第一个参数是可迭代对象;
               key,主要是用来进行比较的元素,只有一个参数,具体的函数的参数就是取自于可迭代对象中,指定可迭代对象中的一个元素来进行排序;
               reverse,是否反转,默认情况下不反转;
    例子:
        sorted()的理解,对list的排序为例:

def test_sorted():
    L = [('b', 2), ('a', 1), ('c', 3), ('d', 0)]
    print(sorted(L,key=lambda x:x[0])) # 用第一项排序
    print(sorted(L,key=lambda x:x[1])) # 用第二项排序
test_sorted()

#输出:
[('a', 1), ('b', 2), ('c', 3), ('d', 0)]
[('d', 0), ('a', 1), ('b', 2), ('c', 3)]

  鸣谢与参考

《python数据分析》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值