java和Python的区别

Python比java简单,学习成本低,开发效率高
java运行效率比Python高
java是一种静态类型的语言,Python则是动态类型的语言
java中的所有变量需要先声明类型才能使用,Python中的变量不需要声明类型
java编译后才能运行,Python直接就可以运行

Python的生成器

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

python中is和==的区别

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

python方法解析顺序

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

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函数的目的是使键值均匀的分布在数组中。

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)

虚函数和纯虚函数的区别

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

Python多进程

方式一: os.fork()
方式二:使用multiprocessing模块:创建Process的实例,传入任务执行函数作为参数
方式三:使用multiprocessing模块:派生Process的子类,重写run方法
方式四:使用进程池Pool

python 锁

全局解释器锁(GIL):
功能:在 CPython 解释器中执行的每一个 Python线程,都会先锁住自己,以阻止别的线程执行。
CPython 不可能容忍一个线程一直独占解释器,它会轮流执行 Python 线程。这样一来,用户看到的就是“伪”并行,即 Python 线程在交替执行,来模拟真正并行的线程。

每个线程在执行时候都需要先获取GIL,保证同一时刻只有一个线程可以执行代码,即同一时刻只有一个线程使用CPU,也就是说多线程并不是真正意义上的同时执行。

什么时候会释放Gil锁?

  • 遇到像 i/o操作这种 会有时间空闲情况 造成cpu闲置的情况会释放Gil
  • 会有一个专门ticks进行计数 一旦ticks数值达到100 这个时候释放Gil锁 线程之间开始竞争Gil锁(说明:ticks这个数值可以进行设置来延长或者缩减获得Gil锁的线程使用cpu的时间)

互斥锁和Gil锁的关系?
Gil锁 : 保证同一时刻只有一个线程能使用到cpu
互斥锁 : 多线程时,保证修改共享数据时有序的修改,不会产生数据修改混乱

同步锁
死锁
递归锁
乐观锁
悲观锁

常用的加锁方式:互斥锁、可重入锁、迭代死锁、互相调用死锁、自旋锁。

python类初始化过程

在执行类的初始化的时候,比如a = A(),先是执行了new(cls) 方法,根据传入的cls来分配空间,然后再执行对象的init(self) 方法。cls为类,self为类实例,类函数需要传入self,类似于C++里的this指针。

python中的new和init区别

均是Python面向对象语言中的函数
new是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。
init是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候。是一个实例方法。

python什么特性你觉得比较好

迭代器

python的迭代器

在Python中,迭代器是遵循迭代协议的对象,用来表示一连串数据流。重复调用迭代器的next()方法(或将其传给内置函数 next())将逐个返回数据流中的项。当没有数据可用时则将引发 StopIteration 异常。

xrange和range的区别

xrange返回的是一个可迭代的对象(生成器)
range返回的是一个列表

xrange函数在Python3中已经取消,在python3中,range()这种实现被移除了,保留了xrange()的实现,且将xrange()重新命名成range()。所以Python3不能使用xrange,只能使用rangexrange

dictionary中key和value的限制

键必须是唯一的,但值则不必。值可以取任何数据类型。
key可以用字符串、整数、浮点型、true|false、元组来定义,不可以使用列表和字典来定义

Python 元组和列表的区别,元组怎么转列表

元组比列表的运算速度快,而且元组的数据比较安全,因为元组是不可改变的,为了包括其内容不被外部接口修改;列表是可以更改的。

直接转换
lists = [1,2,3]
tup = (1,2)
元组–>列表 list(tup)
列表–>元组 tuple(lists)

python 垃圾回收机制

python内部实现了自动的垃圾回收,而无需用户考虑什么时候销毁一个对象或变量。python的垃圾回收机制是以引用计数机制为主,标记-清除和分代收集两种机制为辅的综合方案。

引用计数–>标记-清除–>分代回收

引用计数:当一个对象的引用计数为0,那说明没有任何变量使用了该对象,所以这个对象就是垃圾对象被销毁。引用计数简单方便但是也有弊端:计数占用内存、在相互引用的对象中计数永远不会变为0,所以还引入了标记-清除和分代回收。
还会存在循环引用的问题,当若干对象相互引用,会造成每个对象的引用计数都不会为0,这样这些对象所占用的内存永远不会被回收。

标记-清除:为了解决引用计数器循环引用的不足。GC会对所有对象打上标记,分为活动对象和非活动对象。Python中通过一个directed graph进行对所有对象的标记维护。沿着途中的所有引用,从root object遍历,能到达的对象为活动对象,无法到达的对象为非活动对象。GC首先会把这些标记为非活动对象的object回收

分代回收:分代回收是一种以空间换时间的操作方式,Python将内存根据对象的存活时间划分为不同的集合,每个集合称为一个代,Python将内存分为了3“代”,分别为年轻代(第0代)、中年代(第1代)、老年代(第2代),他们对应的是3个链表,它们的垃圾收集频率与对象的存活时间的增大而减小。新创建的对象都会分配在年轻代,年轻代链表的总数达到上限时,Python垃圾收集机制就会被触发,把那些可以被回收的对象回收掉,而那些不会回收的对象就会被移到中年代去,依此类推,老年代中的对象是存活时间最久的对象,甚至是存活于整个系统的生命周期内。同时,分代回收是建立在标记清除技术基础之上。分代回收同样作为Python的辅助垃圾收集技术处理那些容器对象.

之字形打印

多层MLP可以拿来训练吗,初始化全是同一值有什么问题,relu的缺点,tensorflow如何处理不可导的情况

一个矩阵从左上到右下最小路径和
一颗二叉树最长路径

不用加减乘除做加法(只做各位相加不进位;做进位;将前面两个结果相加)
堆排序
最大的子序和(简单的动态规划)
学生成绩的第1000名(成绩是整数且有最大值,可以统计一遍信息,然后二分查找)

聊聊项目中的一些bad case

给一个任务:垃圾邮件分类,分阶段和流程细致描述一下每一步应该怎么做,以及最终要优化的效果。