python面试常见问题,软件测试python面试题

  python面试常见问题,软件测试python面试题

  1.Python1、数据类型、变量和不可变:tuple、str、int、float、bool变量:list、dict、set2、轻拷贝通常只拷贝对象本身,而改变拷贝中的原对象不会改变,而深拷贝不仅会拷贝对象,还会递归地拷贝与对象关联的对象。更改对象的副本时,不会影响原始对象。深度复制会导致两个问题:如果一个对象直接或间接引用自己,就会导致无休止的递归复制(被复制的对象可以用memo字典保存,这样就避免了刚才说的自引用递归的问题)。它还可以复制最初设计为由多个对象共享的数据。test=[1,2,3,[a , b ]]import copy a=copy . copy(test)b=copy . deep copy(test)a[1,2,3,[a , b]] a[3][1]=c a[1,2,3,[a , c]] test[1,2,3,[a ,C]] b [1,2,3,[a , b ]]b[3][0]= b b b[1,2,2

  #数据结构只有一层:类型可变时,浅拷贝id不一致;当类型不可变时,浅表副本id是一致的。A=[1,2,3]B=copy . copy(a)ID(a)1996137345800 ID(B)1996137414600 a=(1,2,3)B=copy . copy(a)ID(a)1996136097400 ID(B)19961360974003。Python是如何实现内存管理的?Python提供自动内存管理,内存空间的分配和释放由Python解释器运行时自动执行。以CPython解释器为例,其内存管理有三个关键点:引用计数、标签清理和代收集。

  引用计数

  Python中的每个对象实际上都是一个PyObject结构,内部有一个名为ob_refcnt的引用计数器成员变量。在程序运行期间,ob_refcnt的值将被更新,以反映有多少变量被引用到该对象。当一个对象的引用计数值为0时,它的内存将被释放。

  以下情况将导致引用计数增加1:

  被引用的对象将创建的对象作为参数传递给函数,对象作为元素存储在容器中。以下情况将导致参考计数减少1:

  Del语句用来表明被删除的对象引用被重新分配给其他对象的对象引用。当一个对象离开它的作用域时,保存该对象本身的容器就被销毁了。删除对象时,可以通过sys模块的getrefcount函数获取对象的引用计数。计数的内存管理方式遇到循环引用会很致命,需要其他垃圾收集算法来补充。

  清理:

  CPython使用“标记和清除”算法来解决容器类型可能导致的循环引用问题。该算法在垃圾收集中分为两个阶段:

  标记阶段,遍历所有对象,如果对象可达(被其他对象引用),则标记为可达;在清除阶段,再次遍历对象,如果发现某个对象没有被标记为可达,则逐代回收。

  在循环引用对象的回收中,整个应用程序将被挂起。为了减少应用暂停的时间,Python通过分代回收(空间换时间)的方法提高了垃圾收集的效率。逐代回收的基本思想是:一个物体存在的时间越长,它就越不可能是垃圾,所以我们应该尽量不回收这样的物体。

  4.大量的字符串被拼接转换成一个列表再连接,但是使用数字会生成一个新的字符串(字符串是不可变的)。

  5.理解Python中的迭代器和生成器。迭代器:实现迭代器协议的对象。__next__和_ _ iterator _ _这两个神奇的方法,代表了迭代器协议。可以通过for-in循环从迭代器对象中取出值,next函数可以取出下一个值生成器:在调用生成器运行的过程中,每次遇到yield,函数都会暂停并保存当前运行的所有信息,返回yield的值,下次执行next()方法时从当前位置继续运行生成器函数:实现yield的函数,自动实现迭代器协议生成器表达式:列表推导中的括号用括号替换。

  迭代器是访问容器的一种方式,也就是容器已经出现,但是这次迭代只打印出现有元素的一个副本。生成器是自动生成元素,只能遍历一次。迭代生成器,属于边缘计算,随着使用而生成,用完就释放。它效率高,不占用太多内存,节省资源。如果一个对象想要迭代,它需要在内部实现迭代器协议:

  class Fib(object):def _ _ init _ _(self,num): self.num=num self.a,self.b=0,1 Self . idx=0 def _ _ ITER _ _(Self):return Self def _ _ next _ _(Self):if Self . idx Self . num:Self . a,self.b=self.b,Self。一个自我。b自我。idx=1返回自我。一个raise stop iteration()和迭代器协议已经在生成器内部自动实现,这更加简洁:

  Def fib (num): a,b=0,1 for _ inrange (num): a,b=b,a b产生参考:

  生成器和迭代器的区别

  话题008:说说你对Python中迭代器和生成器的理解

  6.多线程和多进程的差异

  通常,我们运行的程序包含一个或多个进程,每个进程包含一个或多个线程。

  多线程:操作系统分配CPU的基本单位,适用于IO密集型任务,比如请求请求。

  优点:多线程可以共享进程内存空间,进程间的通信容易实现。但是由于GIL的限制,多线程无法利用CPU的多核特性。

  多进程是操作系统内存分配的基本单位。适用于需要大量计算的CPU密集型任务,如视频编解码、数据处理、科学计算等。

  我们可以充分利用CPU的多核特性,但是进程间通信比较麻烦,IPC机制(管道,socket等。)是需要的。

  8.列表扩展,越晚添加数据,性能越差。怎么优化呢?

  列表会自动扩展,但会自动摊销和相乘。您可以使用字典或集合来代替大型列表。

  9.写一个函数来计算列表中每个元素出现的次数。

  方法1:

  a=[a , b , a , c]

  信息={}

  因为我在一个:

  .info[i]=info.get(i,0) 1

  信息

  {a: 2, b: 1, c: 1}

  方法二:

  从集合导入计数器

  信息=计数器(a)

  信息

  计数器({a: 2, b: 1, c: 1})

  10.Python为什么运行很慢?

  Python是一种动态的强类型语言,一边解释一边运行。比较和转换类型的成本很高。每当你读、写或引用一个变量时,你必须检查它的类型。

  用C运行时,先编译,它可以直接生成高效的机械代码。python在执行的时候是源代码,一个从源代码到机械代码的过程变量需要随时切换,所以运行时需要随时检查类型。

  GIL限制了多核CPU的并发执行,这是一种同步线程的机制,因此任何时候都只有一个线程在执行。即使在多核处理器上,使用GIL的解释器也只允许单个进程一次只使用一个线程。

  1.Python构造方法和析构函数构造方法

  构造方法__init__:用于实例化一个类。

  析构函数__del__:函数是在对象被调用后将其释放,不再使用。

  A类:

  def __init__(self):

  及格

  def __del__(self):

  打印(“对象已发布”)

  a=A()

  德尔阿

  Print(a) #调用会报告一个错误,因为A已经被清理了

  12.函数参数*arg和**kwargs分别代表什么?

  在Python中,函数的参数分为位置参数、变量参数、关键字参数和命名关键字参数。

  *args代表可变参数,它可以接收0个或任意数量的参数。当您不确定调用者将传入多少个位置参数时,您可以使用variable parameter,它会将传入的参数打包到一个元组中。

  **kwargs代表关键字参数,可以接收参数名=参数值形式传入的参数。传入的参数将被打包成一个字典。

  如果在定义函数时同时使用了*args和**kwargs,那么该函数可以接收任意参数。

  13.写一个记录函数时间的装饰器。

  1.用函数实现装饰器:

  导入时间

  从functools导入包装

  定义记录时间(函数):

  @wraps(func)

  def包装(*args,**kwargs):

  start_time=time.time()

  result=func(*args,**kwargs)

  Print(f 总时间:{time.time()-start_time} )

  回送结果

  返回包装

  @record_time

  def ff():

  对于在幅度内的I(22000):

  打印(一)

  if __name__==__main__ :

  法国法郎()

  2.用类实现装饰器:

  班级记录:

  def __call__(self,func,*args,**kwargs):

  ‘’这个方法的作用类似于在类中重载()运算符,这样就可以像调用普通函数一样,以“object name()”的形式使用类实例对象。

  @wraps(func)

  def包装(*args,**kwargs):

  start_time=time.time()

  result=func(*args,**kwargs)

  Print(f 总时间:{time.time()-start_time} )

  回送结果

  返回包装

  记录=记录()

  # record()将触发__call__

  @记录

  def ff():

  对于在幅度内的I(22000):

  打印(一)

  14.单一模式

  装饰器实现、元类实现、导入

  1)、装饰形式:

  从functools导入包装

  def singleton(cls):

  单纯形类装饰器

  实例={}

  @wraps(cls)

  def包装(*args,**kwargs):

  如果cls不在实例中:

  instances[cls]=cls(*args,**kwargs)

  返回实例[cls]

  返回包装

  @singletonclass

  总统:

  及格

  2)、元类:

  类SingletonMeta(类型):

  自定义单例元类

  def __init__(cls,*args,**kwargs):

  cls。__instance=无

  超级()。__init__(*args,**kwargs)

  def __call__(cls,*args,**kwargs):

  如果cls。_ _实例为无:

  cls。__instance=super()。__call__(*args,**kwargs)

  返回cls。_ _实例

  班长(元

  15.什么是lambda及其使用场景?

  匿名函数不会与其他函数命令冲突。一行代码可以实现一个函数要实现的功能,表达式的执行结果就是函数的返回值。

  其主要目的是将一个函数转换成另一个高阶函数(如filter、Python内置的map等。)对功能进行解耦,增强功能的灵活性和通用性。

  列表(map(lambda x: x*2,[1,2,3]))

  #按值对字典排序

  info={a: 1, b: 2}

  sorted(info.items(),key=lambda x: x[1],reverse=True) # [(b ,2),( a ,1)]

  16.什么是鸭子打字?

  鸭式是动态类型语言用来判断一个对象是否是某一类型的方法,也叫鸭式判断法。简单来说,鸭型是指判断一只鸟是不是鸭子。我们只在乎它游得像鸭子,叫得像鸭子,走得像鸭子。换句话说,如果一个物体的行为与我们的预期一致(它能接受某种信息),我们就会假设它是某种类型的物体。

  在Python中,有很多类字节对象(如bytes,bytearray,array.array,memoryview),类文件对象(如StringIO,BytesIO,GzipFile,socket),类路径对象(如str,bytes),其中,类文件对象可以支持读写操作,可以像文件一样读写。这就是所谓的判断方法,一个物体如果表现得像鸭子,就可以判断它是鸭子。另一个例子是Python中list的extend方法。它需要的参数不一定是列表,只要是可迭代的对象就没有问题。

  说明:动态语言的duck类型大大简化了设计模式的应用。

  17.谈谈对闭包的理解

  由于各种原因,有时需要在函数外部获取函数内部的局部变量,但由于Python作用域的限制,外部访问会直接报告NameError,这是无法直接实现的,比如:

  定义f1():

  n=999

  打印(n)

  但是,如果在函数内部定义了内部函数,它就可以访问函数的局部变量。如果直接返回内部函数,则函数内部的局部变量也可以在外部间接访问:

  定义f1():

  n=999

  定义f2():

  打印(n)

  返回f2

  结果=f1()

  结果()

  上面的f2()函数是一个闭包。闭包的定义是,当一个函数中可以定义(嵌套)另一个函数时,如果内部函数引用外部函数的变量,就可能产生闭包。

  关闭的目的

  读取函数内部的变量。

  将函数内部的局部变量一直保存在内存中:函数运行后,函数内部的局部变量会被Python的垃圾收集机制从内存中清除。如果想让这个局部变量长时间存放在内存中,可以用闭包来实现这个功能,这样会导致很大的内存开销,所以要避免滥用。

  18、收藏

  1、默认字典

  是内置dict类的子类。它实现了键不存在时返回默认值的功能,只是和内置的dict函数完全一样。

  从集合导入默认字典

  default_dict=defaultdict(int)

  default_dict[x]=22

  default_dict[x]

  default_dict[y]

  #自定义返回默认值

  def get_default_info()。

  .return {name: 123}

  D1=default dict(get _ default _ info)

  d1[aa]

  { 姓名: 123}

  2、有序直接

  有序字典,可以保持元素的插入顺序。

  从集合导入订单直接

  d=OrderedDict()

  d[名字]=罗斯

  d[年龄]=18

  OrderedDict([(name , rose ),( age ,18)])

  D.move_to_end(name) #可以将指定的键移动到末尾,D.move_to_end(name ,last=false)移动到开头。

  OrderedDict([(age ,18),( name , rose)])

  3、柜台

  统计元素出现的次数,其附加的most_common()函数通常用于解决Top k问题。

  从集合导入计数器

  d=[a , b , a , c]

  d_counter=计数器(d)

  d _计数器

  计数器({a: 2, b: 1, c: 1})

  d_counter.most_common(1)

  [(a ,2)]

  4、德克

  双端队列

  从集合导入队列

  q=deque([1,2,3])

  q.append(4)

  q.appendleft(5)

  德克([5,1,2,3,4])

  q .波普()

  q.popleft()

  五

  5、命名双拼

  命名元组(Named tuple ),返回一个新的带有命名字段的元组子类,可以用来构建一个只有几个属性而没有方法的类对象;比直接定义类节省了很多空间。其次,它的返回值是一个元组,支持各种元组。

  从集合导入命名元组

  Point=namedtuple(Point ,[x , y])

  点. x

  0x000001D0C31050E8处的属性对象

  P=点(1,2) #实例化

  页(page的缩写)_asdict()

  OrderedDict([(x ,1),( y ,2)])

  6、链式地图

  将多个字典组合成一个字典,向外界提供统一的视图。

  从集合导入链图

  def演示链():

  user1={name: rose , age: 18}

  user2={name: lila , age: 19}

  用户=链图(用户1,用户2)

  print(user . maps)#[{ name : rose , age: 18},{name: lila , age: 19}]

  print(user . keys())# keys view(chain map({ name : rose , age: 18},{name: lila , age: 19}))

  print(user . values())# values view(chain map({ name : rose , age: 18},{name: lila , age: 19}))

  对于user.items()中的k,v:

  打印(k,v)

  名字叫罗斯

  18岁

  如果ChainMap()中的多个字典有重复的键,那么在查看的时候可以看到所有的键,但是在遍历的时候只会遍历第一个出现键的地方,而忽略其余的。

  19.线程池的工作原理

  线程池是一种可以减少线程的创建和销毁所带来的开销的技术,属于以空间换时间的操作。

  由于线程的创建和销毁涉及大量的系统底层操作,开销较大;线程池的原理是将创建和释放线程的操作改为预创建。在创建了一定数量的线程后,它们被放入空闲队列。最初,这些线程被阻塞,不会消耗CPU资源,但会占用少量内存空间。

  当一个新任务到来时,从队列中取出一个空闲线程,并将其标记为已占用。任务完成后,线程不会结束,而是继续留在池中等待下一个任务。当系统空闲且大部分线程长时间空闲时,线程池可以自动销毁部分线程,回收系统资源。

  基于这种预创建技术,线程池将线程创建和销毁的成本分配给每个特定的任务。执行的次数越多,每个任务的成本越小。

  20.如何读取大文件,比如8G的文件?

  使用产量生成器指定尺寸读数。

  def读取文件():

  用open(path,encoding=utf-8 )作为f:

  虽然正确:

  chunk _ data=f . read(chunk _ size=2048)#指定每次读取的大小(字节)。

  如果不是chunk_data:

  破裂

  产出区块数据

  21.Python实例方法、类方法、静态方法详解

  方法:可以通过对象直接调用。

  Classmethod:不能访问实例变量,只能访问类变量,类变量可以通过类名和对象调用。

  Staticmethod:与类无关,只是类中的一个函数。不能作为类变量或实例变量,可以通过类名或对象调用。

  班级狗:

  年龄=3 #类变量

  def __init__(self):

  Self.name=小白 #实例变量

  DEF (self): #实例方法

  print({}岁的{}正在运行!。格式(自我年龄,自我姓名))

  @classmethod

  def eat(cls):

  # print(cls.name) # class方法,无法访问实例变量(属性)

  打印(小黑{岁)。format (cls.age)) # Class方法只能访问类变量。

  @静态方法

  定义睡眠(名称):

  #静态方法与类无关,只有类中的一个函数。

  #静态方法不能访问类变量和实例变量。

  打印(({}正在睡觉)。格式(名称))

  d=狗()

  D.run() #通过实例化对象来调用实例方法

  Dog.run(d) #通过类名调用实例方法,实例对象需要传入方法。

  D.eat() #通过实例化对象来调用类方法

  Dog.eat() #通过类名调用类方法

  D.sleep(小兰)#通过实例化对象来调用静态方法

  Dog.sleep(晓兰)#通过类名调用静态方法

  参考:Python实例方法、类方法、静态方法的详细讲解。

  第二,卡夫卡

  1.提交人:卡夫卡胶印

  自动提交:基于时间提交,很难把握提交时机。

  手动提交:

  提交:它影响吞吐量,将无法重试。

  异步提交:最常用的,没有重试机制可能会失败。

  2.信息泄露消费和重复消费的场景

  无论是同步还是异步提交抵销,都有可能遗漏或重复消耗。

  漏消费:消费前提交。

  重复消费:提交前消费。

  3.自定义偏移

  在kafka 0.9之前,offset存储在zk中,之后默认存储在内置主题中。用户还可以自定义存储模式。

  其目的是保证抵销的消耗和提交同时成功或失败。可以利用数据库的事务函数来实现,所以offset可以存储在MySQL中。

  4.邮件积压场景

  或者实时消耗任务挂机:任务挂机,不被监控,直到自动拉起。

  卡夫卡分区数设置不合理(太少),消费者消费能力不足。

  kafka消息的密钥不均匀,导致分区间数据不均衡(生产者生产消息时可以指定密钥)。

  解决:

  任务重启后,直接消耗最新消息,滞后的历史数据被离线程序捕获。

  监控和自动上拉任务从最后一次提交偏移开始。如果数据积压量大,就要增加任务的处理能力,比如增加资源,让任务以最快的速度消耗和处理,赶上最新的消耗消息,合理增加分区。

  如果使用Spark stream和Kafka direct方法,KafkaRDD也可以重新分区以增加并行性。

  添加随机后缀的关键,以平衡它。

  Redis:非关系数据库,数据类型:字符串、列表、集合、有序集、hash,存储在内存中,读写速度快,可以作为缓存键值存储结构。

  缺点:由于是基于内存查询,限制了可以存储的数据量,限制了Redis在大规模数据场景下的应用。

  场景:适用于读写性能极高、数据表结构简单、查询条件简单的应用场景。

  MongoDB:非关系数据库,存储在磁盘上,读取的数据会加载到内存中,读取速度快,表结构灵活可变,字段类型可以随时修改。插入数据时,不必考虑表结构的限制。

  缺点:妨碍多表查询、复杂事务等高级操作。

  场景:适用于那些表结构变化频繁,数据逻辑结构没有那么复杂,不需要多表查询操作,数据量比较大的应用场景。

  HBase:非关系型数据库(列存储),横向扩展能力强,适合存储海量数据。使用廉价的PC就可以构建一个用于海量数据处理的大数据集群。

  缺点:数据的读取受到限制,只能把同一列族的数据放在一起,所有的查询都必须依赖于键,导致很多复杂的查询很难实现。

  场景:hbase是一个重产品,依赖于很多hadoop组件。如果数据规模不大,没必要用hbase,MongoDB完全可以满足需求。因为列存储的容量带来了海量数据的容量,所以非常适合数据量巨大,查询条件简单,列间联系少的场景。

  唯一索引:加速查询列值是唯一的(可以为空)。

  主键索引:只有一个整表,只有一个列值用于加速查询(不允许null)

  复合(联合)索引:多个列构成一个索引。

  采用单线程,避免不必要的上下文切换和竞争条件,不存在多进程或多线程导致的切换对CPU的消耗。不需要考虑各种锁,没有锁和解锁操作,也不会因为可能的死锁而消耗性能。

  使用不同的底层模型,它们与客户端通信的底层实现方法和应用协议是不同的。Redis直接自建VM机制,因为一般系统调用系统函数,会浪费一定的时间去移动和请求。

  四。火花

  1.星火任务如何解决第三方依赖?

  比如机器学习包需要本地安装?- py-files添加py、zip和egg文件不需要安装在每个节点上。

  2.如何解决火花数据的偏斜?

  spark中的数据偏斜是指shuffle过程中的数据偏斜,主要是由于key对应的数据不同,导致不同任务处理的数据不同。

  例如,reduce点必须处理总共100万条数据。第一个和第二个任务分别分配到10000条数据,计算在5分钟内完成。第三个任务分配给98万条数据。此时,第三个任务可能需要10个小时才能完成,这使得整个Spark作业需要10个小时才能运行和完成。这就是数据倾斜的后果。

  数据倾斜的性能:

  Spark jobs的大部分任务执行得很快,只有有限的几个任务执行得非常慢。这时候可能会有数据倾斜,作业可以运行,但是运行很慢。

  Spark jobs的大部分任务执行速度都很快,但是有些任务在运行过程中会突然报告OOM,有些任务在重复执行几次后会报告OOM错误。此时可能会发生数据倾斜,作业无法正常运行。

  定位数据倾斜问题:

  检查代码中的shuffle操作符,如reduceByKey、countByKey、groupByKey、join等。并根据代码逻辑判断这里是否会出现数据偏斜。

  检查Spark作业的日志文件。日志文件会将错误记录到代码的某一行。根据异常所在代码的位置,可以确定错误发生在哪个阶段,对应的是哪个shuffle运算符。

  3.火花驱动器和执行器

  在执行Spark的应用时,Spark集群会启动两个JVM进程,Driver和Executor。

  驱动程序:负责创建spark上下文,提交spark job作业,将作业转换为计算任务,并协调各执行器进程之间的任务调度。

  执行程序:负责在工作节点执行具体的计算任务,将结果返回给驱动程序,并为需要持久化的RDD提供存储功能。

  4.火花内部和外部存储器

  Spark内存管理包括堆上内存和堆外内存。因为驱动的内存管理比较简单,所以下面说的内存指的是执行程序的内存。

  Excutor作为一个JVM进程,它的内存管理是建立在JVM内存管理的基础上,Spark更细致地分配JVM的堆空间,充分利用内存。同时还引入了堆外内存,可以直接在工作节点的系统内存中开辟空间,进一步优化了内存的使用。

  堆内内存的大小,由- executor-memory或spark.executor.memory参数在spark应用程序启动时配置。

  堆内内存分区

  执行程序堆内存可以分为四个主要块:

  执行程序内存(Excutor memory):主要用于计算过程中的临时数据的洗牌、连接、排序、聚合等。

  存储内存:主要用于存储缓存数据,如rdd缓存和展开数据。

  用户内存:主要用于存储rdd转换操作所需的数据,如rdd依赖等信息。

  预留内存:系统预留内存来存储内部spark对象,防止OOM,因为spark堆中的内存大小记录不准确,所以需要留出安全区域(在Spark 2.2.1中是写死的,其值等于300MB,不可修改)

  # systemMaxMemory取决于JVM堆中当前的内存大小,实际上是由spark.executor.memory或- executor-memory配置的。

  可用存储内存=system maxmemory * spark . storage . memory fraction * spark . storage . safety fraction。

  可用执行内存=system maxmemory * spark . shuffle . memory fraction * spark . shuffle . safety fraction。

  可用内存=系统内存-预留内存,也就是Spark的可用内存。

  堆外内存

  堆外空间的分配相对简单,只有存储内存和执行内存。

  可用的执行内存和存储内存占用的空间直接由参数spark.memory.storageFraction决定,由于堆外内存占用的空间可以精确计算,所以不需要设置保险区域。

  spark . memory . off heap . enabled true

  spark . memory . offheap . size 10747 . 48868868687

  两者的区别

  参考:Spark内存管理的堆内/堆外内存原理详解

  5.火花血缘关系

  父子rdd的构造中存在依赖关系,通过依赖关系可以实现rdd的容错,连续几个rdd的依赖关系变成血缘关系。

  每个rdd不会保存数据,但是会保存血缘关系。如果当前rdd的计算有错误,可以根据其保存的血缘关系重新读取数据源进行计算。

  参考:RDD血统的火花

  6.火花宽度依赖性

  狭义依赖

  如果依赖关系可以在设计时确定,就不需要考虑父rdd分区中的记录,父rdd中的每个分区最多只有一个子分区。

  父rdd的每个分区最多被子rdd的一个分区使用。

  子rdd中的分区或者仅依赖于父rdd中的一个分区(例如,映射和过滤操作)。

  或者可以在设计时确定子rdd是父rdd的子集(例如,coalesce)。

  窄依赖变换可以在任何分区上独立执行,而不需要任何其他分区的信息。

  广泛依赖

  父rdd的分区依赖于多个子rdd的分区,这称为广泛依赖。

  计算宽依赖时,不能随意在一些记录中运行,需要使用特殊的方式(比如根据键获取分区中的所有数据)。

  比如排序sort的时候,数据必须分区,相同范围的键必须在同一个分区。

  具有广泛依赖性的转换操作包括:sort、reduceByKey、groupByKey、join以及任何调用修复函数的操作。

  7.常见的转换和动作操作

  转换:

  Map(func):返回一个新的rdd,其结果由func函数处理的每个输入元素组成。

  MapPartition(func):类似于map,但是在rdd的每个分区中独立运行。假设有N个元素,M个分区,map的函数会被调用N次,而mapPartition会被调用M次,一次性处理所有分区。

  FlatMap(func):对集合中的每个元素进行操作,然后将其展平。

  Filter(func):返回一个新的rdd,rdd中的每个元素都会被func函数的逻辑过滤掉。

  RedubyKey (func,[numtask]):调用一个(K,V) RDD并返回一个(K,V) RDD。使用reduce函数将同一个键的值聚合在一起。第二个参数可以设置reduce任务的数量。

  动作:首先、计数、收集、保存文本文件、获取、foraech、countByKey

  8.spark可以通过多种方式部署。

  Local:它在机器上运行,通常用于手工练习或测试。

  Standalone:基于主从的资源调度集群,将spark任务提交给Master运行,这是spark本身的一个调度系统。

  纱线:有两种模式:纱线客户端和纱线集群。主要区别在于驱动程序的运行节点。Spark客户端直接连接到Yarn,因此不需要构建额外的Spark集群。

  Mesos:在家庭环境中很少使用。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: