第6章 第1节 编程语言

推荐给朋友

● 什么是python的生成器?

参考回答:

python生成器是一个返回可以迭代对象的函数,可以被用作控制循环的迭代行为。生成器类似于返回值为数组的一个函数,这个函数可以接受参数,可以被调用,一般的函数会返回包括所有数值的数组,生成器一次只能返回一个值,这样消耗的内存将会大大减小。

● Java抽象类和接口的区别?

参考回答:

Java中,一个类可以实现多个接口,但是一个类只能继承一个抽象类。接口中只包含接口签名,而抽象类可以提高默认实现,子类可以重载抽象类方法。接口中默认的所有方法均为public修饰,而抽象类可以用protected修饰符。接口中不允许定义任何属性,而抽象类中可以定义属性和常量在应用场景中。在应用场景中使用接口来完成同一方法的不同实现,若不同的方法实现需要共享同样的行为或状态则用抽象类。

● python中is和==的区别

参考回答:

is是用来判断两个变量引用的对象是否为同一个,==用于判断引用对象的值是否相等。可以通过id()函数查看引用对象的地址。

● python方法解析顺序

参考回答:

Python的方法解析顺序优先级从高到低为:实例本身继承类(继承关系越近,越先定义,优先级越高)

● Ctrl+C程序挂掉还是抛出异常,如何判断两个dict是否一样,list头上删除元素,字符串拼接?

参考回答:

Ctrl+C会挂掉程序

通过is可以判断两个dict是否相同

list.pop(0)删除list第一个元素

join()函数进行字符串拼接

● pytorch中cuda()作用,两个Tensor,一个加了cuda(),一个没加,相加后很怎样?

参考回答:

cuda()将操作对象放在GPU内存中,加了cuda()的Tensor放在GPU内存中而没加的Tensor放在CPU内存中,所以这两个Tensor相加会报错。

● python中dict和list的区别,dict的内部实现

参考回答:

dict查找速度快,占用的内存较大,list查找速度慢,占用内存较小,dict不能用来存储有序集合。Dict用{}表示,list用[]表示。

dict是通过hash表实现的,dict为一个数组,数组的索引键是通过hash函数处理后得到的,hash函数的目的是使键值均匀的分布在数组中。

● Java虚拟机内存的划分

参考回答:

程序计数器,本地方法栈,虚拟机栈,堆,方法区和运行时的常量池。

● python dict按照value进行排序

参考回答:

按照value从大到小排序:

sorted(d.items(),key = lambda x:x[1],reverse = True)

按照value从小到大排序:

sorted(d.items(),key = lambda x:x[1],reverse =False)

● C++中static关键字的作用

参考回答:

同时编译多个文件时,所有未加static前缀的全局变量和函数都具有全局可见性,所以加了static关键字的变量和函数可对其它源文件隐藏。还可以保持变量内容的持久性。用static前缀作为关键字的变量默认的初始值为0。

● 虚函数和纯虚函数的区别

参考回答:

含有纯虚函数的类称为抽象类,只含有虚函数的类不能称为抽象类。虚函数可以直接被使用,也可以被子类重载以后以多态形式调用,而纯虚函数必须在子类中实现该函数才可使用,因为纯虚函数在基类中只有声明而没有定义。虚函数必须实现,对虚函数来说父类和子类都有各自的版本。

● Python多进程

参考回答:

方式一: os.fork()

方式二:使用multiprocessing模块:创建Process的实例,传入任务执行函数作为参数

方式三:使用multiprocessing模块:派生Process的子类,重写run方法

方式四:使用进程池Pool

● 深拷贝,浅拷贝,写一个出来(写了个自己认为对的版本)

参考回答:

深拷贝与浅拷贝的区别

深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。

浅复制 —-只是拷贝了基本类型的数据,而引用类型数据,复制后也是会发生引用,我们把这种拷贝叫做“(浅复制)浅拷贝”,换句话说,浅复制仅仅是指向被复制的内存地址,如果原地址中对象被改变了,那么浅复制出来的对象也会相应改变。

深复制 —-在计算机中开辟了一块新的内存地址用于存放复制的对象。

浅拷贝实例

//此递归方法不包含数组对象

var obj = { a:1, arr: [2,3] };
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
var newobj = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
newobj[prop] = src[prop];
}
}
return newobj;
}

深拷贝实例

而深复制则不同,它不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上。这就不会存在上面obj和shallowObj的arr属性指向同一个对象的问题。

var obj = {
a:1,
arr: [1,2],

nation : '中国',

birthplaces:['北京','上海','广州']

};

var obj2 = {name:'杨'};

obj2 = deepCopy(obj,obj2);
console.log(obj2);

//深复制,要想达到深复制就需要用递归

function deepCopy(o,c){
var c = c || {};
for(var i in o){
if(typeof o[i] === 'object'){

//要考虑深复制问题了

if(o[i].constructor === Array){

//这是数组

c[i] =[];
}else{

//这是对象

c[i] = {};
}
deepCopy(o[i],c[i]);
}else{
c[i] = o[i];
}
}
return c
}

● 在程序里面智能指针的名字是啥?

参考回答:

一个是shared_ptr允许多个指针指向同一个对象;一个是unique_ptr独占所指向的对象;还有一种伴随类weak_ptr他是一种弱引用 指向shared_ptr所指向的对象。

● new,malloc区别

参考回答:

1).malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

2).对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

3).因此C++语言需要一个能完成动态内存分配和初始化工作的运算符new,以一个能完成清理与释放内存工作的运算符delete。注意new/delete不是库函数。

4).C++程序经常要调用C函数,而C程序只能用malloc/free管理动态内存

● 纯虚函数怎么定义,写一个出来

参考回答:

纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。这就是纯虚函数的作用。

纯虚函数是一种特殊的虚函数,它的一般格式如下:

class <类名>

{

virtual <类型><函数名>(<参数表>)=0;

};

● 函数后面接const是什么意思?

参考回答:

这是把整个函数修饰为const,意思是“函数体内不能对成员数据做任何改动”。如果你声明这个类的一个const实例,那么它就只能调用有const修饰的函数

● 写一个函数指针

参考回答:

#include<iostream>
using namespace std;

int compute(int a, int b, int(*func)(int, int)) {  //函数指针

return func(a, b);
}
int max(int a, int b) {
return (a > b) ? a : b;
}
int min(int a, int b) {
return(a < b) ? a : b;
}
int add(int a, int b) {
return a + b;
}
int main() {
int m, n, res_max, res_min, res_add;

类型

abstract class

Interface

定义

abstract class关键字

Interface关键字

继承

抽象类可以继承一个类和实现多个接口;子类只可以继承一个抽象类

接口只可以继承接口(一个或多个);子类可以实现多个接口

访问修饰符

抽象方法可以有publicprotecteddefault这些修饰符

接口方法默认修饰符是public

不可以使用其它修饰符

方法实现

可定义构造方法,可以有抽象方法和具体方法

接口完全是抽象的,没构造方法,且方法都是抽象的,不存在方法的实现

实现方式

子类使用extends关键字来继承抽象类。如果子类不是抽象类的话,它需要提供抽象类中所有声明的方法的实现

子类使用关键字implements来实现接口。它需要提供接口中所有声明的方法的实现

作用

了把相同的东西提取出来,即重用

为了把程序模块进行固化的契约,是为了降低偶合

cin >> m >> n;
res_max = compute(m, n, max);
res_min = compute(m, n, &min);
res_add = compute(m, n, add);
cout << res_max << res_min << res_add << endl;
return 0;
}

● 有看过c++的一些库吗?

参考回答:

标准库

C++标准库,包括了STL容器,算法和函数等。

C++ Standard Library:是一系列类和函数的集合,使用核心语言编写,也是C++ISO自身标准的一部分。

Standard Template Library:标准模板库

C POSIX library:POSIX系统的C标准库规范

ISO C++ Standards Committee:C++标准委员会

框架

C++通用框架和库

Apache C++ Standard Library:是一系列算法,容器,迭代器和其他基本组件的集合

ASL:Adobe源代码库提供了同行的评审和可移植的C++源代码库。

Boost:大量通用C++库的集合。

BDE:来自于彭博资讯实验室的开发环境。

Cinder:提供专业品质创造性编码的开源开发社区。

Cxxomfort:轻量级的,只包含头文件的库,将C++ 11的一些新特性移植到C++03中。

Dlib:使用契约式编程和现代C++科技设计的通用的跨平台的C++库。

EASTL:EA-STL公共部分

ffead-cpp:企业应用程序开发框架

Folly:由Facebook开发和使用的开源C++库

JUCE:包罗万象的C++类库,用于开发跨平台软件

libPhenom:用于构建高性能和高度可扩展性系统的事件框架。

LibSourcey :用于实时的视频流和高性能网络应用程序的C++11 evented IO

LibU:C语言写的多平台工具库

Loki:C++库的设计,包括常见的设计模式和习语的实现。

MiLi:只含头文件的小型C++库

openFrameworks :开发C++工具包,用于创意性编码。

Qt:跨平台的应用程序和用户界面框架

Reason:跨平台的框架,使开发者能够更容易地使用Java,.Net和Python,同时也满足了他们对C++性能和优势的需求。

ROOT:具备所有功能的一系列面向对象的框架,能够非常高效地处理和分析大量的数据,为欧洲原子能研究机构所用。

STLport:是STL具有代表性的版本

STXXL:用于额外的大型数据集的标准模板库。

Ultimate++:C++跨平台快速应用程序开发框架

Windows Template Library:用于开发Windows应用程序和UI组件的C++库

Yomm11:C++11的开放multi-methods.

● c++你看的最久的一章是哪一章,c++primer最熟哪一章

参考回答:

指针那一章看的最久,数组那一章最熟。

● 开发环境、语言的掌握

参考回答:

熟悉Linux常用命令,熟练使用SVN、FTP,熟练使用Keras及常见IDE;熟练使用Java,Python,了解C,C++,Matlab

● Python 多进程

参考回答:

方式一: os.fork()

方式二:使用multiprocessing模块:创建Process的实例,传入任务执行函数作为参数

方式三:使用multiprocessing模块:派生Process的子类,重写run方法

方式四:使用进程池Pool

● Python 锁

参考回答:

Python中的各种锁:

一、全局解释器锁(GIL)

1、什么是全局解释器锁

每个CPU在同一时间只能执行一个线程,那么其他的线程就必须等待该线程的全局解释器,使用权消失后才能使用全局解释器,即使多个线程直接不会相互影响在同一个进程下也只有一个线程使用cpu,这样的机制称为全局解释器锁(GIL)。GIL的设计简化了CPython的实现,使的对象模型包括关键的内建类型,如:字典等,都是隐含的,可以并发访问的,锁住全局解释器使得比较容易的实现对多线程的支持,但也损失了多处理器主机的并行计算能力。

2、全局解释器锁的好处

1)、避免了大量的加锁解锁的好处

2)、使数据更加安全,解决多线程间的数据完整性和状态同步

3、全局解释器的缺点

多核处理器退化成单核处理器,只能并发不能并行。

4、GIL的作用:

多线程情况下必须存在资源的竞争,GIL是为了保证在解释器级别的线程唯一使用共享资源(cpu)。

二、同步锁

1、什么是同步锁?

同一时刻的一个进程下的一个线程只能使用一个cpu,要确保这个线程下的程序在一段时间内被cpu执,那么就要用到同步锁。

2、为什么用同步锁?

因为有可能当一个线程在使用cpu时,该线程下的程序可能会遇到io操作,那么cpu就会切到别的线程上去,这样就有可能会影响到该程  序结果的完整性。

3、怎么使用同步锁?

只需要在对公共数据的操作前后加上上锁和释放锁的操作即可。

4、同步锁的所用:

为了保证解释器级别下的自己编写的程序唯一使用共享资源产生了同步锁。

三、死锁

1、什么是死锁?

指两个或两个以上的线程或进程在执行程序的过程中,因争夺资源或者程序推进顺序不当而相互等待的一个现象。

2、死锁产生的必要条件?

互斥条件、请求和保持条件、不剥夺条件、环路等待条件

3、处理死锁的基本方法?

预防死锁、避免死锁(银行家算法)、检测死锁(资源分配)、解除死锁:剥夺资源、撤销进程

四、什么是递归锁?

在Python中为了支持同一个线程中多次请求同一资源,Python提供了可重入锁。这个RLock内部维护着一个Lock和一个counter变量,counter记录了acquire的次数,从而使得资源可以被多次require。直到一个线程所有的acquire都被release,其他的线程才能获得资源。递归锁分为可递归锁与非递归锁。

五、什么是乐观锁?

假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。

六、什么是悲观锁?

假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。

七、python常用的加锁方式?

互斥锁、可重入锁、迭代死锁、互相调用死锁、自旋锁。