目录

?

?

注:代码均用python3实现,并测试通过!

?

1. 可变与不可变类型

?? ?1.1 解释两种类型:

?? ??? ?不可变对象 -- 该对象所指向的内存中的值不能被改变。当改变某个变量时候,由于其所指的值不能被改变,

?? ??? ?相当于把原来的值复制一份后再改变,这会开辟一个新的地址,变量再指向这个新的地址。

?? ??? ?

?? ??? ?可变对象 -- 该对象所指向的内存中的值可以被改变。变量(准确的说是引用)改变后,实际上是其所指的值

?? ??? ?直接发生改变,并没有发生复制行为,也没有开辟新的出地址,通俗点说就是原地改变。

?? ??? ?

?? ?1.2 两种类型分别有哪些:

?? ? ? ?不可变:int,float,str,tuple

?? ??? ?可变: list,dict,set

2. 谈谈浅拷贝与深拷贝

?? ?2.1 python中有值类型与引用类型之分(对应不可变与可变对象)

?? ?2.2 由于值类型的对象在内存中占固定内存空间,所以他们的值保存在栈,按值访问数据

?? ??? ? 而引用类型的对象大小不固定,所以只将它们的内存地址(它是固定的)存放在栈,由于内存地址指向

?? ??? ? 实际对象,所有引用类型是按引用访问

?? ?2.3 浅拷贝实现:只复制某个对象的内存地址,新旧变量共享同一内存同一对象。

?? ??? ? 深拷贝实现:直接复制对象本身,新的对象是独立的,拥有不一样的内存地址,对原对象的修改不影响新对象。

3. __new__和__init__的区别

?? ?3.1 new在init之前执行,前者可决定是否调用后者

?? ?3.2 在OOP中,实例化遵循 创建x,初始化x,返回x (x=实例对象)这么个顺序,new是创建,init是初始化

?? ?

4. 谈谈设计模式

?? ??? ?*题外话*:设计模式详解 -> https://www.cnblogs.com/Liqiongyu/p/5916710.html

?? ?4.1 解释一下什么是设计模式

?? ??? ?简述:是经过总结、优化后的可重用解决方案。它是一种代码设计思想,不同的模式解决不同的问题,

?? ??? ?跟编程语言不相关。

?? ?4.2 你知道哪些设计模式,代码如何实现

?? ??? ?a. 工厂模式: 是一个在软件开发中用来创建对象的设计模式。(详解工厂模式:https://www.cnblogs.com/lizhitai/p/4471952.html)

?? ??? ?意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类。Factory Method 使一个类的实例化延迟到其子类。

?? ??? ??? ?适用性:

?? ??? ??? ?当一个类不知道它所必须创建的对象的类的时候。

?? ??? ??? ?当一个类希望由它的子类来指定它所创建的对象的时候。

?? ??? ??? ?当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化的时候。

?? ??? ?

?? ??? ?代码实现:

class Person: #基类(超类):提供一个抽象的接口来创建一个特定类型的对象

def __init__(self, name, gender):

self.name = name

self.gender = gender

def getName(self):

return self.name

def getGender(self):

return self.gender

class Male(Person): #子类1:继承自基类的子类

def __init__(self, name, gender):

super().__init__(name, gender)

print(self.gender, name)

class Female(Person): #子类2:继承自基类的子类

def __init__(self, name, gender):

super().__init__(name, gender)

print(self.gender, name)

class Factory: #工厂类(简易版可以只提供一个工厂函数)

def getPerson(self, name, gender): #工厂方法:是创建类的入口,用于创建用户想要的类

if gender == 'M':

return Male(name, 'male')

if gender == 'F':

return Female(name, 'female')

factory = Factory()

male = factory.getPerson("Chetan", "M")

female = factory.getPerson('Charle', 'F')

?? ??? ??? ?

?? ??? ?b. 单例模式:

?? ??? ??? ?意图:保证程序运行时全局环境中只有一个该类的实例

?? ??? ??? ?适用性:无论何时何处调用该类,都能使用同一个该类的实例对象的时候。

?? ??? ??? ?代码实现:

?? ??? ??? ? ? ?

class Singleton: #一个通用的单例超类,其他类继承即可(也可通过装饰器实现)

def __new__(cls, *args, **kw):

if not hasattr(cls, '_instance'):

cls._instance = object.__new__(cls)

return cls._instance

class SingleSpam(Singleton):

def __init__(self, s):

self.s = s

def __str__(self):

return self.s

s1 = SingleSpam('spam')

print(id(s1), s1)

s2 = SingleSpam('spa')

print(id(s2), s2)

print(id(s1), s1) #s1被s2替换,永远只有一个SingleSpam实例对象

?? ??? ??? ??? ?

?? ??? ?c. 装饰模式:

?? ??? ??? ?意图:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

?? ??? ??? ?适用性:

?? ??? ??? ?1. 在不影响其他对象的情况下,以动态、透明的方式给单个对象添加职责。

?? ??? ??? ?2. 处理那些可以撤销的功能

?? ??? ??? ?代码实现:

?? ??? ??? ? ? ?

class foo(object): #原类

def f1(self):

print("original f1")

def f2(self):

print("original f2")

class foo_decorator(object): #装饰类

def __init__(self, decorate):

self._decorate = decorate

def f1(self): #给原类方法添加功能

print("decorated f1") #可以是logging

self._decorate.f1()

def __getattr__(self, name):

return getattr(self._decoratee, name)

u = foo()

v = foo_decorator(u) #通过将实例作为参数传入的方式,动态修改对象的方法

v.f1()

v.f2()

?? ??? ??? ??? ?

?? ??? ?d. 迭代器模式:

?? ??? ??? ?意图:提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

?? ??? ??? ?适用性:

?? ??? ??? ?1. 访问一个聚合对象的内容而无需暴露它的内部表示。?

?? ??? ??? ?2. 支持对聚合对象的多种遍历。?

?? ??? ??? ?3. 为遍历不同的聚合结构提供一个统一的接口(即, 支持多态迭代)。

?? ??? ??? ?代码实现:

?? ??? ??? ? ?

class concreIterator():

def __init__(self, container):

self._a = container

self.index = -1

def first(self):

return self._a[0] if self._a else None

def isDone(self):

if self.index + 1 >= len(self._a):

return True

return False

def next(self):

try:

ret = self._a[self.index+1]

self.index += 1

return ret

except:

return None

def currItem(self):

return self._a[self.index]

i = concreIterator([1,2,3,4,6])

while not i.isDone():

print(i.next())

print(i.next()) # None

# 使用magic方法构建迭代器

class iterable2:

def __init__(self,container):

self._a = container

self._index= -1

def __iter__(self):

return self

def __next__(self):

try:

ret = self._a[self._index+1]

self._index += 1

return ret

except:

raise StopIteration

print(iterable2([1,2,3]))

for i in iterable2([1,2,3]):

print(i)

?? ??? ??? ??? ??? ?

?? ??? ?...(共有二十多种,不必说完)

?? ??? ?

5. 列表推导式和生成器的优劣

?? ?推导式:它将所有元素一次性加载到内存中,适合数量小的元素集合表示

?? ?生成器:只能遍历使用,每次返回一个元素,没有下一个元素时抛出异常。适合大数据量的处理。

6. 什么是装饰器,想在函数之后进行装饰,怎么做?

?? ?装饰器是一个函数,这个函数的主要作用是包装另一个函数或类,动态修改其行为。

?? ?要在函数后进行装饰,只需要新增一个函数或类,将原函数作为参数传入新函数/类的方法中,

?? ?在其中执行原函数,并在执行前或后添加想要的功能即可。

7. 使用装饰器的单例模式和其他方法(如new方法,或者单文件实现的单例)相比,有何区别?

?? ?使用装饰器实现不会重新初始化对象,它是直接返回之前的对象;

?? ?而其他方法均会再执行一次init方法,这也是装饰器实现单例的好处。

?? ??? ?

8. 谈谈线程与进程的区别

?? ?从四个方面来分析:

? ? 调度方不同:进程是操作系统调度的基本单位,而线程是cpu调度的基本单位。

?? ?开销不同:创建一个进程需要系统单独分配新的地址空间,代价昂贵;而创建新的线程可以直接

?? ??? ??? ??? ?使用进程的内存空间,所以进程开销大于线程。

?? ?通信方式不同:进程间通信一般通过HTTP或RPC方式;而同一进程下的不同线程间是共享全局变量的,通信更简便。

?? ?健壮性不同:单个进程死掉不会影响其他进程,而单个线程死掉会导致整个进程死掉。

?? ??? ?

9. 谈谈Python垃圾回收机制

?? ?垃圾回收机制属于python内存管理机制中的一种。

?? ?它包含三种机制:

?? ??? ?1. 引用计数

?? ??? ?2. 标记清除

?? ??? ?3. 分代回收

? ? 9.1. 引用计数

?? ??? ?是一种直观,简单的垃圾收集技术。当内存中某个对象的引用计数为0时,

?? ??? ?说明没有任何引用指向该对象,该对象就成为要被回收的垃圾了。其缺点是

?? ??? ?不能处理一种特殊情况:循环引用,这种情况需要另一种机制,即【标记清除】

?? ??? ?

? ? 9.2. 标记清除

?? ??? ?属于一种追踪式收集法,与引用计数不同,一般在【已申请内存空间达到阈值】时触发。

?? ??? ?若垃圾回收后仍然内存不足,就报错。

?? ??? ?原理:从位于内存中的一个根集开始,找到所有可达的对象集合,剩下不可达的对象都是待回收的垃圾。

?? ??? ?过程:1.从根集开始,标记所有可达对象(这一步将进行循环引用的的拆除,然后可以识别真正的垃圾对象)

?? ??? ??? ? ?2.遍历所有对象,回收未标记对象(不可达对象)占用的内存。(不可达:用户无法调用,且引用计数不为0的对象)

?? ??? ??? ? ?

?? ??? ?带来新问题:当内存中的对象较多时,而真正需要的回收的对象又很少的时候,对这些可达对象的检测是很耗时的,

?? ??? ?若生存周期较长的对象占比较大,那么每次垃圾回收就是低效率高耗时的操作,有较大优化空间,这时候又引入

?? ??? ?【分代回收】机制。

?? ??? ?

? ? 9.3. 分代回收

?? ??? ?分代回收策略着重于提升垃圾回收的效率。

?? ??? ?当对象很多时,垃圾检测将耗费大量的时间而真的垃圾回收花不了多久。

?? ??? ?对于这种多对象程序,我们可以把一些进行垃圾回收频率相近的对象称为“同一代”的对象。

?? ??? ?垃圾检测的时候可以对频率较高的“代”多检测几次,反之,进行垃圾回收频率较低的“代”

?? ??? ?可以少检测几次。这样就可以提高垃圾回收的效率了。至于如何判断一个对象属于什么代,

?? ??? ?python中采取的方法是通过其生存时间来判断。如果在好几次垃圾检测中,该变量都是

?? ??? ?reachable的话,那就说明这个变量越不是垃圾,就要把这个变量往高的代移动,要减少

?? ??? ?对其进行垃圾检测的频率。

?? ?代码演示python的垃圾回收(着重于循环引用问题的解决):

?? ??? ?

import sys,gc

gc.set_debug(gc.DEBUG_STATS | gc.DEBUG_LEAK) #开启gc调试

a = []

b = []

a.append(b)

print(sys.getrefcount(a)) # 2,但a真实的引用计数应该是2-1=1 ,这个函数获取的计数包含一个引用副本

b.append(a)

print(sys.getrefcount(a)) # 3

print(a) # [[[...]]]

del a,b #显式删除变量,对应变量引用计数应该清零,但由于循环引用,其引用计数仍然为一。

# print(sys.getrefcount(a)) #显式删除后无法再调用变量,此步异常

unreachable_count = gc.collect() #执行垃圾回收(用的就是标记-清除算法),得到所有的不可达对象(垃圾)

print(666, gc.garbage) # [] 查看待回收的垃圾对象列表

print(unreachable_count) #检测此刻内存中的不可达对象的数量,所谓不可达:用户无法调用,且引用计数不为0,这也是内存泄露的原因之一

print(gc.collect()) # 0,即垃圾回收成功

?? ??? ?

10. Python中的@property有什么作用? 如何实现成员变量的只读属性?

?? ?@property装饰器就是负责把一个方法变成属性调用,通常用在属性的get方法和set方法,

?? ?通过设置@property可以实现实例成员变量的直接访问,又保留了参数的检查。

?? ?另外通过设置get方法而不定义set方法可以实现成员变量的只读属性。

?? ?代码示例:

?? ? ? ?

class student:

@property

def birth(self):

return self._birth #使用一个内部变量来存储数据

@birth.setter #这个装饰器使得age可以被修改,否则就是read_only

def birth(self,v):

if v > 2019:

raise ValueError('birth cannot greate than 2019!')

self._birth = v

@property

def age(self):

self._age = 2019-self._birth

return self._age

s = student()

s.birth = 2011

print(s.age)

s.age = 22 #异常! 因age没有定义携带setter装饰器的方法,所以不能修改

?? ??? ?

?? ??? ?

11. *args and **kwargs如何使用?

?? ?*args代表位置参数,它会接收任意多个参数并把这些参数作为元组传递给函数。

?? ?**kwargs代表的关键字参数,允许你使用没有事先定义的参数名,kwagrs是一个dict;

?? ?另外,位置参数一定要放在关键字参数的前面。

?? ?

12. with语句应用场景是?有什么好处?能否简述实现原理

?? ?场景:with语句适用于对资源进行访问的场合,确保不管使用过程中是否发生异常都会执行必要的“清理”操作,

?? ?释放资源,比如文件使用后自动关闭、线程中锁的自动获取和释放等。

?? ?好处:不需要人为释放资源。

?? ?原理:with 主要用到一个概念:上下文管理器。

?? ??? ?12.1. 程序运行时,将with后紧跟的对象(一般是个class示例)称作上下文管理器。这个class必须

?? ??? ?定义两个方法,__enter__()方法和__exit__(),前者的返回对象赋值给as后面变量。

?? ??? ?

?? ??? ?12.2. 运行中如果发生了异常,那么将会把异常的类型,值和追踪传递给__exit__()方法。如果__exit__()

?? ??? ?方法返回值为true,那么这个异常将会被抑制,否则这个异常将会被重新抛出。

?? ??? ?

?? ??? ?12.3. 如果没有发生异常,也会调用__exit__()方法,但是传入的参数为None, None, None。

?? ??? ?通常也是在这里放入代码进行如文件流/会话的关闭等操作。

?? ??? ?

【进阶题目】

13. 标准库线程安全的队列是哪一个?不安全的是哪一个?

?? ?标准库中的queue.Queue是线程安全的,基础类型list,dict,set,tuple都不是线程安全队列,因为没有锁机制。

?? ?

14. python适合的场景有哪些?当遇到计算密集型任务怎么办?

?? ?适合场景:

?? ??? ?14.1. web开发,有非常优秀的web开发框架,如django,flask,aiohttp,且文档完善。

?? ??? ?14.2. linux运维。有完善的执行shell脚本的库。

?? ??? ?14.3. 网络爬虫。是最适合写爬虫的语言,没有之一;有丰富的访问网页和提取HTML文档数据的库。

?? ??? ?14.4. 对并发要求不高的场景。GIL使得python只适合应用于对IO密集型任务的并发处理,对计算密集型任务的并发无能为力。

?? ?

?? ?处理计算密集型任务:

?? ??? ?使用多进程来执行,进程之间相互独立,各自拥有系统分配的CPU资源和独立内存空间,实现并行

?? ??? ?(但CPU必须是多核或多颗CPU,现代计算机均符合此条件)。

?? ?

?? ?

15. python高并发解决方案?

?? ?高并发有两种任务场景:

?? ?15.1. IO密集型任务

?? ??? ?这种任务场景直接使用多线程库threading即可解决。

?? ??? ?更高效:线程有上下文切换开销,使用协程更好,如asyncio、gevent库

?? ?15.2. 计算密集型任务

?? ??? ?提高这种任务的执行效率只能使用并行,而并行只能通多进程(multiprocessing)来实现。

??

? ? ? ?以下是Gevent代码示例,更多关于gevent参考:https://blog.csdn.net/feixiaoxing/article/details/79056535:

import gevent

from gevent.lock import BoundedSemaphore

sem = BoundedSemaphore() #通过信号量来实现锁机制

def f1():

for i in range(5):

sem.acquire() #获得锁

print('this is ' + str(i))

sem.release() # 释放锁

gevent.sleep(2) #模拟IO事件操作,协程执行遇到IO事件时,将进行控制权转让

def f2():

for i in range(5):

sem.acquire()

print('that is ' + str(i))

# gevent.sleep(1)

sem.release()

t1 = gevent.spawn(f1) #孵化任务

t2 = gevent.spawn(f2)

gevent.joinall([t1,t2]) #执行一系列协程任务

'''

总结:gevent是基于协程的网络库,通过事件循环机制来实现并发编程(区别于并行)。

当某个协程遇到IO事件时,会将控制权转让给主线程,主线程再将控制权

交给IO事件已经完成的协程,若都没完成,主线程将一直持有控制权。

需注意:不管是threading还是gevent都不能利用多核优势,都只适合处理IO密集型的任务。

'''

??

?? ??? ?

python基础知识面试题-[面试] 1. 关于Python的基础知识相关推荐

  1. python基础知识面试题-深入解答关于Python的11道基本面试题

    前言 本文给大家深入的解答了关于Python的11道基本面试题,通过这些面试题大家能对python进一步的了解和学习,下面话不多说,来看看详细的介绍吧. 一.单引号,双引号,三引号的区别 分别阐述3种 ...

  2. python基础知识面试题-python的一些基本概念知识和面试题

    对于机器学习算法工程师而言,Python是不可或缺的语言,它的优美与简洁令人无法自拔.那么你了解过Python编程面试题吗?从Python基础到网页爬虫你是否能全方位Hold住?今天,机器之心为读者们 ...

  3. python网络爬虫面试题,搞定这套Python爬虫面试题(面试会so easy)

    搞定这套Python爬虫面试题(面试会so easy) 来源:中文源码网    浏览: 次    日期:2019年11月5日 [下载文档:  搞定这套Python爬虫面试题(面试会so easy).t ...

  4. [转载] Java基础知识面试题(2020最新版)

    参考链接: Java中的异常类型与示例 文章目录 Java概述何为编程什么是Javajdk1.5之后的三大版本JVM.JRE和JDK的关系什么是跨平台性?原理是什么Java语言有哪些特点什么是字节码? ...

  5. Java基础知识面试题(2021最新版)

    转载自:https://thinkwon.blog.csdn.net/article/details/104390612 文章目录 Java概述 何为编程 什么是Java jdk1.5之后的三大版本 ...

  6. 猿圈 题库_小猿圈总结常见HTML5基础知识面试题汇总

    现在对于刚刚毕业的大学生来说,面试是一种一点自信都没有的,但是对于一些有职场经验的人来说,是轻车熟路的,今天作为IT行业中的老油条,小猿圈web前端讲师为你简单讲解HTML5基础知识面试题汇总. 1. ...

  7. Java基础知识面试题每日三道 追梦:第二天

    Java基础知识面试题每日三道 追梦:第二天 1.什么是类和对象? 类和对象的区别? 类是对象的抽象,而对象是类的具体实例. 类是抽象的,不占用内存,而对象是具体的,占用存储空间. 类是用于 创建对象 ...

  8. python基础知识面试题-Python基本面试解答由浅入深—简答题

    原标题:Python基本面试解答由浅入深-简答题 不管你是学习任何语言,不管你是刚毕业还是行业大佬,找工作最终逃不掉的就是面试题,有的程序员很讨厌面试题,他们觉得面试题不会不代表我做不出东西,其实这种 ...

  9. python基础知识面试题-干货满满--亲身经历的 Python 面试题

    写在之前 这是首发在我公众号 "Python空间" 的第 2 篇文章. 如果看过我第一篇文章(三个月自学拿到 python 开发 offer!)的朋友可能知道,我来上海一个多星期, ...

最新文章

  1. 化浆池是什么东西_冷水滩酒店海鲜贝类池定制定做大型海鲜池
  2. Vue轻松入门,一起学起来!
  3. 4-spark学习笔记-spark运行模式与原理
  4. shop--10.店铺详情(后台+前端类似于shoplist)
  5. createrepo常用参数
  6. mysql错误修改数据_使用正则表达式快速修改mysql中错误的varchar类型数据
  7. CSS基础(part12)--盒子模型之外边距
  8. 论ORM框架—EntityFrameworkCore
  9. P3992 [BJOI2017]开车
  10. CF765F Souvenirs(势能线段树)
  11. css-animation-走路动画
  12. C++ vector所有操作,你真的掌握vector了吗?两万总结带你干穿vector
  13. pythonnumpy详解_Python:Numpy详解
  14. Xshell 连接CentOS服务器解密
  15. Vue项目部署到服务器上路由无法访问的问题
  16. stella forum 知识库---一些错误的修补
  17. SpringBoot(尚硅谷)
  18. Android 一篇文章轻松搞懂什么是Callback回调
  19. 小游戏————坦克大战
  20. P1757 通天之分组背包(动态规划 分组背包)

热门文章

  1. 【財務会計】固定資産の除却と廃棄の違い
  2. 常用数据库优化方案(三)
  3. 面试题23_从上往下打印二叉树
  4. 一起学习android图片四舍五入图片集资源 (28)
  5. asp access的安全:不要认为简单的改后缀mdb为asp就能防下载
  6. 装了VS2005再装IIS的小问题
  7. python与人工智能编程-五大人工智能流行编程语言对比,只要学会一种绝对不亏!...
  8. 下面不属于python第三方库的安装方法的是-关于python中第三方库安装方法和问题解决...
  9. python语言程序设计2019版第二章课后答案-《Python语言程序设计》 —2.7 课后习题...
  10. python绘图实例-Python中turtle绘图学习笔记和实例