程序员最近都爱上了这个网站  程序员们快来瞅瞅吧!  it98k网:it98k.com

本站消息

站长简介/公众号

  出租广告位,需要合作请联系站长

+关注
已关注

分类  

暂无分类

标签  

暂无标签

日期归档  

暂无数据

面试题-python基础

发布于2019-08-03 09:11     阅读(3734)     评论(0)     点赞(14)     收藏(1)


一、Python基础

1、什么是python?使用python有什么好处?

python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,而且它开源

Python是一种解释性语言,它的源代码可以直接运行,Python解释器会将源代码转换成中间语言,之后再翻译成机器码再执行

2、可变类型与不可变类型

可变类型:list、dict、可变集合set

不可变类型:数字,str,tuple元组,frozenset

内存中的那块内容(value)是否可变

可直接在原来的地址,修改

不可变的类型都可以被hash哈希

3、深浅copy

对不可变类型进行copy的话,都是深copy

对于可变类型进行copy的话,一般都是浅copy

浅拷贝只是增加了一个指针指向所复制的对象,共用一块内存

深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存,

In [42]: li = [1,2,3,[4,5]]
In [43]: li2 = copy.copy(li)
In [44]: li3 = copy.deepcopy(li)


In [45]: li[-1][-1] = "222"
    
In [46]: li
Out[46]: [1, 2, 3, [4, '222']]

In [47]: li2
Out[47]: [1, 2, 3, [4, '222']]

In [48]: li3
Out[48]: [1, 2, 3, [4, 5]]

简单来说,如果有嵌套的话,浅copy只复制第一层,深copy会复制所有的

4、range-and-xrange

    py2:
        range() 生成的是列表
        xrange() 生成的是一个生成器 
    py3:
        range() 就是一个生成器
        xrange() 没了

5、闭包

def func():
    
    def inner():
        print('aaaa')  
        
    return inner

func()()  # aaaa 

内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

闭包的意义:返回函数对象+一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

6、装饰器

调用装饰器其实是一个闭包函数,

不修改函数的代码与修饰方式,为其他函数添加附加功能

比如:插入日志、性能测试、事物处理、缓存、权限验证等

# 装饰器
import time
def login(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print("fun 执行时间",end_time-start_time)
    return inner

@login
def test():
    for i in range(10000):
        for j in range(10000):
            pass
    print('test函数执行')

test()
# test函数执行
# fun 执行时间 2.0163347721099854

7、生成器

延迟操作,需要的时候才产生结果,而不是立即产生结果

在每次调用next()的时候执行,遇到yield语句返回

创建生成器的两种方式:

li = [i for i in range(100)]、yield方法

8、迭代器

for循环的数据类型:集合数据类型+生成器

list,tuple,dict,set,str + generator

不是一次性把数据加载到内存,而是被next()函数调用,不断返回下一个数据

9、*args与**kwargs

*args:位置参数 ('alex',18)

**kwargs:关键字参数 {'name'='alex','age'=18} 关键字参数一定要放在最后面

二、面向对象

1、经典类、新式类

经典类:深度优先,python2中

新式类:广度优先,Python3中

2、继承、多态、封装

(1)继承:类与类之间关系,Cat类是动物类,解决代码重用问题

重用 父类的属性与方法

def __init__(self, name, life_value, aggresivity, weapon):
        super().__init__(name, life_value, aggresivity,)        # python3格式
        self.weapon = weapon

 def attack(self, enemy):
       super().attack(enemy)

(2)多态:同一类事物多种形态

一个接口,多种形态

不应关注对象的类型本身,而是它如何使用的

鸭子类型:如果看起来像、叫声像而且走起路来像鸭子,那么它就是鸭子’

(3)封装

私有化的属性,私有化的方法,封装起来,外部无法调用 双下划线__foo

3、classmethod,staticmethod,property

(1)property:特性 (统一访问 原则)

    @property
    def bmi(self):
        return self.weight / (self.height ** 2)

把类的方法转换为属性,直接 alex.bmi 调用

(2)staticmethod 静态方法 (普通函数 ) 绑定到对象上

类内的函数实例化---> 普通函数 。 (类和对象都可以使用)

    @classmethod
    def from_conf(cls):
        obj = settings.name,
        return obj

(3)classmethod 类方法 (def foo(cls)) 绑定到类上

将cls 类本身当做参数传入,直接用类来调用函数,而不用借助类实例

优雅地实现某个类的实例的构造

4、 new.init区别,如何实现单例模式

创建一个新实例时调用new new()在 init()之前被调用

初始化一个实例时调用init

单例模式设计的类只能实例化1个对象

# 方式1 python模板自带单例模式
# admin.py

class Admin(object):
    def register(self):
        pass

site = Admin()

# test.py
from admin import site
site.register()

# 方式2  __new__  _instance
class Single(object):
    _instance = None
    def __new__(cls,*args,**kwargs):
        if not cls._instance:
            cls._instance = super(Single,cls).__new__(cls,*args,**kwargs)
            
        return cls._instance

5、反射

“字符串”形式,操作对象的相关属性或方法。

hasattr, getattr, setattr, delattr

ret = getattr(obj,'get_file')()       # 反射  obj是实例对象,name是方法 

三、并发

1、线程、进程的区别

(1)进程:程序的运行过程, os 资源调度、分配的基本单位 os的并发

(2)线程:进程的实体, cpu 调度、分派的基本单位 进程内部的并发

区别

1、进程有独立的内存空间, 线程 共享 本进程 的内存空间

2、进程有独立的系统资源 ,线程只有(程序计数器,一组寄存器,栈) 共享本进程的资源(内存,I/O,cpu)

3、独立性:进程崩溃,不会影响其他的(健壮) 线程崩溃,本进程的全部线程死掉

4、开销:进程切换与创建 开销大于 线程的

5、线程不能独立执行 进程可以

联系

都可并发、一个进程由1or多个线程 组成、一个进程中的所有线程共享该进程全部资源

2、协程、GIL

GIL:全局解释器锁(cpython解释器), 同一时刻,在cpu只能有一个线程执行

协程:轻量级的线程,用户控制调度的

单线程下(的并发), 遇到I/O阻塞,多个任务,自动切换

3、进程同步方式

1、Event事件 。 通知操作

2、互斥量。 加锁

3、信号量。 生产者消费者模型 阻塞队列Queue

4、临界区 。保护区域

同步问题:生产者消费者模型,作者读者问题,哲学家进餐问题

4、通信方式

管道,系统IPC(消息队列,信号量,信号,共享内存),套接字,远程过程调用rpc

5、死锁

多个进程运行,争夺资源,一种僵局;没有外力,进程,无法继续执行

导致死锁的原因:循环等待、不可抢占、占有且等待、互斥

死锁处理:

1、预防 :破坏4个条件

2、避免:银行家算法

3、检测:算法检测,清除死锁

4、解除: 检测到,撤销进程or剥夺资源

6、select、poll和epoll (I/O多路复用)

可以监视多个描述符

一个描述符就绪,通知应用程序,执行读or写操作

(1)select :

把文件描述符 fd 集合maxSize=1024,用户态copy到内核态 开销大,在内核,遍历所有fd

(2)poll:

改善了连接数,不断轮询,fd集合 每次都copy到内核态

(3)epoll:

linux下的多路复用I/O接口, 只copy一次,只告知 ,刚变为就绪状态的fd

四、mysql数据库

1、索引

B+数:二叉树-->平衡二叉树-->B数

一个排序好,数据结构 (协助快速查询data) 范围查询

create index ix_age on t1(age);
create index 索引名1,索引名2 on 表名('字段1','字段2')

(1)什么时候用?

经常 select查询、表记录超多

经常需要搜索的列、主键列、连接的列(外键)、范围查找 age in [20,40]、排序的列 salary、where上的列

(2)什么时候不用?

经常update,delete,insert 表记录少

不经常使用的列 addr,数据值很少的列 blog,文本,image,bit 修改>查询的

2、存储过程

相当于 函数,封装了,一系列,可执行的sql语句,存放在mysql中

直接调用它的名称

create procedure p1()
BEGIN
    select * from blog;
    INSERT into blog(name,sub_time) values("xxx",now());
END

优点:网络传输量小,程序与slq解耦

缺点:程序猿拓展功能不方便

3、数据库引擎

INNODB 支持事务,外键,行锁, 查表总行数,全表扫描

MYISAM不支持事务,不支持外键,表锁(插入data,锁定这个表),查表总行数,不需要全表扫描

4、redis

key-value数据库 ,经常用的data放在redis

性能极高,支持多种数据类型 ,放在内存中 (必要时可以写入硬盘)

五、网络

1、http常用的状态码

200:请求成功 OK

202:服务器接受请求,尚未处理

302:重定向

304  :上次的文档,已被缓存, 还可继续使用

400:客户端请求语法or参数错误

403:服务器收到请求,拒绝提供服务,找不到cookie

404:客户端请求的资源url不存在

500: 服务器的程序出现错误

503:服务器当前时间不能处理客户端的请求,一段时间后恢复

2、HTTP请求方式

HTTP1.0 GET/HEAD/POST

HTTP1.1 PUT/DELETE/CONNECT/OPTIONS/TRACE

3.GET/POST区别

(1)get提交的数据放在url后 /?name=alex&age=18 http请求头

     post的数据放在http报请求体

(2)GET的数据大小有限制,POST没有限制

(3)GET方式会带来安全问题,在url出现信息,可能获得username password

(4)在服务端 获取请求数据方式不同

4、http请求头,请求体

协议版本,状态码,状态码原因 HTTP /1.1 200 OK

Cookie:

Content-Language

Content-Type 文本类型

Content-Length 请求体长度

User-Agent: 浏览器的身份标识,类型,手机端or电脑端

Date:时间

请求体

5、TCP/UDP区别 (运输层)

1、TCP 传输控制协议,面向连接的,可靠的,数据流传输 ,注重data安全性,传输慢,面向字节流

2、UDP用户数据报文协议,非面向连接的,不可靠,数据流传输, data传输快,安全性一般,面向报文

python部分

4、深浅拷贝

浅拷贝只是增加了一个指针指向一个存在的地址,
深拷贝是增加一个指针并且开辟了新的内存,这个增加的指针指向这个新的内存,
简单地说,浅拷贝只拷贝一层(如果有嵌套),深拷贝拷贝所有层。

In [42]: li = [1,2,3,[4,5]]
In [43]: li2 = copy.copy(li)
In [44]: li3 = copy.deepcopy(li)


In [45]: li[-1][-1] = "222"
    
In [46]: li
Out[46]: [1, 2, 3, [4, '222']]

In [47]: li2
Out[47]: [1, 2, 3, [4, '222']]

In [48]: li3
Out[48]: [1, 2, 3, [4, 5]]
7、闭包
内部函数对外部函数作用域里变量的引用(非全局变量),则称内部函数为闭包。

闭包的意义:返回的函数对象,不仅仅是一个函数对象,在该函数外还包裹了一层作用域,这使得,该函数无论在何处调用,优先使用自己外层包裹的作用域

def func():
    
    def inner():
        print('aaaa')  
        
    return inner

func()()  # aaaa 
6、装饰器

调用装饰器其实是一个闭包函数,为其他函数添加附加功能,不修改被修改的源代码和不修改被修饰的方式,装饰器的返回值也是一个函数对象。
比如:插入日志、性能测试、事物处理、缓存、权限验证等,有了装饰器,就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

# 装饰器
import time
def login(func):
    def inner():
        start_time = time.time()
        func()
        end_time = time.time()
        print("fun 执行时间",end_time-start_time)
    return inner

@login
def test():
    for i in range(10000):
        for j in range(10000):
            pass
    print('test函数执行')

test()
# test函数执行
# fun 执行时间 2.0163347721099854
1、什么是python?使用python有什么好处?

python是一种编程语言,它有对象、模块、线程、异常处理和自动内存管理。它简洁,简单、方便、容易扩展、有许多自带的数据结果,而且它开源
Python是一种解释性语言,它的源代码可以直接运行,Python解释器会将源代码转换成中间语言,之后再翻译成机器码再执行

3、数组和元祖之间的区别是什么?

数组和元祖之间的区别:数组内容可以被修改,而元祖内容是只读的,不可被修改的,另外元祖可以被哈希,比如作为字典的key

5、os与sys区别:

os是模块负责程序与操作系统的交互,提供了访问操作系统底层的接口
sys模块是负责程序与python解释器的交互,提供了一系列的函数和变量,用于操控Python时运行的环境

15、range-and-xrange
    py2:
        range() 生成的是列表
        xrange() 生成的是一个生成器 
    py3:
        range() 就是一个生成器
        xrange() 没了
21、什么是pickling和unpickling?

Pickle模块读入任何python对象,将它们转换成字符串,然后使用dump函数将其转储到一个文件中——这个过程叫做pickling
反之从存储的字符串文件中提取原始python对象的过程,叫做unpickling

8、迭代器与生成器

生成器:Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。

这里,最难理解的就是generator和函数的执行流程不一样。
函数是顺序执行,遇到return语句或者最后一行函数语句就返回。generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次被next()调用时从上次返回的yield语句处继续执行。

迭代器

可以直接作用于for循环的数据类型:

  • 一类是集合数据类型,如listtupledictsetstr等;
  • 一类是generator,包括生成器和带yield的 generator function。
    不是一次性把数据加载到内存,而是被next()函数调用,不断返回下一个数据

    9、classmethod,staticmethod,property

    类方法:将类的函数转换成类方法,函数上装饰@classmethod会将函数的自动传值参数改成cls
    静态方法:此方法相当于给类扩展一个功能,将类内的函数实例化,给类或对象使用,此时类内的函数就是普通函数,不管是类还是实例化的对象都可以使用
    实例化:类的实例化就会产生一个实例(对象),可以理解为类()把虚拟的东西实例化,得到具体存在的值

    10、 new.init区别,如何实现单例模式,有什么优点
    __new__是一个静态方法,__init__是一个实例方法
    __new__返回一个创建的实例,__init__什么都不返回
    __new__返回一个cls的实例时后面的__init__才能被调用
    当创建一个新实例时调用new,初始化一个实例时调用init
 _new_()在 _init_()之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。
 单例模式是指创建唯一对象,单例模式设计的类只能实例,实例化1个对象
                   class Singleton(object):
                        __instance=None
                        def __init__(self):
                            pass
                        def __new__(cls, *args, **kwargs):
                            if Singleton.__instance is None:
                                Singleton.__instance=object.__new__(cls,*args,**kwargs)
                            return Singleton.__instance
2. python面向对象中的反射:
通过字符串的形式操作对象相关的属性。python中的一切事物都是对象(都可以使用反射)
11、多进程,多线程,协程,GIL

GIL:全局解释器锁,是锁在cpython解释器上,导致同一时刻,同一进程只能有一个线程被执行
多进程:多进程模块multiprocessing来实现,cpu密集型,IO计算型可以用多进程
多线程:多线程模块threading来实现,IO密集型,多线程可以提高效率
协程:依赖于geenlet,对于多线程应用。cpu通过切片的方式来切换线程间的执行,遇到IO操作自动切换,线程切换时需要耗时,
而协成好处没有切换的消耗,没有锁定概念。
进程:是资源管理单位,进行是相互独立的,实现并发和并发
线程:是最小的执行单位,线程的出现为了降低上下文切换的消耗,提供系统的并发性

12、IO多路复用/异步非阻塞

IO多路复用:通过一种机制,可以监听多个描述符 select/poll/epoll
select:连接数受限,查找配对速度慢,数据由内核拷贝到用户态
poll:改善了连接数,但是还是查找配对速度慢,数据由内核拷贝到用户态
epoll:epoll是linux下多路复用IO接口,是select/poll的增强版,它能显著提高程序在大量并发连接中只有少量活跃的情况下的系统CPU利用率
异步非阻塞:异步体现在回调上,回调就是有消息返回时告知一声儿进程进行处理。非阻塞就是不等待,不需要进程等待下去,
继续执行其他操作,不管其他进程的状态。

14、PEP8规范,规范的好处是什么?

1.缩进:4个空实现缩进,尽量不使用Tab
2.行:没行最大长度不超过79,换行可以使用反斜杠
3.命名规范:
4.注释规范:

16、with上下文机制原理

enter_和_exit,上下文管理协议,即with语句,为了让一个对象兼容with语句,必须在这个对象类中声明_enter_和_exit_方法,
使用with语句的目的就是把代码块放入with中执行,with结束后,自动完成清理工作,无须收到干预

17、经典类、新式类

经典类遵循:深度优先,python2中
新式类遵循:广度优先,Python3中

25、Python都有哪些自带的数据结构?
可变:列表  字典
不可变: 数字  字符串  元祖
26、命名空间?

在python中,所有的名字都存在于一个空间中,它们在改空间中存在和被操作——这就是命名空间,它就好像一个盒子,在每个变量名字都对应装着一个对象,
当查询变量的时候,会从该盒子里面寻找相应的对象

28、*args与**kwargs
*args代表位置参数,它会接收任意多个参数并把这些参数作为元祖传递给函数。
**kwargs代表的关键字参数,返回的是字典,位置参数一定要放在关键字前面
7.索引B+树

B+树(数据结构,平衡树,根节点,子节点,数据) 索引能够让数据库查询数据的速度上升,而使写入数据的速度下降, 因为平衡树这个结构必须一直维持在一个正确的状态, 增删改数据都会改变平衡树各节点中的索引数据内容,破坏树结构, 因此,在每次数据改变时, DBMS必须去重新梳理树(索引)的结构以确保它的正确,这会带来不小的性能开销, 也就是为什么索引会给查询以外的操作带来副作用的原因。

8.哈希表

(Hash Table,又称为散列表),是一种线性表的存储结构。通过把每个对象的关键字k作为自变量,通过一个哈希函数h(k),将k映射到下标h(k)处,并将该对象存储在这个位置。

例如:数据集合{1,6,7,9},假设存在哈希函数h(x)使得h(1) = 0, h(6) = 2, h(7) = 4, h(9) = 5,那么这个哈希表被存储为[1,None, 6, None, 7, 9]。
当我们查找元素6所在的位置时,通过哈希函数h(x)获得该元素所在的下标(h(6) = 2),因此在2位置即可找到该元素。



所属网站分类: 技术文章 > 博客

作者:小白鼠

链接:https://www.pythonheidong.com/blog/article/3836/62f53fbd41de5b558f58/

来源:python黑洞网

任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任

14 0
收藏该文
已收藏

评论内容:(最多支持255个字符)