01.29 金融科技求职面试题


金融科技求职面试题


1、 线程和进程

什么叫"多任务"呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。

现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?

答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。

真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。

对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。

有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个"子任务",我们把进程内的这些"子任务"称为线程(Thread)。

由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。

我们前面编写的所有的Python程序,都是执行单任务的进程,也就是只有一个线程。如果我们要同时执行多个任务怎么办?

有两种解决方案:

一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。

还有一种方法是启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。

当然还有第三种方法,就是启动多个进程,每个进程再启动多个线程,这样同时执行的任务就更多了,当然这种模型更复杂,实际很少采用。

总结一下就是,多任务的实现有3种方式:

· 多进程模式;

· 多线程模式;

· 多进程+多线程模式。

同时执行多个任务通常各个任务之间并不是没有关联的,而是需要相互通信和协调,有时,任务1必须暂停等待任务2完成后才能继续执行,有时,任务3和任务4又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。但是,有很多时候,没有多任务还真不行。想想在电脑上看电影,就必须由一个线程播放视频,另一个线程播放音频,否则,单线程实现的话就只能先把视频播放完再播放音频,或者先把音频播放完再播放视频,这显然是不行的。

Python既支持多进程,又支持多线程。


2、 有指针和无指针

指针是C语言的核心概念,使用指针可以带来如下的好处:

(1)可以提高程序的编译效率和执行速度,使程序更加简洁。

(2)通过指针被调用函数可以向调用函数处返回除正常的返回值之外的其他数据,从而实现两者间的双向通信。

(3)利用指针可以实现动态内存分配。

(4)指针还用于表示和实现各种复杂的数据结构,从而为编写出更加高质量的程序奠定基础。

(5)利用指针可以直接操纵内存地址,从而可以完成和汇编语言类似的工作。

(6)跟容易实现函数的编写和调用。

当然,指针也是一把双刃剑,如果对指针不能正确理解和灵活有效的应用,利用指针编写的程序也更容易隐含各式各样的错误,同时程序的可读性也会大打折扣。


3、浅拷贝与深拷贝

浅拷贝可以使用列表自带的copy()函数(如list.copy()),或者使用copy模块的copy()函数。深拷贝只能使用copy模块的deepcopy(),所以使用前要导入:from copy import deepcopy

如果拷贝的对象里的元素只有值,没有引用,那浅拷贝和深拷贝没有差别,都会将原有对象复制一份,产生一个新对象,对新对象里的值进行修改不会影响原有对象,新对象和原对象完全分离开。

如果拷贝的对象里的元素包含引用(像一个列表里储存着另一个列表,存的就是另一个列表的引用),那浅拷贝和深拷贝是不同的,浅拷贝虽然将原有对象复制一份,但是依然保存的是引用,所以对新对象里的引用里的值进行修改,依然会改变原对象里的列表的值,新对象和原对象完全分离开并没有完全分离开。而深拷贝则不同,它会将原对象里的引用也新创建一个,即新建一个列表,然后放的是新列表的引用,这样就可以将新对象和原对象完全分离开。


3、 类和继承

类可以看做相同的属性和方法抽象概括而来,对象就是类实例化而来。

子类继承父类的属性和方法,可以有比父类更具体的属性和方法,在类的属性和方法使用中,首先在子类中查找再往父类上查找,节约代码。如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。继承可以把父类的所有功能都直接拿过来,这样就不必重零做起,子类只需要新增自己特有的方法,也可以把父类不适合的方法覆盖重写。

那么可以在 子类的 __init__中调用一下父类的 __init__ 方法,这样就可以调用了:

金融科技求职面试题

<code>class Animal:/<code>
<code>    def __init__(self):/<code>
<code>        self.a = 'aaa'/<code>
<code>class Cat(Animal):/<code>
<code>    def __init__(self):/<code>
<code>        super().__init__()  #也可以用 Animal.__init__(self)  这里面的self一定要加上/<code>
<code>cat = Cat()print(cat.a)>>>aaa生成器和迭代器迭代是Python最强大的功能之一,是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。迭代器有两个基本的方法:iter()和next()。字符串,列表或元组对象都可用于创建迭代器:在 Python 中,使用了 yield 的函数被称为生成器(generator)。跟普通函数不同的是,生成器是一个返回迭代器的函数,只能用于迭代操作,更简单点理解生成器就是一个迭代器。在调用生成器运行的过程中,每次遇到 yield 时函数会暂停并保存当前所有的运行信息,返回 yield 的值, 并在下一次执行 next() 方法时从当前位置继续运行。调用一个生成器函数,返回的是一个迭代器对象。可变对象和不可变对象Python3 中有六个标准的数据类型:· Number(数字) Python3 支持int、float、bool、complex(复数)。· String(字符串)· List(列表)· Tuple(元组)· Set(集合)· Dictionary(字典)Python3 的六个标准数据类型中:· 不可变数据(3 个):Number(数字)、String(字符串)、Tuple(元组);· 可变数据(3 个):List(列表)、Dictionary(字典)、Set(集合)。hive中Sort By,Order By,Cluster By,Distribute By,Group By的区别order by:  hive中的order by 和传统sql中的order by 一样,对数据做全局排序,加上排序,会新启动一个job进行排序,会把所有数据放到同一个reduce中进行处理,不管数据多少,不管文件多少,都启用一个reduce进行处理。如果指定了hive.mapred.mode=strict(默认值是nonstrict),这时就必须指定limit来限制输出条数,原因是:所有的数据都会在同一个reducer端进行,数据量大的情况下可能不出结果,那么在这样的严格模式下,必须指定输出的条数。sort by:sort by 是局部排序,会在每个reduce端做排序,每个reduce端是排序的,也就是每个reduce出来的数据是有序的,但是全部不一定有序,除非一个reduce,一般情况下可以先进行局部排序完成后,再进行全局排序,会提高不少效率。distribute by:  distribute by 是控制map端在reduce上是如何区分的,distribute by 会把指定的值发到同一个reduce中,比如 用上面数据distribute by id 它就会把id相同的值放到一个reduce中执行,不是一个值一个reduce,而是相同的值进入到一个reduce,例如用上面数据可以进入到2个reduce,一般情况下可以sort by 结合使用,先进行分组reduce,再进行排序(相当于mapreduce中的分区函数)。PS:Order by 能够预期产生完全排序的结果,但是它是通过只用一个reduce来做到这点的。所以对于大规模的数据集它的效率非常低。在很多情况下,并不需要全局排序,此时可以换成Hive的非标准扩展sort by。Sort by为每个reducer产生一个排序文件。在有些情况下,你需要控制某个特定行应该到哪个reducer,通常是为了进行后续的聚集操作。Hive的distribute by 子句可以做这件事cluster by(只能是使用默认的升序排序,不能使用ACS和DESC):  这个其实就是distribute by 和sort by 结合使用的结果(前提是同一个字段)。  例如:select id,money,name from t cluster by id;  等价于:select id,money,name from t distribute by id sort by iddistribute by和group by的区别:  都是按key值划分数据 都使用reduce操作 **唯一不同的是,distribute by只是单纯的分散数据,distribute by col – 按照col列把数据分散到不同的reduce。而group by把相同key的数据聚集到一起,后续必须是聚合操作。order by和sort by的区别:  order by是全局排序 sort by只是确保每个reduce上面输出的数据有序。如果只有一个reduce时,和order by作用一样。Hive分区表和分桶表的区别分区在HDFS上的表现形式是一个目录, 分桶是一个单独的文件分区: 细化数据管理,直接读对应目录,缩小mapreduce程序要扫描的数据量分桶: 1、提高join查询的效率(用分桶字段做连接字段)     2、提高采样的效率Hive数据倾斜处理hive底层的执行引擎 mr:mapreduce 由两部分组成:map 、 reduce归根结底:底层mr的数据倾斜。怎么判断程序发生了数据倾斜?reduce停留在一个阶段很长时间不动数据倾斜与 1)数据量; 2)map端key的设置;有关hive中哪些操作容易造成数据倾斜:join操作:join关联时有null值关联时数据类型不同小表 关联 大表 造成数据倾斜set hive.auto.convert.join = true; //设置mapjoin优化自动开启装饰器就是现在比如有很多个性化函数,但是每个函数都有一些重复的代码。现在需要做的就是将这些重复的代码放到一个装饰器函数的内层函数之中,个性化函数作为装饰器的参数传入,装饰器形成闭包。Python存在这样的语法糖,@ 然后调用个性化函数就可以了。个性化函数的参数对应内层函数的参数,函数对应外层函数参数。主要就是起到不改变代码的情况下,增加更多的函数功能。python2和python3的range(100)的区别python2返回列表,python3返回迭代器,节约内存/<code> 


分享到:


相關文章: