函数和高阶函数

函数
1.描述
以def 开头, 缩进的代码块为函数体.
函数声明中可以为形参指定默认值, 含默认值的形参,一般放在普通形参的后面.
调用时的实参可以指定参数名字.

2.例子
def f_greet(name,greeting=‘hello’):
print(greeting,name+’!’)

f_greet(‘cc’)
f_greet(name=‘cc’)
f_greet(‘du’,‘hi’)
3.引用传递
字符串, 数字, 元组 都是不可变的.
实参到形参是引用传递, 所以形参指向的对象被改变了, 实参指向的对象自然同样被改变了.

  1. 函数文档
    类似javadoc.
    如果在函数的开头写下字符串, 它就会作为函数的一部分进行存储.

def square(x):
'calculates xx’
return x
x
那么就可以通过square.__doc__访问函数的功能说明.

  1. 多值返回
    其实返回的就是tuple.

#coding=utf-8
def return_multi():
return ‘hi’,‘hello’

x=return_multi()
print (x)
print(x.class)

a,b=return_multi()
print(a,b)
“”"
显示结果
(‘hi’, ‘hello’)
<type ‘tuple’>
(‘hi’, ‘hello’)
“”"
6. 可变参数
一个星号, *args, 表示当作tuple看待.
两个星号, **kvargs, 表示当作dict看待.

def print_params_4(x,y,z=3,*pospar,**keypair):
print(x,y,z)
print(pospar)
print(keypair)

print_params_4(1,2,3,‘hi’,‘hello’,name=‘xiaoMing’,score=95)
“”"
显示结果
1 2 3
(‘hi’, ‘hello’)
{‘name’: ‘xiaoMing’, ‘score’: 95}
“”"
还有一段代码:

想把一个数组拆成变长形参传递的时候, 就可以这么写.

def foo(*args):
print(args)

a=[1,2,3]
foo(a)
print(’--------’)
foo(*a)
“”"
([1, 2, 3],)

(1, 2, 3)
“”"
7.函数作为参数
在Python中,函数本身也是对象,所以可以将函数作为参数传入另一函数并进行调用.

def call_other_fun(other_fn,params):
print(type(other_fn))
print(other_fn(params))

def foo(params):
“”"
求和
“”"
import numpy as np
return np.sum(params)

call_other_fun(foo,(1,2))
“”"
<class ‘function’>
3
“”"
如 tensorflow 中Estimator#init(self,model_fn,…)函数, 为类 Estimator的构造函数, 第一个参数接受的就是一个函数,并对它的函数签名做check。
#7.定义与调用的关系
在函数定义中, 可以调用尚未声明的函数. 如

def bar():
foo()
def foo():
print “hi”
bar()
是可以运行的.
函数调用的时候, 必须先定义再调用.

fun()
def fun():
print ‘hi’
1
2
3
是运行报错的.
如果函数嵌套复杂, 可以把一部分函数定义到其他模块中去.

  1. 赋值全局字段
    需要使用 global keyword.
    Assign to global variable is dangerous, so python explicitly requires the global keyword before you assign to the global variable.

X=1

def foo():
X=2
def hi():
global X
X=2

foo()
print(X)
hi()
print(X)
“”"
1
2
“”"
高级函数
递归函数

​ 递归是颇为高级的话题,它在Python中相对少见。然而,它是一项应该了解的有用的技术,因为它允许程序遍历拥有任意的、不可预知的形状的结构。递归甚至是简单循环和迭代的替换,尽管它不一定是最简单的或最高效的一种。​ 用递归求和 让我们来看一些例子。 要对一个数字列表(或者其他序列)求和,我们可以使用内置的sum函数,或者自己编写一个更加定制化的版本。这里是用递归编写的一个定制求和函数的示例:

def mysum(L):
if not L:
return 0
else:
return L[0] + mysum(L[1:]) #调用自身 print(mysum([1,2,3,4,5,6]))

第一次:L = [ 1, 2, 3, 4, 5, 6]

​ L[0] = 1 , l1 = L[1:] = [2, 3, 4, 5]

第二次:L = l1= [2, 3, 4, 5, 6]

​ L[0] = 2, L[1:] = [3, 4, 5, 6]

以此类推

​ 在每一层,这个函数都递归地调用自己来计算列表剩余的值和

list = [] def fa(n):
if n1:
return 1
if n
2:
return 1
else:
return fa(n-1)+fa(n-2)
for i in range(1,11):
list.append(fa(i))
print(list) [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
匿名函数

lambda表达式

​ lambda的一般形式是关键字lambda,之后是一个或多个参数(与一个def头部内用括号括起来的参数列表极其相似),紧跟的是一个冒号,之后是一个表达式,即:

lambda para1,para2,…,paran:expression using paras

​ 由lambda表达式所返回的函数对象与由def创建并赋值后的函数对象工作起来是完全一样的,但是lambda有一些不同之处让其在扮演特定的角色时很有用

lambda是一个表达式,而不是一个语句。因为这一点,lambda能够出现在Python语法不允许def出现的地方——例如,在一个列表常量中或者函数调用的参数中。此外,作为一个表达式,lambda返回了一个值(一个新的函数),可以选择性地赋值给一个变量名。相反,def语句总是得在头部将一个新的函数赋值给一个变量名,而不是将这个函数作为结果返回。

lambda的主体是一个单个的表达式,而不是一个代码块。这个- lambda的主体简单得就好像放在def主体的return语句中的代码一样。简单地将结果写成一个顺畅的表达式,而不是明确的返回。因为它仅限于表达式,lambda通常要比def功能要小:你仅能够在lambda主体中封装有限的逻辑进去,连if这样的语句都不能够使用。这是有意设计的——它限制了程序的嵌套:lambda是一个为编写简单的函数而设计的,而def用来处理更大的任务。

除了这些差别,def和lambda都能够做同样种类的工作。例如:

def
add(x,y,z):
return x+y+z
print(add(1,2,3))
使用lambda表达式到相同的效果,通过明确的将结果赋值给一个变量名,之后就能通过这个变量名来调用这个函数

num = lambda x, y, z:
x+y+z print(num(2,3,4))

这里的num被赋值给一个lambda表达式创建的函数对象。这也就是def所完成的任务,只不过def的赋值是自动进行的

默认参数也就能够在lambda参数中使用,就像在def中使用一样

f= (lambda a="Tom " , b ="loves " , c="python ":a+b+c)
print(f())
print(f('liLei '))
print(f('A ','ppx ','c '))
Tom loves python liLei loves python A ppx c
高阶函数

高阶函数:把一个函数名,一实参的形式,传给这个函数的形参,这个函数就称为高阶函数

比如下面的形参c,对应的实参是一个函数名abs。

#函数abs()的功能是取绝对值
def add(a,b,c):
return
c(a)+c(b)
add_value = add(-9,1,abs)
print(add_value)
最正确的高阶函数解释

满足下面两个条件之一,就可称之为高阶函数:

1、把一个函数名当做一个实参,传给另一个函数

2、返回值中包含函数名(不修改函数的调用方式)
Python中常见的高阶函数

(1)filter

功能

filter的功能是过滤掉序列中不符合函数条件的元素,当序列中要删减的元素可以用某些函数描述时,就应该想起filter函数

调用

filter(function,sequence)

function可以是匿名函数或者自定义函数,它会 对后面的sequence序列的每个元素判断是否符合函数条件,返回TRUE或者FALSE,从而留下TRUE的元素;sequence可以是列表、元组或者字符串

例子:

x = [1,2,3,4,5]
y = filter(lambda x: x%2==0,x) #找出偶数
print(y) print(list(y)) #py3之后filter函数返回的不在是列表而是迭代器,所以需要用list转换 <filter object at 0x0000013CB785B0B8>

[2, 4]

普通函数使用lambda

x = [1,2,3,4,5]
def is_odd(n):
return n%2==1
print(list(filter(is_odd,x)))

[1, 3, 5]

(2)map

功能

求一个序列或者多个序列进行函数映射之后的值,就该想到map这个函数,他是python自带的函数,py3返回的是迭代器,通filter,需要进行列表转换

调用

map(function,iterable1,iterable2)

function中的参数数值不一定是一个x,也可以是x和y,甚至多个;后面的iterable表示需要参与function运算中的参数值,有几个参数值就传入几个iterable

例子:

x = [1,2,3,4,5] y = [2,3,4,5,6]
z = map(lambda x , y : x*y + 2, x, y)
print(z)
print(list(z))
<map object at 0x00000294A2A0B1D0>
[4, 8, 14, 22, 32]

普通函数:

def f(x,y):
return x*y+2
x = [1,2,3,4,5] y = [2,3,4,5,6]
print(list(map(f,x,y)
注:map中如果传入的几个序列的长度不一,那么会一句最短的序列进行计算

(3)reduce

功能

对一个序列进行压缩运算,得到一个值,但是reduce在python2的时候是内置函数,到了python3移到了functools模块,所以之前需要from functools import reduce。

调用

reduce(function,iterable[,inital])

其中function必须传入两个参数,inerable可以是列表或者元组

例子:

from functools
import reduce
y = [2,3,4,5,6]
z = reduce(lambda x,y: x+y, y)
print(z) 20
li = [1,2,3,4,5,6] a=1100000+210000+31000+4100+5*10+6
print(a)

其计算原理:

先计算骰两个元素:f(2,3),结果为5;

再把结果和第三个元素计算:f(5,4),结果为9

再把结果和第四个元素计算:f(9,5),结果为14

再把结果和第五个元素计算:f(14,6),结果为20

由于没有更多的元素了,计算结束,返回结果为20

### 回答1: Apache Spark 2.4 中提供了许多解决复杂数据类型的内置函数高阶函数。其中,内置函数包括数组函数、结构体函数、日期时间函数、字符串函数等,可以方便地对复杂数据类型进行操作和处理。高阶函数则可以将函数作为参数传递给其他函数,实现更加灵活的数据处理。 例如,数组函数包括 explode、array_contains、array_distinct 等,可以对数组类型的数据进行拆分、查找、去重等操作。结构体函数包括 struct、getField、withField 等,可以对结构体类型的数据进行创建、获取、修改等操作。日期时间函数包括 year、month、day、hour、minute、second 等,可以对日期时间类型的数据进行提取和转换。字符串函数包括 concat、substring、trim、regexp_replace 等,可以对字符串类型的数据进行拼接、截取、去空格、替换等操作。 高阶函数包括 map、filter、reduce、fold 等,可以对数据集进行映射、过滤、聚合等操作。例如,map 函数可以将一个函数应用于数据集中的每个元素,返回一个新的数据集;filter 函数可以根据指定的条件过滤数据集中的元素,返回一个新的数据集;reduce 函数可以将数据集中的元素进行聚合,返回一个单一的值;fold 函数可以对数据集中的元素进行聚合,并指定一个初始值,返回一个单一的值。 总之,Apache Spark 2.4 中提供了丰富的内置函数高阶函数,可以方便地对复杂数据类型进行操作和处理,提高数据处理的效率和灵活性。 ### 回答2: Apache Spark是一款非常流行的大数据处理框架,而在该框架的最新版本Apache Spark 2.4中,主要更新了复杂数据类型的内置函数高阶函数,以帮助用户更加方便地进行数据分析和处理。 首先,Apache Spark 2.4 中加入了多个新的内置函数,如array_contains、map_from_arrays、map_keys、map_values和posexplode等,用于处理不同的复杂数据类型。 array_contains函数用于判断一个数组是否包含某个指定元素,它很容易地就能来检查一个数据集中是否具有某些特定的值。而map_from_arrays、map_keys和map_values等函数则用于对一个Map类型的数据集进行操作,例如将一些key数组转换成一个map,或者将一个map的值集返回成一个数组等。 此外,Apache Spark 2.4版本还增加了许多高阶函数高阶函数是使用其他函数作为参数的函数,因此通常具有更强的灵活性和适应性。一些常用的高阶函数,如aggregate、foldLeft、reduce、foreach和flatMap等,都能在Spark中得到很好的支持。 其中,aggregate函数用于将数据集中的每条记录与一个给定的初始值进行组合,然后再用一个给定的函数进行聚合。例如,它可以被用于求数据集中的最大值、最小值和平均值等等。 与此相似,foldLeft函数和reduce函数都可以用来对数据集中的每个元素进行操作,但它们的实现方式略有不同。foldLeft函数还可以提供一个序列化的初始值,并将结果与初始值合并以产生最终结果。而reduce函数则使用指定的函数将所有元素逐一聚合起来,得到一个最终的输出结果。 总之,Apache Spark 2.4中新增的这些内置函数高阶函数,为用户提供了丰富的功能和更加灵活的选项,使得Spark在处理各种类型的数据时更加方便和高效。 ### 回答3: Apache Spark 2.4是一个强大的大数据分析和处理引擎,它通过内置的函数库和高阶函数来解决复杂数据类型的处理问题。这些函数使得对非结构化数据或半结构化数据的查询和分析变得容易和高效。 Apache Spark 2.4内置的函数库支持各种复杂数据类型,包括结构化数据(如JSON或XML),图形数据(如社交网络)和空间数据(如地图数据)。对于每种数据类型,Spark都提供了一组专门的函数来解决常见的数据操作问题。例如,Spark提供了大量的JSON函数来解析和查询JSON数据,这些函数可以方便地提取某个字段或值,进行集合操作,或者转换为其他数据格式。 除了内置的函数库之外,Apache Spark 2.4还支持高阶函数高阶函数是指一个函数可以接受另一个函数作为参数或返回一个函数作为结果。这种函数式编程风格可以使得代码更加简洁和灵活。例如,Spark提供了flatMap、map和filter等高阶函数,可以方便地进行复杂的数据转换和筛选。此外,Spark还支持用户定义的函数(UDF),可以让用户根据自己的业务逻辑定义自己的函数,从而获得更高的灵活性和可定制性。 总体而言,Apache Spark 2.4提供了强大的内置函数高阶函数,可以方便地解决各种复杂数据类型的处理问题。这些函数可以提高数据分析和处理的效率,使得数据科学家和开发人员能够更快地分析和挖掘数据价值,实现更加智能和高效的数据处理系统。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值