互联网协议定义(分别有4层、5层及7层协议的说法,以下从上层向下层介绍)?

a) 四层协议:应用层、传输层、网络层、网络接口层

a) 五层协议:

应用层:用户使用的应用程序都归属于应用层,作用为规定应用程序的数据格式。

传输层:网络层帮我们找到主机,但是区分应用层的应用就是靠端口,所以传输层就是建立端口到端口的通信。(端口范围0-65535,0-1023为系统占用端口)

网络层:区分不同的广播域或者子网(否则发送一条数据全世界都会受到,是灾难)。

数据链路层:定义电信号的分组方式。

物理层:基于电器特性发送高低点电压(电信号),高电压对应数字1,低电压对应数字0。

C)七层协议:(应用层、表示层、会话层)、传输层、网络层、(数据链路层、物理层)

传输层基于tcp协议的三次握手和四次挥手?

答:传输层有两种数据传输协议,分别为TCP协议和UDP协议,其中TCP协议为可靠传输,数据包没有长度设置,理论可以无限长,而UDP协议为不可靠传输,报头一共就8个字节。Tcp的三次握手和四次挥手定义为:建立连接时三次握手完成建立连接,然后传输数据,断开连接时是四次挥手。所以tcp传输数据是安全的。

为什么连接的时候是三次握手,关闭的时候却是四次挥手?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

什么是socket?

socket是在应用层和传输层之间的一个抽象层,它把TCP/IP层复杂的操作抽象为几个简单的接口供应用层调用以实现进程在网络中通信。

什么是多路复用和多路复用要解决的问题?

多道技术的实现就是为了解决多个程序竞争或者共享同一个资源(比如cpu)的有序调度问题,解决方式即是多路复用。多路复用分为时间上的复用和空间上的复用,空间上的多路复用是指将内存分为几部分,每一部分放一个程序,这样同一时间内存中就有多道程序,前提保证内存是分割;时间上的多路复用是指多个程序需要在一个cpu上运行,不同的程序轮流使用cpu,当某个程序运行的时间过长或者遇到I/O阻塞,操作系统会把cpu分配给下一个程序,保证cpu处于高使用率,实现伪并发。

并发与并行的区别?

并发不是并行,但看起来像是同时运行的,单个cpu和多道技术就可以实现并发;并行也属于并发,指的是同时运行,只有具备多个cpu才能实现并行。

进程、线程、协程的定义?

进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独立的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。

线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

进程、线程、协程的区别?

线程是指进程内的一个执行单元,也是进程内的可调度实体。线程与进程的区别:
1) 地址空间:线程是进程内的一个执行单元,进程内至少有一个线程,它们共享进程的地址空间,而进程有自己独立的地址空间
2) 资源拥有:进程是资源分配和拥有的单位,同一个进程内的线程共享进程的资源
3) 线程是处理器调度的基本单位,但进程不是
4) 二者均可并发执行

5) 每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口,但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制

协程多与线程进行比较:

1) 一个线程可以多个协程,一个进程也可以单独拥有多个协程,这样python中则能使用多核CPU。

2) 线程进程都是同步机制,而协程则是异步

3) 协程能保留上一次调用时的状态,每次过程重入时,就相当于进入上一次调用的状态

进程同步锁概念介绍

进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件或者打印终端是可以的。共享带来了竞争,竞争的结果就是混乱。解决办法就是加锁处理。加锁可以保证多个进程修改同一块数据时,同一时间只能有一个任务可以进行修改,即串行的修改,没错,速度是慢了,但牺牲了速度却保证了数据安全。

生产者消费者模型?

程序中有两类角色:一类负责生产数据(生产者),一类负责处理数据(消费者);引入生产者消费者模型为了解决的问题是:平衡生产者与消费者之间的工作能力,从而提高程序整体处理数据的速度;如何实现:生产者<-->队列<——>消费者;生产者消费者模型实现类程序的解耦和。

进程与线程的关系?

进程如一个车间,线程如车间内的一条流水线;创建进程需要申请特别的内存空间(车间),各进程间是竞争关系,所以创建进程的开销大;而多个线程属于同一个进程(车间),线程间共享进程中的资源,属于合作关系,所以创建线程开销小。所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

什么是协程?

协程是单线程下的并发,本质就是在单线程下,由用户自己控制一个任务遇到io阻塞了就切换另外一个任务去执行,以此来提升效率。

优点:协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级;单线程内就可以实现并发的效果,最大限度地利用cpu

缺点:协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程;协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

数据库分类

关系型数据库:如sqllite,db2,oracle,access,sql server,MySQL,注意:sql语句通用,需要有表结构;非关系型:mongodb,redis,memcache,非关系型数据库是key-value存储的,没有表结构。

MyISAM和InnoDB搜索引擎的特点

存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方法。所以存储引擎也可以称为表类型。

MyISAM:
    特点:
    (1)不支持事务:MyISAM存储引擎不支持事务,所以对事务有要求的业务场景不能使用
    (2)表级锁定:其锁定机制是表级索引,这虽然可以让锁定的实现成本很小但是也同时大大降低了其并发性能
    (3)读写互相阻塞:不仅会在写入的时候阻塞读取,MyISAM还会在读取的时候阻塞写入,但读本身并不会阻塞另外的读
    (4)只会缓存索引:MyISAM可以通过key_buffer缓存以大大提高访问性能减少磁盘IO,但是这个缓存区只会缓存索引,而不会缓存数据
    适用场景:
    (1)不需要事务支持(不支持)
    (2)并发相对较低(锁定机制问题)
    (3)数据修改相对较少(阻塞问题)
    (4)以读为主
    (5)数据一致性要求不是非常高
InnoDB:
    特点:
    (1)具有较好的事务支持:支持4个事务隔离级别,支持多版本读
    (2)行级锁定:通过索引实现,全表扫描仍然会是表锁,注意间隙锁的影响
    (3)读写阻塞与事务隔离级别相关
    (4)具有非常高效的缓存特性:能缓存索引,也能缓存数据
    (5)整个表和主键以Cluster方式存储,组成一颗平衡树
    (6)所有Secondary Index都会保存主键信息
    适用场景:
    (1)需要事务支持(具有较好的事务特性)
    (2)行级锁定对高并发有很好的适应能力,但需要确保查询是通过索引完成
    (3)数据更新较为频繁的场景
    (4)数据一致性要求较高
    (5)硬件设备内存较大,可以利用InnoDB较好的缓存能力来提高内存利用率,尽可能减少磁盘 IO

char 和varchar字符串类型的区别?

char类型:定长,存入字符长度大于设置长度时报错,存入字符长度小于设置长度时,会用空格填充,达到设置字符长度,简单粗暴,浪费空间,存取速度快。

Varchar类型:varchar类型存储数据的真实内容,不会用空格填充,会在真实数据前加1-2Bytes的前缀,该前缀用来表示真实数据的bytes字节数,变长,精准,节省空间,存取速度慢。

虽然varchar使用起来较为灵活,但是从整个系统的性能角度来说,char数据类型的处理速度更快,有时甚至可以超出varchar处理速度的50%。因此,用户在设计数据库时应当综合考虑各方面的因素,以求达到最佳的平衡。

foreign key外键关联(一对多)实例。

create table press(

id int primary key auto_increment,

name varchar(20)

);

create table book(

id int primary key auto_increment,

name varchar(20),

press_id int not null,

foreign key(press_id) references press(id)

on delete cascade

on update cascade

);

mysql索引相关介绍。

索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。

上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。建立索引会占用磁盘空间的索引文件。

联合索引命中规则是:最左匹配规则,如下联合索引(姓名,年龄,性别):

诸如select * from user where name= ‘zzz’ and sex=’male’ and age=18查询语句,当对name、sex、age分别建立列索引和建立(name、sex、age)组合索引时,查询的结果是不一样的,组合索引效率高于多个列索引,因为在执行多个列索引的时候,mysql只会选择其中一个效率最高的。但是通过组合索引就直接锁定那一条信息了。由于组合索引的最左匹配原则,上述组合索引相当于分别建立(name),(name、sex),(name、sex、age)这样的三个索引,只有查询条件与这三个顺序相一致的才会用到组合索引。

MySQL在以下操作场景下会使用索引

1) 快速查找符合where条件的记录
2) 快速确定候选集。若where条件使用了多个索引字段,则MySQL会优先使用能使候选记录集规模最小的那个索引,以便尽快淘汰不符合条件的记录。
3) 如果表中存在几个字段构成的联合索引,则查找记录时,这个联合索引的最左前缀匹配字段也会被自动作为索引来加速查找。
例如,若为某表创建了3个字段(c1, c2, c3)构成的联合索引,则(c1), (c1, c2), (c1, c2, c3)均会作为索引,(c2, c3)就不会被作为索引,而(c1, c3)其实只利用到c1索引。
4) 多表做join操作时会使用索引(如果参与join的字段在这些表中均建立了索引的话)。
5) 若某字段已建立索引,求该字段的min()或max()时,MySQL会使用索引。
6) 对建立了索引的字段做sort或group操作时,MySQL会使用索引。

redis如何做持久化?

因为Redis是内存型数据库,所以为了防止因为系统崩溃等原因导致数据丢失的问题,Redis提供了两种不同的持久化方法来将数据存储在硬盘里面,一种方法是快照(RDB),它可以将存在于某一个时刻的所有数据都写入到硬盘里面,另外一种方法是只追加文件(AOF),它会在执行写命令时,将被执行的写命令都写入到硬盘里面。

快照持久化:Redis可以通过创建快照来获得在内存里面的数据在某一个时间点上的副本。在创建快照之后,用户可以对快照进行备份,可以将快照复制到其它服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务器时使用。在只使用快照持久化来保存数据时,如果系统真的发生崩溃,用户将丢失最近一次生成快照之后更改的所有数据。因此,快照持久化只适用于那些即使丢失一部分数据也不会造成问题的应用程序。有两个命令可以用于生成RDB文件,一个是SAVE,另外一个BGSAVE。

SAVE特点:SAVE命令会阻塞Redis服务器进程,直到RDB文件创建完毕,在服务器进程阻塞期间,服务器不能处理任何命令请求。缺点:服务器持久化期间无法接受其它请求。

BGSAVE特点:BGSAVE命令则会派生出一个子进程,然后由子进程负责创建RDB文件,服务器进程则继续处理命令请求。缺点:创建子进程所耗费的时间会随着Redis占用的内存而增加。

文件持久化:AOF持久化会将被执行的写命令写到AOF文件的末尾,以此来纪录数据所发生的变化,因此,Redis只要从头到尾重新执行一次AOF文件所包含的所有写命令,就可以恢复AOF文件所记录的数据集。因为Redis会不断的将被执行的写命令纪录到AOF文件里面,所以随着Redis不断执行,AOF文件的体积也会不断增长,极端条件下,AOF甚至可能会用完硬盘的所有可用空间。为了解决上面的缺点,Redis提供了BGREWRITEAOF命令,这个命令会通过移除AOF文件中的冗余命令来重写AOF文件,使得AOF文件尽可能的小。它的原理和BGSAVE命令相似,Redis会创建一个子进程,然后由子进程负责对AOF文件进行重写,因为AOF文件重写也需要用到子进程,所以同样存在快照持久化因为创建子进程所导致的性能问题和内存占用问题。

django的http请求流程

http协议与https协议的区别?

HTTP:是互联网上应用最为广泛的一种网络协议,是一个客户端和服务器端请求和应答的标准(TCP),用于从WWW服务器传输超文本到本地浏览器的传输协议,它可以使浏览器更加高效,使网络传输减少。

HTTPS:是以安全为目标的HTTP通道,简单讲是HTTP的安全版,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL,作用有:一种是建立一个信息安全通道,来保证数据传输的安全;另一种就是确认网站的真实性。

1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。

2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。

3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。

4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。

websocket协议?

http协议:HTTP 协议是一种无状态的、无连接的、单向的应用层协议。它采用了请求/响应模型。通信请求只能由客户端发起,服务端对请求做出应答处理。HTTP 协议无法实现服务器主动向客户端发起消息。

Websocket协议:WebSocket 连接允许客户端和服务器之间进行全双工通信,以便任一方都可以通过建立的连接将数据推送到另一端。WebSocket 只需要建立一次连接,就可以一直保持连接状态。

轮训(ajax):首先是 ajax轮询 ,ajax轮询 的原理非常简单,让浏览器隔个几秒就发送一次请求,询问服务器是否有新信息。

长轮训:其实原理跟 ajax轮询 差不多,都是采用轮询的方式,不过采取的是阻塞模型(一直打电话,没收到就不挂电话),也就是说,客户端发起连接后,如果没消息,就一直不返回Response给客户端。直到有消息才返回,返回完之后,客户端再次建立连接,周而复始。

单列模式

# 方式一:基于@classmethod
import threading
class Singleton(object):
    instance_clock = threading.Lock()

    def __init__(self):
        pass
    @classmethod
    def instance(cls,*args,**kwargs):
        if not hasattr(Singleton,"_instance"):
            with Singleton.instance_clock:
                if not hasattr(Singleton,"_instance"):
                    Singleton._instance = Singleton(*args,**kwargs)
        return Singleton._instance
# 方式二:基于__new__
import  threading

class Singlton(object):
    def __init__(self):
        pass
    instance_lock = threading.Lock()
    def __new__(cls, *args, **kwargs):
         if not hasattr(Singlton,"_instance"):
             with Singlton.instance_lock:
                 if not hasattr(Singlton,"_instance"):
                     Singlton._instance = object.__new__(cls,*args,**kwargs)

         return Singlton._instance

递归实现二分查找实例

pass

冒泡排序

def bubble_sort(li):
    for i in range(len(li)-1):
        exchange=False
        for j in range(len(li)-i-1):
            if li[j] >li[j+1]:
                li[j],li[j+1]=li[j+1],li[j]
                exchange=True
        if not exchange:
            return

选择排序

def select_sort(li):
    for i in range(len(li)-1):
        min_index = i
        for j in range(i+1,len(li)):
            if li[j]<li[min_index]:
                min_index = j
        if min_index != i:
            li[i],li[min_index] = li[min_index],li[i]

解释什么叫栈溢出,在什么情况下可能出现?

栈是一种后进先出的数据结构,堆栈也是采用这种结构管理内存,调用过程中当最初的结果依赖于后面的计算处理,那么后面的部分虽然后开始处理,却先结束。当后续处理太多并且又依赖更后面的处理......(比如递归),便会一直压栈,当空间全部用完,就会造成“堆栈溢出”。
在Python中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。

简述cpython的内存管理机制

包括如下三种机制:
(1)引用计数机制:在Python中,整数和短小的字符,Python都会缓存这些对象,以便重复使用。赋值语句,只是创造了新的引用,而不是对象本身。长的字符串和其它对象可以有多个相同的对象,可以使用赋值语句创建出新的对象。每个对象都有存有指向该对象的引用总数,即引用计数(reference count)。
(2)垃圾回收机制:引用计数也是一种垃圾收集机制,而且也是一种最直观,最简单的垃圾收集技术。当Python的某个对象的引用计数降为0时,说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。
(3)内存池机制:Python的内存机制呈现金字塔形状,-1,-2层主要有操作系统进行操作;第0层是C中的malloc,free等内存分配和释放函数进行操作;第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;第3层是最上层,也就是我们对Python对象的直接操作;
Python在运行期间会大量地执行malloc和free的操作,频繁地在用户态和核心态之间进行切换,这将严重影响Python的执行效率。为了加速Python的执行效率,Python引入了一个内存池机制,用于管理对小块内存的申请和释放。 Python内部默认的小块内存与大块内存的分界点定在256个字节,当申请的内存小于256字节时,
PyObject_Malloc会在内存池中申请内存;当申请的内存大于256字节时,PyObject_Malloc的行为将蜕化为malloc的行为。

列举你知道的python魔法方法及用途

# (1)__getattr__:获取一个并不存在的属性的时候就会调用,而如果这个属性存在则不会调用该方法。如下:
class Test(object):
    def __init__(self, world):
        self.world = world

    def __getattr__(self, item):
        return item

x = Test('world123')
print(x.world)   # 输出world123
print (x.pppp)   # 输出pppp

# (2)__getattribute__:比__getattr__更加强大,他可以拦截所有的属性获取行为。如下:
class Test(object):
    def __init__(self, world):
        self.world = world

    def __getattribute__(self, item):
        print ('get_something: %s' % item)
        return (item)

x = Test(123)
print( x.world)     # get_something: world    world
print(x.pppp)       # get_something: pppp     pppp

# (3)__setattr__:是设置参数的时候会调用到的魔法方法,相当于设置参数前的一个钩子。每个设置属性的方法都绕不开这个魔法方法,只有拥有这个魔法方法的对象才可以设置属性。
class Test(object):
    def __init__(self, world):
        self.world = world

    def __setattr__(self, name, value):
        if name == 'value':
            object.__setattr__(self, name, value - 100)
        else:
            print(111)
            object.__setattr__(self, name, value)

x = Test(123)    #实例化时就会执行__setattr__方法
print(x.world)
x.value = 200
print (x.value

# (4)__delattr__:与__setattr__特别相似,执行如 del self.name删除属性时,会执行__delattr__
class Test(object):
    def __init__(self, world):
        self.world = world

    def __delattr__(self, item):
        print ('hahaha del something')
        object.__delattr__(self, item)

x = Test(123)
del x.world
print (x.world)   # 报错

代码出现以下异常的原因

IndexError:索引异常,如列表索引取值时,索引不存在会抛此异常
AttributeError:属性异常,如实例化对象获取没有的属性就会抛出此异常
AssertionError:断言语句失败抛出的异常
NotImplementedError:尚未实现的方法时抛出的异常
StopIteration:迭代器没有更多值的时候。
TypeError:传入对象与要求不符
IndentationError:缩进错误

简述你对GIL的理解

首先明确GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念。每次执行python程序,都会开启一个进程,在此进程不但有主线程,还有主线程开启的其他子线程,同时包括垃圾回收等解释器级别的线程,这些线程在同一个进程,共享进程中的数据。所有的线程访问解释器代码,拿到执行权限,因为解释器数据共享,所以可能出现垃圾回收在回收解释器中数据的同时另一个线程在对数据做修改,这样就会导致数据的不可靠。为了解决这个问题,cpython解释器干脆给解释器加一把互斥锁,每个线程只有拿到解释器锁才能访问解释器代码,其他线程等待解释器锁被释放后才能访问,从而保证了解释器级别的数据安全。结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。

简述以下内置函数的用法:reduce  map   any    all

(1)reduce:
    用传给reduce中的函数 function(有两个参数)先对集合中的第 1、2 个元素进行操作,得到的结果再与第三个数据用
    function 函数运算,最后得到一个结果。
from functools import reduce
def add(x,y):
    return x+y
result = reduce(add,[1,2,3,4,5])
print(result)

(2)map:
    第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表。
    function可以是一个参数,也可以是两个参数,对应的就需要一个或者两个参数序列。
实例一:
result1 = map(lambda x: x ** 2, [1, 2, 3, 4, 5])
print(result1)          #python3中为迭代器,python2为列表
for i in result1:
    print(i)
实例二:
result2 = map(lambda x, y: x + y, [1, 3, 5, 7, 9], [2, 4, 6, 8, 10])
print(result2)          #python3中为迭代器,python2为列表

(3)any:
    函数用于判断给定的可迭代参数 iterable 中的所有元素,有一个为真时返回True,所有为假时返回False
示例:
print(any([1,0,'']))       #True
print(any([False,0,'']))   #False

(4)all:
    函数用于判断给定的可迭代参数 iterable 中的所有元素,所有元素为真时返回True,有一个为假时返回False

copy和deepcopy的区别是什么?

python中,变量的存储采用了引用语义的方式,即变量存储不是值本身,而是值的内存地址,对于复杂的数据结构,如列表字典等,
变量存储的是数据结构中每个值的存储地址。
使用copy.copy(obj)对对象obj进行浅拷贝,它复制了对象,但是对象中的元素依然使用的是原始引用,所以只要原始引用不发生改
变,原始引用对应的数值发生变化后,也会影响到浅拷贝后的对象。如下实例:

import copy
li=[1,2,3,4]
sourselist=['a','b','c',li]
copylist=copy.copy(sourselist)
li.append('xxx')
print(sourselist)   # ['a', 'b', 'c', [1, 2, 3, 4, 'xxx']]
print(copylist)     # ['a', 'b', 'c', [1, 2, 3, 4, 'xxx']]

使用copy.deepcopy(obj)对对象深拷贝,深拷贝会完全复制原变量相关的所有数据,在内存中重新开辟一块空间,不管数据结构
多么复杂,只要遇到可能发生改变的数据类型,就重新开辟一块内存空间把内容复制下来,直到最后一层,不再有复杂的数据类型,就
保持其原引用。在这个过程中我们对这两个变量中的一个进行任意修改都不会影响其他变量。如下实例:

import copy
li=[1,2,3,4]
sourselist=['a','b','c',li]
copylist=copy.deepcopy(sourselist)
li.append('xxx')
print(sourselist)   # ['a', 'b', 'c', [1, 2, 3, 4, 'xxx']]
print(copylist)     # ['a', 'b', 'c', [1, 2, 3, 4]]

代码中经常遇到的*args和**kwargs的含义及用法

*arg代表任意个位置参数,**kwargs代表任意个关键字参数,使用顺序为def 函数名(位置参数,*args,默认参数,**kwargs),即*arg一定在**kwargs之前。使用见如下实例:

# 实例一:
def test(*args,**kwargs):
    print(args)
    print(kwargs)
test(1,2,a=3,b=4)   # (1, 2)  {'a': 3, 'b': 4}
# 实例二:
def test(*args,**kwargs):
    print(args)
    print(kwargs)

li=(1,2)
dic={'a':3,'b':4}
test(*li,**dic)   # (1, 2)  {'a': 3, 'b': 4}

列举一下你知道的HTTP Header及其功能

Accept:
浏览器端可以接受的媒体类型,通配符 * 代表任意类型
Accept-Encoding:
浏览器申明自己接收的编码方法,例如: Accept-Encoding: zh-CN,zh;q=0.8
Accept-Language:
浏览器申明自己接收的语言,
Connection:
如Connection: keep-alive 当一个网页打开完成后,客户端和服务器之间用于传输HTTP数据的TCP连接不会关闭,
如果客户端再次访问这个服务器上的网页,会继续使用这一条已经建立的连接。
Referer:
当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的,服务器籍此可以获得一些信息用于处理。
User-Agent:
告诉HTTP服务器, 客户端使用的操作系统和浏览器的名称和版本.
Cookie:
Cookie是用来存储一些用户信息以便让服务器辨别用户身份的(大多数需要登录的网站上面会比较常见),比如cookie会存储一些用户的用户名和密码,
当用户登录后就会在客户端产生一个cookie来存储相关信息,这样浏览器通过读取cookie的信息去服务器上验证并通过后会判定你是合法用户,从而允许查看相应网页。

简述cookie和session的区别和联系

1.cookie是保存在浏览器端的键值对,而session是保存的服务器端的键值对,但是依赖cookie。
2.以登录为例,cookie为通过登录成功后,设置明文的键值对,并将键值对发送客户端存,明文信息可能存在泄漏,不安全。
session则是生成随机字符串sessionID,发给用户,并写到浏览器的cookie中,同时服务器自己也会保存一份。
3.在登录验证时,cookie:根据浏览器发送请求时附带的cookie的键值对进行判断,如果存在,则验证通过;
session:在请求用户的cookie中获取随机字符串,根据随机字符串在session中获取其对应的值进行验证

简述什么是浏览器的同源策略

同源指的是一个请求路径中的请求协议、ip及端口和另一个请求路径中的请求协议、ip及端口保持一致。同源策略是浏览器的一个安全功能,
不同源的客户端脚本在没有明确授权的情况下,不能读写对方资源。

简述python上下文管理器原理,并用上下文管理器简单实现将”hello world”,写入文件的功能。

定义:在使用Python编程中,可以会经常碰到这种情况:有一个特殊的语句块,在执行这个语句块之前需要先执行一些准备动作;当语句块执行完成后,需要继续执行一些收尾动作。如操作文件时,操作前打开文件,操作后关闭文件,对于这些情况,Python中提供了上下文管理器(Context Manager)的概念,可以通过上下文管理器来定义/控制代码块执行前的准备动作,以及执行后的收尾动作。

原理:创建一个上下文管理器类型的时候,就需要实现__enter__和__exit__方法,在Python中,可以通过with语句来方便的使用上下文管理器,with语句可以在代码块运行前进入一个运行时上下文(执行__enter__方法),并在代码块结束后退出该上下文(执行__exit__方法)。

with open('test.txt',mode='w',encoding='utf-8') as f:
    f.write("hello world")

简述一致性哈希原理和他要解决的问题

pass

Python中@staticmethod和@classmethod的区别。

在类中总共有三种方法:普通方法(需要参数,使用时默认将类的实例对象传进去,类调用的时候需要传递实例对象),@staticmethod装饰的静态方法与普通函数相同(实例和类均可调用,没有默认的参数传递进去),@classmethod装饰的类方法(需要参数,使用时将调用的类传进去,或者实例对象调用时是将实例对应的类传进去。实例:

class Bar():
    def __init__(self, name):
        self.name = name

    a = 'hello'

    def foo(self):
        print(self.name)

    @classmethod
    def classmethod_foo(cls):
        print(cls.a)

    @staticmethod
    def staticmethod_foo():
        print('world')

obj = Bar('lcg')

obj.foo()  # lcg
Bar.foo(obj)  # lcg

obj.classmethod_foo()  # hello
Bar.classmethod_foo()  # hello

obj.staticmethod_foo()  # world
Bar.staticmethod_foo()  # world

Python里面search()和match()的区别。

首先match()和search()都是只匹配一个结果,但是match()是从字符串开始处进行匹配,匹配成功返回,没有返回None而search()则是从头开始,在整个字符串内匹配。

import re

result1 = re.match('li', 'lichengguangxxx').group()
result2 = re.match('li', 'guangchenglixxx')
print(result1, result2)  # li None

result3 = re.search('li', 'lichengguangxxx').group()
result4 = re.search('li', 'guangchenglixxx').group()
print(result3, result4)  # li li

简述迭代器和生成器以及他们之间的区别?

迭代器就是用于迭代操作的的对象,遵从迭代协议(内部实现了__iter__()和__next__()方法,可以像列表(可迭代对象,只有__iter__()方法)一样迭代获取其中的值,与列表不同的是,构建迭代器的时候,不像列表一样一次性把数据加到内存,而是以一种延迟计算的方式返回元素,即调用next方法时候返回此值。

生成器本质上也是一个迭代器,自己实现了可迭代协议,与生成器不同的是生成器的实现方式不同,可以通过生成器表达式和生成器函数两种方式实现,代码更简洁。生成器和迭代器都是惰性可迭代对象,只能遍历一次,数据取完抛出Stopiteration异常

菲波那切数列

# 计算出前n个fib数列
def fib(n):
    a,b =  1,1
    while n>0:
        n-=1
        yield a
        a,b = b,a+b
print([i for i in fib(10)])
# 计算max之前的fib数列
def fib(max):
    a,b =  1,1
    while a <= max:
        yield a
        a,b = b,a+b
print([i for i in fib(57)])

# 迭代器实现菲波那切数列
class Fib:
    def __init__(self,n):
        self.a = 1
        self.b = 1
        self.n = n
    def __iter__(self):
        return self
    def __next__(self):
        if self.n > 0:
            self.n -= 1
            value = self.a
            self.a,self.b =self.b,self.a +self.b
            return value
        else:
            raise StopIteration()

print([i for i in Fib(10)])

列表表达式与生成器表达式的区别

列表表达式生成是一个列表属于可迭代对象,数据一次性生成,占用内存;生成器表达式结果为一个生成器,具有生成器的特性数据,延迟计算,一次只生成一个结果,只能遍历一遍,取完抛异常,节省内存。

注意:range()属于可迭代对象,不是迭代器或生成器,但是是属于惰性可迭代对象,数据是延迟加载,娶一个生成一个,可以重复遍历获取。

result1 = [i for i in range(10)]
result2 = (i for i in range(10))
print(result1)   # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(result2)   # <generator object <genexpr> at 0x0000021884E24BF8>

什么是装饰器?请用装饰器实现singleton。

装饰器的本质是一个闭包函数,实现的功能是在不修改原函数及调用方式的情况下对原函数进行功能扩展的,是开放封闭原则的典型代表。

def wraper(func):
    def inner(*args,**kwargs):
        print("执行函数前扩展的内容")
        ret=func(*args,**kwargs)
        print("执行函数后扩展的内容")
        return ret
    return inner

@wraper
def index(name,age):
    print("我叫%s,今年%s岁" %(name,age))
index("lcg",22)

装饰器单例:

import threading
class Singleton(object):
    _instance_lock = threading.Lock()
    def __init__(self):
        import time
        time.sleep(3)

    @classmethod
    def instance(cls,*args,**kwagrs):
        if not hasattr(Singleton,'_instance'):
            with Singleton._instance_lock:
                if not hasattr(Singleton, '_instance'):
                    Singleton._instance = Singleton(*args,**kwagrs)
        return Singleton._instance

写一个简单的python sockect编程

# 服务端
from socket import socket

server = socket()
server.bind(('127.0.0.1', 8000))
server.listen(5)
while True:
    conn, addr = server.accept()
    while True:
        data = conn.recv(1024)
        print(data.decode('utf-8'))
        conn.send(data.upper())
    conn.close()
server.close()

# 客户端
from socket import socket

client = socket()
client.connect(('127.0.0.1', 8000))
while True:
    msg = input('>>>').strip()
    if not msg: continue
    client.send(msg.encode('utf-8'))
    data = client.recv(1024).decode('utf-8')
    print('服务端已接收客户端发来的消息并转换为大写', data)
client.close()

有这样一段代码:

a = 10
b = 20
c = [a]
a = 15
print(c)
会输出什么,为什么?

如何下代码(python2.x):

for i in range(1):
    print(i)
for i in xrange(1):
    print(i)

这两段代码输出一样吗?占用系统资源一样吗?为什么要用xrange代替range?

结果一样,但是占用系统资源不一样,range与xrange均属于可迭代对象,通过循环迭代可以取出其中的值,但是xrange属于惰性可迭代对象,虽然不是迭代器,没有next方法,但是有迭代器一样的性质,不会一次性将数据加载到内存,而是通过延迟加载的方式生成数据,取一个生成一个,节省内存资源,与python3中的range相同。

有这样一个url

url:footbar/homework/2009-10-20/xiaoming,其中2009-10-20和xiaoming为变量,请用正则表达式捕获这个url,要求尽量精准.

'^footbar/homework/(?P<date>[0-9]{4}-[0-9]{2}-[0-9]{2})/(?P<name>\w+)$'

当前项目根目录

import os, sys

# 获取当前项目根目录方式一
path1 = os.path.abspath(os.path.dirname(sys.argv[0]))
print(path1)  # D:\WorkSpace\Test
# 获取当前项目根目录方式二
path = os.path.dirname(os.path.abspath(__file__))
print(path)  # D:\WorkSpace\Test

现有两个元组(('a'),('b')),(('c'),('d')),请使用python中匿名函数生成列表[{'a':'c'},{'b':'d'}]

result = map(lambda x, y: {x[0]: y[0]}, (('a'), ('b')), (('c'), ('d')))
print(list(result))  # [{'a': 'c'}, {'b': 'd'}]

# data = zip((('a'), ('b')), (('c'), ('d')))
# print(list(data))  # [('a', 'c'), ('b', 'd')]

django里Queryset的get和filter方法的区别?

get获得是一个对象,filter得到是一个对象列表,即使只有一个满足条件

简述django对http请求的执行流程。

一个 HTTP 请求,首先被转化成一个 HttpRequest 对象,然后该对象被传递给 Request 中间件处理,如果该中间件返回了Response,则直接传递给 Response 中间件做收尾处理。否则的话 Request 中间件将访问 URL 配置,确定哪个 view 来处理,在确定了哪个 view 要执行,但是还没有执行该 view 的时候,系统会把 request 传递给 View 中间件处理器进行处理,如果该中间件返回了Response,那么该Response 直接被传递给 Response 中间件进行后续处理,否则将执行确定的 View 函数处理并返回 Response,在这个过程中如果引发了异常并抛出,会被 Exception 中间件处理器进行处理。

简述django下的(内建的)的缓存机制

缓存是将一些常用的数据保存内存或者memcache中,在一定的时间内有人来访问这些数据时,则不再去执行数据库及渲染等操作,而是直接从内存或memcache的缓存中去取得数据,然后返回给用户.django提供了6中内存缓存机制,分别为:

开发调试缓存(为开发调试使用,实际上不使用任何操作);

内存缓存(将缓存内容缓存到内存中);

文件缓存(将缓存内容写到文件 );
数据库缓存(将缓存内容存到数据库);

memcache缓存(包含两种模块,python-memcached或pylibmc.)。

以上缓存均提供了三种粒度的应用。

django中model的slugfeild类型字段有什么用途?

只包含字母、数字、下划线和连接符,通常用于urls

列表的sort方法和sorted的区别是什么?

list=[-2,1,3,-6],如何实现以绝对值的大小从小到大将list的内容进行排序。

sort 与 sorted 区别:
sort 是应用在 list 上的方法,sorted 可以对所有可迭代的对象进行排序操作。
list 的 sort 方法返回的是对已经存在的列表进行操作,而内建函数 sorted 方法返回的是一个新的 list,而不是在原来的基础上进行的操作。

li = [-2, 1, 3, -6]
li.sort()
print(li)  # [-6, -2, 1, 3]

result = sorted(li)
print(result)  # [-6, -2, 1, 3]

# 以绝对值的的大小从小到大排列
result2 = sorted(li, key=lambda x: abs(x))
print(result2)  # [1, -2, 3, -6]

dic = [("a", 2), ("b", 1), ("c", 3)]
result1 = sorted(dic, key=lambda x: x[1])
print(result1)  # [('b', 1), ('a', 2), ('c', 3)]

Python中变量的作用域(变量的查找顺序)

python中的作用域分4种情况:
(1)L:local,局部作用域,即函数中定义的变量;
(2)E:enclosing,嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的;
(3)G:globa,全局变量,就是模块级别定义的变量;
(4)B:built-in,系统固定模块里面的变量,比如int, bytearray等。
搜索变量的优先级顺序依次是:局部作用域>外层作用域>当前模块中的全局>python内置作用域,也就是LEGB。

Web开发中有哪些技术手段防止sql注入?

sql注入:在sql语句中,如果存在'--'字符,则执行sql语句时会注释掉--字符后面的内容。凡有SQL注入漏洞的程序,
都是因为程序要接受来自客户端用户输入的变量或URL传递的参数,并且这个变量或参数是组成SQL语句的一部分。放置方式有:
1、使用预编译绑定变量的SQL语句 如execute()
2.严格加密处理用户的机密信息
3.不要随意开启生产环境中Webserver的错误显示
4.使用正则表达式过滤传入的参数
5.字符串过滤
6.检查是否包函非法字符

关系型数据库中,表与表之间有左连接、内连接、外连接,分别指出他们的含义及区别?

1、 交叉连接:不使用任何匹配条件生成笛卡尔积
select * from employee,department

2、内连接:只连接匹配的行
selcet employee.name,employee.age,department.name from employee inner join department on employee.dep_id = department.id
3、外连接之左连接:优先显示左表全部内容
selcet employee.name,employee.age,department.name from employee left join department on employee.dep_id = department.id
4、外连接之右连接:优先显示右表全部内容
selcet employee.name,employee.age,department.name from employee right join department on employee.dep_id = department.id
5、全外连接:显示左右两个表全部记录(mysql不支持full join),实现方式如下:
select * from employee left join department on employee.dep_id = department.id
union
select * from employee right join department on employee.dep_id = department.id

解释python脚本程序的"__name__"变量及其作用

每一个python程序脚本在运行的时候,都有一个__name__属性,如果程序是作为模块被引入的,则其__name__属性值则自动被设置为模块名,如果脚本程序独立运行,则其__name__属性则自动被设置为__main__,利用__name__属性即可控制python程序的运行方式。

解释python字符串驻留机制。

Python支持字符串驻留机制,即:对于短字符串,将其赋值给多个不同的对象时,内存中只有一个副本,多个对象共享该副本。这一点不适用于长字符串,即长字符串不遵守驻留机制,下面的代码演示了短字符串和长字符串在这方面的区别。

a = "123"
b = "123"
print(id(a) == id(b))  # True

c = "123" * 50
d = "123" * 50
print(id(c) == id(d))  # False

解释下HTTP常见响应状态码

2XX Success(成功状态码)
    200   表示从客户端发来的请求在服务器端被正常处理
    204   该状态码表示服务器接收的请求已成功处理,但在返回的响应报文中不含实体的主体部分
    206   该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求
3XX Redirection(重定向状态码)
    301   永久性重定向
    302   临时性重定向
4XX Client Error(客户端错误状态码)
    400   该状态码表示请求报文中存在语法错误
    401   该状态码表示发送的请求需要有通过HTTP认证的认证信息
    403   该状态码表明对请求资源的访问被服务器拒绝了。
    404   该状态码表明服务器上无法找到请求的资源
5XX Server Error(服务器错误状态码)
    500   该状态码表明服务器端在执行请求时发生了错误。
    503   该状态码表明服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。

python是如何进行内存管理的

python采用的是基于值的内存管理方式,如果为不同变量赋值相同值,则在内存中只有一份该值,多个变量指向同一块内存地址

mysql中随着数据量的增大,查询速度会越来越慢,请给出简易的优化方案。

1.合理的添加索引(mysql默认只会btree类型索引);
mysql常见的索引:
普通索引INDEX:加速查找

唯一索引:
-主键索引PRIMARY KEY:加速查找+约束(不为空、不能重复)
-唯一索引UNIQUE:加速查找+约束(不能重复)

联合索引:
-PRIMARY KEY(id,name):联合主键索引
-UNIQUE(id,name):联合唯一索引
-INDEX(id,name):联合普通索引
2、避免使用select *
3、创建表时尽量用char代替varchar
4、表的字段顺序,固定长度的优先
5、组合索引代替多个单列索引
6、使用连接(join)代替子查询
7、使用explain优化神器

python自定义栈实例

class Mystack(object):
    def __init__(self):
        self.__items = []

    def size(self):
        return len(self.__items)

    def is_empty(self):
        return self.__items == []

    def push(self, item):
        self.__items.append(item)

    def pop(self):
        return self.__items.pop()

    def peek(self):
        return self.__items[len(self.__items) - 1]

if __name__ == '__main__':
    stack_obj = Mystack()
    stack_obj.push(1)
    stack_obj.push(2)
    stack_obj.push(3)
    print(stack_obj.pop())  # 3
    print(stack_obj.size())  # 2
    print(stack_obj.is_empty())  # Flase

开启多进程实例

方式1

from multiprocessing import Process
import time, random

def Test(name):
    print("welcome to my house %s" % name)
    time.sleep(random.randint(1, 3))
    print("see you next time %s" % name)

if __name__ == '__main__':
    p1 = Process(target=Test, args=('鸣人',))
    p2 = Process(target=Test, args=('佐助',))
    p3 = Process(target=Test, args=('小樱',))

    p1.start()
    p2.start()

方式2

from multiprocessing import Process
import time, random, os

class Test(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name

    def run(self):
        print("welcome to my house %s" % self.name, os.getpid())
        time.sleep(random.randint(1, 3))
        print("see you next time %s" % self.name)

if __name__ == '__main__':
    p1 = Test('鸣人')
    p2 = Test('佐助')
    p3 = Test('小樱')

    p1.start()
    p2.start()
    p3.start()
    print('主进程')

开启多线程的实例

#方式一
# from threading import Thread
# import time ,random
#
# def Test(name):
#     print('welcome to my house %s' %name)
#     time.sleep(random.randint(1,3))
#     print("see you next time %s" %name)
#
# if __name__ == '__main__':
#     t1 = Thread(target = Test,args=('鸣人',))
#     t2 = Thread(target = Test,args=('佐助',))
#     t3 = Thread(target = Test,args=('小樱',))
#
#     t1.start()
#     t2.start()
#     t3.start()

#方式二
# from threading import Thread
# import time ,random,os
#
# class Test(Thread):
#     def __init__(self,name):
#         super().__init__()
#         self.name = name
#     def run(self):
#         print('welcome to my house %s' %self.name,os.getpid())
#         time.sleep(random.randint(1,3))
#         print("see you next time %s" %self.name)
#
# if __name__ == '__main__':
#     t1 = Test('鸣人')
#     t2 = Test('佐助')
#     t3 = Test('小樱')
#
#     t1.start()
#     t2.start()
#     t3.start()
#
#     print('主线程')

from threading import Thread
from socket import socket
import time
s=socket()
s.bind(('127.0.0.1',8000))
s.listen(5)

def action(conn):
    while True:
        data= conn.recv(1024)
        time.sleep(1)
        conn.send(data.upper())
if __name__ == '__main__':
    while True:
        conn,addr= s.accept()
        t=Thread(target=action,args=(conn,))
        t.start()

  

剑指offer-python面试篇第一部分的更多相关文章

  1. 剑指Offer——中国银行面试知识储备

    剑指Offer--中国银行面试知识储备+面试内容 事件介绍 时间:2016.11.23 08:30 地点:北京市海淀区永丰路299号南门(中国银行软件中心) 事件:中国银行面试(中英文面试) 注意事项 ...

  2. 剑指Offer - 九度1283 - 第一个只出现一次的字符

    剑指Offer - 九度1283 - 第一个只出现一次的字符2013-11-21 21:13 题目描述: 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出 ...

  3. 剑指offer——python【第54题】字符流中第一个不重复的字符

    题目描述 请实现一个函数用来找出字符流中第一个只出现一次的字符.例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g".当从该字符流中读出 ...

  4. 【Java】 剑指offer(50-1) 字符串中第一个只出现一次的字符

    本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集   题目 在字符串中找出第一个只出现一次的字符.如输入"abacc ...

  5. 《剑指offer》算法题第一天

    按照个人计划,从今天开始做<剑指offer>上面的算法题,练习平台为牛客网,上面对每道题都有充分的测试实例,感觉还是很不错的.今天下午做了四道题,分别为: 1. 二叉树的深度(书55题) ...

  6. 剑指offer——python【第34题】第一个只出现一次的字符

    题目描述 在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写) 思路 遍历字符串,找到那个第 ...

  7. 剑指offer——python【第36题】两个链表的第一个公共结点

    题目描述 输入两个链表,找出它们的第一个公共结点 思路 注意,这里的公告结点的意思是相同的点,不仅值相同,next也相同,那么同理公共结点后面的点也是不仅值相同,而且next也相同,这样的话,就可以把 ...

  8. 剑指offer——python【第21题】栈的压入、弹出序列

    题目描述 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序.假设压入栈的所有数字均不相等.例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压 ...

  9. 剑指offer——python【第16题】合并两个有序链表

    题目描述 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1->1-& ...

  10. 书评<<剑指offer 名企面试官精讲典型编程题>>

      前前后后阅读了一周, 感慨很多, 面试考察的是一个人的综合能力, 这一点从面试官的角度去解读, 确实对面试的理解更立体. *) 具体考察的点1) 扎实的基础2) 高质量的代码3) 清晰的思路4) ...

随机推荐

  1. Flask 学习资源

    http://docs.jinkan.org/docs/flask/quickstart.html

  2. Java——IO类 字节流概述

    body, table{font-family: 微软雅黑} table{border-collapse: collapse; border: solid gray; border-width: 2p ...

  3. L1-031 到底是不是太胖了

    据说一个人的标准体重应该是其身高(单位:厘米)减去100.再乘以0.9所得到的公斤数.真实体重与标准体重误差在10%以内都是完美身材(即 | 真实体重 − 标准体重 | < 标准体重×10%). ...

  4. python 模块化管理,导入自己的模块(包)

    很多东西似懂非懂,或者当时看懂了,但是感觉不是很重要,经常不用,时间久了,也就变得似懂非懂了.今天被某度电话面试问道一个问题,就是模块倒入,其实我之前也是很仔细的研究过的,不过由于平时做的东西太简单, ...

  5. java设计模式 略版

    <转> 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结 ...

  6. Java内存不足之PermGen space错误探究

    一.Java 程序的运行机制与普通程序,如C或C++ 程序的运行机制有很大的区别. 普通程序运行之前必须首先编译成可执行的二进制码或机器码.机器码是与底层的硬件结构相关的,即使书写源代码的时候没有利用 ...

  7. Python 字典的增删改查

    dic = {"意大利": "李云龙","美国":"美国往事"} dic["日本"] = " ...

  8. grafana查询中的变量templating

    有时我们在管理成百上千台机器的时候,配置grafana无疑是明智的,因为你不需要一个一个的把每个机器的图形都配置一遍,利用templating就可以瞬间实现n台机器的状态显示了. templating ...

  9. Kaggle新手入门之路(完结)

    学完了Coursera上Andrew Ng的Machine Learning后,迫不及待地想去参加一场Kaggle的比赛,却发现从理论到实践的转变实在是太困难了,在此记录学习过程. 一:安装Anaco ...

  10. QT 5.4.1 for Android Ubuntu QtWebView Demo

    QT 5.4.1 for Android Ubuntu QtWebView Demo 2015-5-15 目录 一.说明: 二.参考文章: 三.QtWebView Demo在哪里? 四.Qt Crea ...