python 面试题重点 (基础篇)

python 面试题重点 (基础篇)

第一部分 必答题

1.简述列举了解的编程语言及语言间的区别?

Python:轻量级、易学、自由 开放源码软件、可移植性、支持面向对象、丰富的库、规范的代码。
Java:优点:开源性,功能强大,库多
      缺点:编译速度 比较慢,不完全
PHP:优点:性能很强,配合简单,稳定,容易部署。
     缺点:函数命名不规范,驼峰法和下划线,传参位置不一。
C:  优点:能操纵底层,能细粒度优化性能。
     缺点:1、是面向过程的,2、运行时类型检查不可用,3、不提供命名空间功能,
     4、构造函数和析构函数不可用。       
C#:  优点: 强大的.NET Framework托管代码集合类,较简单的语言特性。
            WEB应用程序开发速度快。
      缺点:底层和高性能不合适,Windows平台以外支持有限。
C++:  优点:性能比较高,可进化型。
      缺点: 难学,门槛高
#第一题
编译型语言:一次性全部编译成二进制码,再去运行
解释性语言:编译- -句,运行一句
1. python
解释型简洁高效,容易上手
2. java
混合型(JVM,JIT编译器)_学习成本高,开发周期慢,web方向
3. C
编译型属于底层语言,只有面向过程没有面向对象
4. c++
编译型属于底层语言,既有面向过程也有面向对象
35. go .
编译型应用在区块链,高并发高可用,游戏方向

2. 例举python2 和python3 的区别?

Python2默认的字符编码是ASCII,默认的文件编码也是ASCII ;
python3默认的字符编码是unicode,默认的文件编码是utf-8。

在python2里,将string处理为原生的bytes类型。
python3把字符串的编码改成了unicode, 还把str和bytes做了明确区分, str就是unicode格式的字符,bytes是单纯二进制。print语句没有了,取而代之的是print()函数。

在python 2.x 中/除法整数相除的结果是一个整数,把小数部分完全忽略掉,浮点数除法会保留小数点的部分得到一个浮点数的结果。
在python 3.x 中/除法不再这么做了,对于整数之间的相除,结果也会是浮点数。
捕获异常的语法由 except exc, var 改为  except exc as var。

Python 2.x 中反引号 相当于 repr 函数的作用
Python 3.x 中去掉了 这种写法,只允许使用 repr 函数
Py3.X去除了long类型,现在只有一种整型——int,但它的行为就像2.X版本的long
在 Python 2 中 有 range ()和 xrange () ,一般使用 xrange ()创建迭代对象。
在 Python 3 中, range () 是像 xrange ()那样实现, xrange ()内置函数已经删除。
笔记:

#第二题
# python2
1. print "123"
2.range返回list
3.默认编码-- ascii
4.2种类经典类和新式类
class Car () :pass
经典类(多继承当中的搜索原则深度优先)
class. Car (object) :pass新式类(多继承当中的搜索原则广度优先)
类.mro() =>继承顺序列表
5.除法:结果是整型
6.int ,long (长整型)
7.raw_ input =>等价于python3 input
# python3
1. print ()
2.range返回的可迭代对象
3.默认编码-- utf-8
4.都是新式类
5.除法:结果是小数
6. int
7. input

3. 看代码写结果

v1 = 1 or 2
v2 = 9 and 7 or 9 and 0
1
7
笔记:逻辑运算符优先级 () > not > and > or

逻辑短路

and 全真则真,一假则假
or  一真则真,全假则假

True or 表达式  => True  (单个运算符和多个运算符的情况,都可以直接判定结果)
False and 表达式 => False(单个运算符的时候可以)

布尔值为假的十种情况: bool() => False

	0,0.0,False,0j,'',[],(),set(),{},None

v1 = 1 or 2
print(v1) # 1

v2 = 3 and 7 or 9 and 0 

v2 = 7 or  0

v2 = 7

print(v2)

"""
数据类型:
	Number(int , float , complex , bool)
	容器:str list tuple set dict
	

复数 : 用在数据分析,人工智能中

complexvar = 3 + 4j
3 : 实数
4j: 虚数
j: 如果有一个数,他的平方等于-1 ,那么这个数就是j,科学家认为有,表达高精度类型
"""


4. 比较以下值有什么不同?

v1 = [1,2,3]
v2 = [(1),(2),(3)]
v1 = [(1,),(2,),(3,)]
 逗号才是区分是否是元组的标识符
 v1 = [1,2,3] # 列表[int , int , int]
 v2 = [(89),(2.12),("abc")] # [int , float , str]
 v3 = [(1,),(2,),(3,)] # [tuple,tuple,tuple,tuple]
 res = () # 表达空元组 

5. 用一行代码实现数值交换。

 a = 1
 b = 2

a,b = b,a

笔记:
# python 特有

a = 1
b = 2
a,b = b,a 

# 通用

tmp = a
a = b
b = tmp


6. Python中单引号、双引号、三引号的区别?

python单引号 ’ 双引号 " 三引号 ‘’’ 和 “”"都是字符串且可以进行转义,
唯一的差别就是三引号 ‘’’ 和 “”"可以显示多行。


笔记:
单双引号没有区别,三引号可以支持跨行
在互相嵌套时需注意:里外不能使用相同的引号

7. is和==的区别?

is 是判断等式两边的内存地址是否相同
 == 是判断等式两边的值是否相等

8. python里如何实现tuple和list的转化?

# int  float  complex  bool  str  list  tuple  set  dict 

list(数据) tuple(数据)

9.如何实现字符串name= '老男孩'的反转?

使用字符串切片
s = "老男孩"
s1 = s[::-1]
print(s1)

笔记:
name[start:end:step] 语法
name[::-1]

10.两个set如何获取交集、并集、差集?

#set 函数是无序不重复的元素集合,可以进行关系测试,去除重复数据,还可以计算交集、差集、和并集
#class set([iterable])  iterable 可迭代对象

#删除重复
x=set('sixbobo')
y=set('googlebb')
print('删除重复元素',x,y)

#取交集
print(x&y)

#取并集
print(x|y)

#取差集
print(x-y)


some_list=['liubo','liuda','liuer','liusan','liusi','liubo','sixbo','sixbo']

duplicates=[]
for value in some_list:
    #判断列表中A元素的个数大于1
    if some_list.count(value)>1:
        #并且不在变量list中
        if value not in duplicates:
            #添加到列表中
            duplicates.append(value)
print(duplicates)


some_list01=set(['liubo','liuda','liuer','liusan','liusi','liubo','sixbo','sixbo'])

some_list02=set(['liubo','jsj','jdsj'])

#取交集
print(some_list01&some_list02)
print(some_list02.intersection((some_list01))) #intersection交集的方法

#取差集
print(some_list01-some_list02)
print(some_list02.difference(some_list02))#difference 差集
#取并集
print(some_list01|some_list02)
print(some_list02.union(some_list01))#union 并集

笔记:
交集 &
intersection
差集 -
difference
并集 |
union
对称差集 ^
symmetric_difference

11.那些情况下, y!=x- (x-y)会成立?

"""
非空集合且不为子父关系的两个集合
"""
y != x-(x-y)
x = {"a","b","c"}
y = {"b","d"}

if y != x-(x-y):
	print("ok")

12. Python中如何拷贝一个对象?

一、赋值、引用
二、深拷贝deepcopy与浅拷贝copy

笔记:
# import copy

# 针对于列表的拷贝,还可以使用[:] , [::],浅拷贝的一种方式

lst1 = [1,2,3]
lst2 = lst1[:]
lst1.append(4)
print(lst2)

13.简述赋值、浅拷贝、深拷贝的区别?

赋值(=),就是创建了对象的一个新的引用,修改其中任意一个变量都会影响到另一个。
浅拷贝:创建一个新的对象,但它包含的是对原始对象中包含项的引用(如果用引用的方式修改其中一个对象,另外一个也会修改改变){1,完全切片方法;2,工厂函数,如list();3,copy模块的copy()函数}

深拷贝:创建一个新的对象,并且递归的复制它所包含的对象(修改其中一个,另外一个不会改变){copy模块的deep.deepcopy()函数}

笔记:
#赋值   : 将变量和值在内存中形成映射指向关系
#浅拷贝 : 只拷贝第一级里所有的元素 copy.copy
#深拷贝 : 为所有层级的元素都单独开辟新空间 copy.deepcopy() (地址:原不可变数据只是暂时的指向,可变的数据独立开辟新空间)
"""
可变数据: list set dict
不可变数据: int float bool complex str tuple
"""

import copy
lst1 = [1,2,3,[4,5,6]]
lst2 = copy.deepcopy(lst1)
lst1[0] = 100
print(lst1)
print(lst2)

print(id(lst1[0]))
print(id(lst2[0]))


14. pass的作用?

python中if ,for等复合语句通常是由一个语句头和语句体构成。语句体中出现的语句数量并没有限制,但是至少需要一行。

偶尔可能会需要一个语句体什么也不做(通常是标记一个你还没来得及写的代码的位置),

这个时候就需要pass了。

pass是空语句,是为了保持程序结构的完整性。

pass 不做任何事情,一般用做占位语句。

if x < 0:
    pass

笔记:
# 占位

15.阅读代码写结果。

import copy
a = [1,2,3,4,5,['b','c']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)

a.append(5)
a[4].append('d')
print(b)
print(c)
print(a)


import copy
a = [1,2,4,5,['b','c']]
b = a
c = copy.copy(a)
d = copy.deepcopy(a)
a.append(5)
a[4].append('d')

# print(a) [1,2,4,5,['b','c',"d"],5]
# print(b) [1,2,4,5,['b','c',"d"],5]
# print(c) [1,2,4,5,['b','c',"d"]]

16.用Python实现9 * 9乘法表。

l=1
i=0
while l<10:
    i=1
    while i<=l:
        if i==l:
            print(i,'*',l,'=',l*i)
        else:
            print(i,'*',l,'=',l*i,end='  ')

        i += 1
    l += 1

笔记:


"""
有行又有列,脑海里瞬间想到两层循环
一层循环控制行
一层循环控制列
"""
i = 1
while i<=9:
	# 这个位置写代码
	j = 1
	while j<= i:
		# "谁"*"谁"="谁"
		print("%d*%d=%2d" % (i,j,i*j),end=" ")
		j+=1
		
	# 打印换行
	print()	
	i+=1


for i in range(1,10):
	for j in range(1,i+1):
		print("%d*%d=%2d" % (i,j,i*j),end=" ")
	print()	

17.用Python显 示一个斐波那契数列。

def fib(n):
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()
fib(1000)  # 取值范围可以任意

# 输出结果如下:
# 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987

笔记:
# 1 1 2 3 5 8 13 21 ...
# 方法一
lst = [1,1]
for i in range(10):
	lst.append(lst[-1] + lst[-2])
print(lst)

# 方法二
a,b = 0,1
for i in range(10):
	print(b)
	a,b = b,a+b

# 方法三
def fib(n):
	if n <= 2:
		return 1
	# 上一个值 + 上上个值
	return fib(n-1) + fib(n-2)

print(fib(6))

18.如何删除列表中重复的值?

方法一 set函数
a = [1, 1, 2, 3, 3]
 
b = set(a)
 
# b = {1, 2, 3}  b是集合

方法二 遍历
b = []
 
for i in a:
    if not i in b:
        b.append(i)
 
# b = [1, 2, 3]

笔记:
list(set(lst))

19.一个大小为100G的文件etl log.txt,要读取文件中的内容,写出具体过程代码?

fp = open("文件名","模式","编码集")
"""
fp 是迭代器
from collections import Iterator,Iterable

# 在遍历fp时,文件按照一行一行进行读取;
for i in fp:
	code ... 

"""

20. a= dict(ip(("a" ,"b",","d","e"),(1,2,3,4,5)))请问a是什么?

强转字典的条件:等长的二级容器,配合强转字典的两个函数 zip , enumerate
# zip  拉链
a = dict( zip( ("a","b") , [1,2] ) )
print(a)
# enumerate  枚举
a = dict( enumerate( ["a","b"] ))
a = dict( enumerate( ["a","b"] ,start = 10 ))
print(a)

21. lambda关键字的作用?

lambda函数是匿名的:所谓匿名函数,通俗地说就是没有名字的函数。lambda函数没有名字。
lambda函数有输入和输出:输入是传入到参数列表argument_list的值,输出是根据表达式expression计算得到的值。
lambda函数一般功能简单:单行expression决定了lambda函数不可能完成复杂的逻辑,只能完成非常简单的功能。由于其实现的功能一目了然,甚至不需要专门的名字来说明。

笔记:
lambda 匿名函数 : 用一句话表达只有返回值的无名函数
lambda 参数 : 返回值

22. *arg 和**kwarg作用?

1、函数调用里的*arg和**kwarg:

    (1)*arg:元组或列表“出现”
       **kwarg:字典“出没”

    (2)分割参数

2、函数定义时传的*arg /**kwarg:

    (1)接收参数

笔记:
*arg **kwarg

# *arg   普通收集参数 :   收集多余的没人要的普通实参
# **kwarg 关键字收集参数: 收集多余的没人要的关键字实参

23. 如何在函数中设置一个全局变量?

在函数的内部,通过global声明,使在函数内部中设置一个全局变量,这个全局变量可以在任意的函数中进行调用!

 

SOLR_URL='http://solr.org'

def tt():
    global SOLR_URL
    SOLR_URL=SOLR_URL+'#aa'

def aa():
    if __name__=='__main__':
        tt()
        print(SOLR_URL)
aa()  # http://solr.org#aa

笔记:
"""
global  有该全局变量,修改当前变量,没有改全局变量,定义一个全局变量;
"""
def func():
	global a
	a = 90
func()
print(a)



24. filter、 map、reduce的作用?

通俗的说..都是用在一堆数据(比如一个列表)上..
filter是筛选出其中满足某个条件的那些数据..字面意思是过滤..比如挑出列表中所有奇数..

map是用同样方法把所有数据都改成别的..字面意思是映射..比如把列表的每个数都换成其平方..

reduce是用某种方法依次把所有数据丢进去最后得到一个结果..字面意思是化简..比如计算一个列表所有数的和的过程,就是维持一个部分和然后依次把每个数加进去..

笔记:
"""
三目(元)运算符  True   if 条件表达式 else False

filter => 过滤数据
iterable : 可迭代对象(range ,容器类型数据 , 迭代器)
filter(func,iterable)  => 返回迭代器

lst = [1,2,3,4,5]
it = filter(lambda x : True   if x % 2 == 0 else False , lst )
print(list(it))

"""


# map -> 处理(映射)数据
map(func,iterable) => 返回迭代器

lst = [1,2,3]
it = map(lambda x : x*3 , lst)
print(list(it))

# reduce -> 计算数据
from functools import reduce
# reduce(func,iterable) => 最后计算的值
# [5,4,8,8] => 5488
lst = [5,4,8,8]
res = reduce(lambda x,y : x*10 + y ,lst )
print(res , type(res))

25.什么是匿名函数?匿名函数有什么作用?

匿名函数顾名思义就是没有名字的函数

可以通过 use 关键字获取上下文中的环境变量,减少不必要参数的传入或导出。
减少不必要的函数暴露,提高代码的可读性

如果使用匿名函数,该函数仅仅会在被调用处使用,其他地方不会引用到。
如果不使用匿名函数,该函数可以在其他地方被引用。从可读性上讲,没有匿名函数可读性高。

笔记:
lambda 匿名函数 : 用一句话表达只有返回值的无名函数
lambda 参数 : 返回值


26. Python递归的最大层数?

最大数为998

import sys
sys.setrecursionlimit(100000)

def foo(n):
    print(n)
    n += 1
    foo(n)
        
if __name__ == '__main__':
    foo(1)

笔记:
官方说法1000 , 实际测试 994 ~ 1000
import sys
sys.setrecursionlimit(999999) # 修改递归的最大深度

27.什么是迭代器?什么是可迭代对象?

迭代器:

  迭代器是一个对象

  迭代器只能使用一次

  迭代器一定是一个可迭代对象,可迭代对象不一定是一个迭代器,迭代器是一个对象class

可以被迭代要满足的要求就叫做可迭代协议。可迭代协议的定义非常简单,就是内部实现了__iter__方法。

迭代器生成的对象就是可迭代对象

笔记:
# 具有__iter__() 和 __next__()这两个方法的是迭代器
# 具有__iter__()方法就是可迭代对象
# dir(数据) 可以查看该数据的内部系统成员
# 可迭代对象 => 迭代器  把不能直接被next获取 => 可直接获取到该数据的一个过程

28.什么是生成器?

Python中提供的生成器:

1.生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行

2.生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表

生成器Generator:

本质:迭代器(所以自带了__iter__方法和__next__方法,不需要我们去实现)

特点:惰性运算,开发者自定义

笔记:
生成器的本质就是迭代器,可以自定义迭代的逻辑
创建方式两种:
	(1)生成器表达式 (推导式)  (i for i in range(3))
	(2)生成器函数   (含有yield关键字)


29.什么是装饰器及应用场景?

概念:

1.装饰器的实现是由闭包支撑的;

2.装饰器本质上是⼀个python函数,它可以在让其他函数在不需要做任何代码的变动的前提下增加额外的功能;

3.装饰器的返回值也是⼀个函数的对象,它经常用于有切面需求的场景,实现路由传参,flask的路由传参依赖于装饰器,浏览器通过url访问到装饰器的路由,从而访问视图函数获得返回的HTML页面;


应用场景:

1.可以在外层函数加上时间计算函数,计算函数运行时间;

2.计算函数运行次数;

3.可以用在框架的路由传参上;

4.插入日志,作为函数的运行日志;

5.事务处理,可以让函数实现事务的一致性,让函数要么一起运行成功,要么一起运行失败;

6.缓存,实现缓存处理;

7.权限的校验,在函数外层套上权限校验的代码,实现权限校验;

笔记:
# 装饰器的本质就是闭包
# 在不修改原有代码的前提下,额外增加新功能就是装饰器
# 应用:登录认证,property类,框架(django,flask,@app.route("/",methdos=["GET","POST"]))

30.什么是反射及应用场景?

反射
主要是指程序可以访问、检测和修改它本身状态或行为的一种能力

应用场景
例如模块化的开发,通过反射去调用对应的字节码;动态代理设计模式也采用了反射机制,还有我们日常使用的 Spring/Hibernate 等框架

笔记:
# 通过字符串去操作类对象 或者 模块中的属性方法
hasattr getattr setattr delattr
应用: 可以配合用户的操作或者输入,调用其中的成员,api接口中

31.写一个普通的装饰器。

import datetime
def time_it(func):
    def _deco(*args, **kwargs):
        start = datetime.datetime.now()
        print("--- Start time: %s ---" % start)
        ret = func(*args, **kwargs)
        end = datetime.datetime.now()
        print("---- End time: %s ----" % end)
        print("Function spend time: %s" % (end - start))
        return ret
    return _deco

笔记:
闭包:内函数使用了外函数的局部变量,外函数把内函数返回出来的过程叫做闭包
这个内函数叫做闭包函数;
特点:如果内函数使用了外函数的局部变量,那么该变量于内函数发生绑定,延长该变量的生命周期
def wrapper(func):
	def inner(*args,**kwargs):
		res = func(*args,**kwargs)
		print("and you")
		return res
		
	return inner

@wrapper
def func():
	print("i am fine 3q")

func()



32.写一个带参数的装饰器。

import time
FLAGE = False
def timeer_out(flag):
    def timeer(func):
        def inner(*args,**kwargs):
            if flag:
                start = time.time()
                ret = func(*args,**kwargs)
                end = time.time()
                print(end - start)
                return ret
            else:
                ret = func(*args,**kwargs)
                return ret
        return inner
    return timeer
@timeer_out(FLAGE)
def lala():
    time.sleep(0.1)
    print("小垃圾")
lala()

笔记:
def outer(n):
	def wrapper(func):
		def inner1(*args,**kwargs):
			res = func(*args,**kwargs)
			print("我是大王")
			return res
			
		def inner2(*args,**kwargs):
			res = func(*args,**kwargs)
			print("大王叫我来巡山")
			return res
		
		if n == "alex":
			return inner1
		else:
			return inner2
			
	return wrapper


@outer("alex123") # outer("alex123") => wrapper =>@wrapper
def func():
	print("i am fine 3q")
	
func()


33.求结果

def num() :
return [lambda x:i*x for i in range(4)]
print([m(2) for m in num()])

[6, 6, 6, 6]

笔记:
def num():
	return [lambda x:i*x for i in range(4)]
print([m(2) for m in num()])

"""
def出现的位置是函数的定义处
函数() 出现的位置是函数的调用处
(1)调用的时候,才会把函数中的代码,从上到下执行一遍,否则不执行
(2)里面的func是一个闭包函数,延长了当前变量i的生命周期,最后一次i的值3,所以再去调用时候拿的3
"""


def num():
	lst = []
	for i in range(4):
		def func(x):
			return i*x
		lst.append(func)
	return lst
	
lst = num()
print(lst)


lst = [ m(2)   for m in num()  ]
lst = [ m(2)   for m in lst  ]
lst = [ i*x   for m in lst  ]
lst = [3 * 2 for m in lst]
lst = [6,6,6,6]


"""
[
<function func at 0x000001A02CA642F0>, 
<function func at 0x000001A02CA64378>, 
<function func at 0x000001A02CA646A8>, 
<function func at 0x000001A02CA64730>
]
def func():
	print(1)

for i in range(3):
	print(i)
	
"""

34. def(a, b=[])这种写法有什么陷阱?

def func(a,b=[]):
    b.append(a)
    print(b)
func(1)
func(1)
func(1)
func(1)

看下结果

  [1]
  [1, 1]
  [1, 1, 1]
  [1, 1, 1, 1]

函数的第二个默认参数是一个list,当第一次执行的时候实例化了一个list,第二次执行还是用第一次执行的时候实例化的地址存储,所以三次执行的结果就是 [1, 1, 1] ,想每次执行只输出[1] ,默认参数应该设置为None。

笔记:
b身上的默认值是列表,如果使用原来默认的参数,调用func函数
会把几次调用的值都存放在同一个默认列表里
"""
默认参数: 
	如果调用时,用户给实参了,那么使用用户的
	如果调用时,用户没给实参,那么使用默认的(早已存在内存中的这个列表)
	
默认值会提前在内存中驻留,在使用时,才能调取,在定义函数的时候就提前开辟了空间
"""

35. 看代码写结果

def func(a,b=[]):
  b. append (a)
  return b
v1 = func(1)
v2 = func(2, [10,20])
v3 = func(3)
print(v1,v2,v3)

[1, 3] [10, 20, 2] [1, 3]

笔记:
def func(a,b=[]):
	b.append(a)
	return b
v1 = func(1)
v2 = func(2,[10,20])
v3 = func(3)
print(v1,v2,v3) # [1,3]  [10, 20, 2]  [1, 3]

36.看代码写结果

def func(a,b=[]):
   b.append(a)
   return b
v1 = func(1)
print(v1)
v2 = func(2, [10,20])
print(v2)
v3 = func(3)
print(v3)

[1]
[10, 20, 2]
[1, 3]

笔记:
def func(a,b=[]):
	b.append(a)
	return b
v1 = func(1)
print(v1) # [1]
v2 = func(2,[10,20])
print(v2) # [10, 20, 2] 
v3 = func(3)
print(v3) # [1, 3]

37.请编写一个函数实现将IP地址转换成一个整数。

如10.3.9.12 转换规则为:
      10             00001010 
       3             00000011
       9             00001001
      12           00001100
再将以上二进制拼接起来计算十进制结果: 00001010 00000011 00001001 00001100 = ?

笔记:
# ljust   原字符串居左,填充符号
# rjust   原字符串居右,填充符号
# 方法一
ip = "10.3.9.12"
strvar = ""
for i in ip.split("."):
	bin_str = str(bin(int(i)))[2:]
	# 总长度是8 原字符串居右
	strvar += bin_str.rjust(8,"0")
print(strvar)
	
# 把二进制字符串转换成十进制,默认转换时,是十进制
print(int(strvar,2))

# 方法二
ip = "10.3.9.12"
strvar = ""
for i in ip.split("."):
	# format 将整型转化成二进制,不够8位的拿0补位
	strvar += format(int(i) , "08b")
print(int(strvar,2))

38.请查找一个目录下的所有文件(可 能存在文件嵌套)。

用file命令查看所有文件的类型

笔记:
# 方法一 (递归写法)
import os
def getallsize(pathvar):
	size = 0
	lst = os.listdir(pathvar)
	print(lst)
	for i in lst:
		pathvar2 = os.path.join(pathvar,i)
		print(pathvar2)
		
		# 判断是否是文件
		if os.path.isfile(pathvar2):
			size += os.path.getsize(pathvar2)
		# 判断是否是文件夹
		elif os.path.isdir(pathvar2):
			size += getallsize(pathvar2)

		print(size)
	
	return size
	
# "E:串讲基础day2	est1.txt"
pathvar = r"E:串讲基础day2	est"
res = getallsize(pathvar)
# print(res)

# 方法二
import os 
# os.walk() => 生成器
pathvar = r"E:串讲基础day2	est"
gen = os.walk(pathvar)

for root,dirs,files in gen:
	for name in files:
		pathvar = os.path.join(root,name)
		print(pathvar)


39.求结果

import math
print (math. f1oor(5.5))

笔记:
# floor ceil round
import math
print(math.floor(5.5))

# round n.5 奇进偶不进
print(round(4.5))
print(round(5.5))
print(round(4.52))

40.是否使用过 functools 中的函数?其作用是什么?

使用过
functools用于高阶函数:指那些作用于函数或者返回其他函数的函数。通常情况下,只要是可以被当做函数调用的对象就是这个模块的目标。
python 中提供一种用于对函数固定属性的函数

笔记:
from functools import reduce
# 在装饰器中使用,如果想要保留原来函数的属性,加上wraps
from functools import wraps

def wrapper(func):
	@wraps(func)
	def inner(*args,**kwargs):
		res = func(*args,**kwargs)
		print("and you")
		return res
		
	return inner

@wrapper
def func():
	print("i am fine 3q")

func()
print(func)

# def abc():
	# pass
# print(abc)



41. re的match和search区别?

1、match()函数只检测RE是不是在string的开始位置匹配,search()会扫描整个string查找匹配;
2、也就是说match()只有在0位置匹配成功的话才有返回,如果不是开始位置匹配成功的话,match()就返回none。
3、例如:

import re
print(re.match('super', 'superstition').span())  # (0,5)
print(re.match('super', 'insuperable'))  # None
4、search()会扫描整个字符串并返回第一个成功的匹配:
例如:

import re
print(re.search('super', 'superstition').span()) #(0,5)
print(re.search('super', 'insuperable')) # <_sre.SRE_Match object; span=(2, 7), match='super'>
5、其中span函数定义如下,返回位置信息:
span([group]): 
返回(start(group), end(group))。

笔记:
"""
match : 必须从字符串的开头进行匹配
search: 从任意位置开始匹配,匹配到就返回
只匹配一个
"""


42.用Python匹配HTML tag的时候, <.>和<.?>有什么区别?

术语叫贪婪匹配( <.> )和非贪婪匹配(<.?> )

笔记:
. 除了
的任意字符
* 量词,代表匹配0次或者多次,任意个
.*  贪婪匹配
.*? 非贪婪匹配

43.如何生成一个随机数?

print(random.randint(1,100))

笔记:

import random
random.random    随机获取 0<= x < 1
random.randrange 随机获取指定范围中的整数,用法上同range
random.uniform   随机获取指定范围中的小数

44. super的作用?

可以避免直接使用父类的名字.主要用于多重继承

笔记:
# 用来解决多继承之间复杂的调用关系使用super
在多继承中,如果出现了多个同名方法
super在调用的时候,会按照mro列表的继承顺序依次调用
类.mro() = > lst

45.双下划线和单”下划线的区别?

单下划线(_): 在交互解释器中,表示上一条语句执行输出的结果。另外,单下划线还可以作为特殊的临时变量,表示在后面将不会在用到这个变量。

名称前的单下划线:只能在内部使用,是API中非公开的部分,不能被 import * 和 from import *导入程序中,除非在all列表中包含了以单下划线开头的属性、方法以及类。

名称前的双下划线:以双下划线开头的属性、方法表示避免父类的属性和方法被子类轻易的覆盖,一般不建议这样定义属性和方法,除非你自己将要做什么。

名称前后的双下划线:这类方法是Python内部定义的方法,你可以重写这些方法,这样Python就可以调用这个重写的方法以及利用操作符。

笔记:
class MyClass():
	__abc = 90
	_ppp = 100
"""
封装: 公有public 私有private 受保护的protected
私有: 只能在当前这个类里面使用,不能再子类或者在类外使用
受保护的: 可以在当前这个类或者子类里使用,不能再类外使用
约定俗成在该变量前面加上一个下划线_ , 就表示受保护了
"""

46. @staticmethod和@classmethod的区 别?

1.定义方式
普通的类方法foo()需要通过self参数隐式的传递当前类对象的实例。 @classmethod修饰的方法class_foo()需要通过cls参数传递当前类对象。@staticmethod修饰的方法定义与普通函数是一样的。

self和cls的区别不是强制的,只是PEP8中一种编程风格,slef通常用作实例方法的第一参数,cls通常用作类方法的第一参数。即通常用self来传递当前类对象的实例,cls传递当前类对象。

2.绑定对象
foo方法绑定对象A的实例,class_foo方法绑定对象A,static_foo没有参数绑定。
>>> print(a.foo)
<bound method A.foo of <__main__.A object at 0x0278B170>>
>>> print(a.class_foo)
<bound method A.class_foo of <class '__main__.A'>>
>>> print(a.static_foo)
<function A.static_foo at 0x02780390>
3.调用方式
foo可通过实例a调用,类对像A直接调用会参数错误。

>>> a.foo(1)
executing foo(<__main__.A object at 0x0278B170>,1)
self: <__main__.A object at 0x0278B170>
>>> A.foo(1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() missing 1 required positional argument: 'x'
但foo如下方式可以使用正常,显式的传递实例参数a。

>>> A.foo(a, 1)
executing foo(<__main__.A object at 0x0278B170>,1)
self: <__main__.A object at 0x0278B170>
class_foo通过类对象或对象实例调用。

>>> A.class_foo(1)
executing class_foo(<class '__main__.A'>,1)
cls: <class '__main__.A'>
>>> a.class_foo(1)
executing class_foo(<class '__main__.A'>,1)
cls: <class '__main__.A'>
static_foo通过类对象或对象实例调用。

>>> A.static_foo(1)
executing static_foo(1)
>>> a.static_foo(1)
executing static_foo(1)
4.继承与覆盖普通类函数是一样的。
class B(A):
    pass
b = B()
b.foo(1)
b.class_foo(1)
b.static_foo(1)
# executing foo(<__main__.B object at 0x007027D0>,1)
# self: <__main__.B object at 0x007027D0>
# executing class_foo(<class '__main__.B'>,1)
# cls: <class '__main__.B'>
# executing static_foo(1)

笔记:
一个静态方法,一个类方法
一个静态方法:(无论是对象还是类,都可以调用,不会默认传递任何参数)
一个类方法  :(无论是对象还是类,都可以调用,会默认传递类这个参数)

47.实现一个单例模式(加锁)。

public class Singleton {
      private volatile static Singleton instance;
      
      private Singleton() {
      }
      
      public static Singleton getInstance() {
          if (instance == null) {
              synchronized (Singleton.class) {
                 if (instance == null) {
                     instance = new Singleton();
                 }
             }
         }
         
         return instance;
     }
 }

笔记:
# 单态模式:这个类无论实例化多少次,都有且只有一个对象
from threading import Lock
class MyClass(object):
	__obj = None
	lock = Lock()
	def __new__(cls,*args,**kwargs):
		with cls.lock:
			if not cls.__obj:
				cls.__obj = object.__new__(cls)
			return cls.__obj
obj1 = MyClass()
obj2 = MyClass()
print(obj1,obj2)


48.栈和队列的区别?

队列是先进先出,有出口和入口,先进去可以先出来。

栈就像一个箱子,后放上去的,可以先出来

笔记:
栈 :  先进后出,或者 后进先出
队列: 先进先出

49.以下代码输出是什么?请给出答案并解释。

class Parent (object):
    X=1
class Child1 (Parent):
    pass
class Child2 (Parent):
    pass
print(Parent.x,Chi1d1.x,Child2.x)
Child1.x = 2
print(Parent.x,Chi1d1.x,Child2.x)
Parent.x = 3
print(Parent.x,Child1.x,Child2. x)

笔记:
class Parent(object):
	x = 1
class Child1(Parent):
	pass
class Child2(Parent):
	pass
# 1 1 1
print(Parent.x, Child1.x, Child2.x)
Child1.x = 2
# 1 2 1
print(Parent.x, Child1.x, Child2.x)
Parent.x = 3
# 3 2 3
print(Parent.x, Child1.x, Child2.x)

50.参考下面代码片段

class Context:
    pass
with Content() as ctx:
   ctx. do_ something()
请在Context类下添加代码完成该类的实现

笔记:
# 面向对象的上下文管理是with语法的具体实现
class Context():
	def __enter__(self):
		return self
	def __exit__(self, exc_type, exc_val, exc_tb):
		# 相当于在最后,执行了文件的关闭操作,fp.close()
		print("abc123")
	def do_something(self):
		print(1111)

with Context() as ctx:
	ctx.do_something()
	print(ctx)

# 自动实现了关闭操作
# with open("文件") as fp:
# 	res = fp.read()



第二部分可选题

1.如何获取列表中第二大的值?

第一种方法:仅需使用sort()和pop()来实现
list26 = [ 1, 13, 5, 6, 11, 12, 7, 8, 13]
list26.sort()                                        # 先对列表元素按从小到大进行排序
count = list26.count(list26[len(list26) - 1] )       # list26[ len(list26) - 1 ]获得列表中最大元素的下标值,count(……)获得最大元素在列表中出现的次数
c = 0
while c < count:                                     # 使用while循环通过最大值出现的次数决定循环次数
    list26.pop()                                     # 使用pop()默认删除列表最后的元素,即最大元素,删除次数取决于循环次数即count()的值
    c += 1
print(list26[len(list26) - 1])             # 打印列表最后一个元素,即未删除最大元素之前的第二大值


第二种方法: 仅使用 if 判断和 while 循环
list27 = [ ]
num1 = 0
while num1 < 5:
    val1 = int(input("请输入五个数字存入列表:  "))
    list27.append(val1)
    num1 += 1
print("接下来将选出你所输入数字的第二大值:")
max = 0
sec = 0
if list27[0] > list27[1]:
    max = list27[0]
    sec = list27[1]
else:
    max = list27[1]
    sec = list27[0]
index = 2
while index < len(list27):
    if list27[index] > max:
        sec = max
        max = list27[index]
    index += 1
 
print(sec)

笔记:
# (1) 所有的容器类型数据都可以通过 sorted (sort只局限于列表进行排序)
# 去重
lst = set([98,1,100,3,-100,50,100,100])
res = sorted(lst)
res_new = res[-2]
print(res_new)



2.简述Python内存管理机制。

引用计数机制、垃圾回收机制、内存池机制

笔记:
# (2) 内存管理机制
计数器,垃圾回收,内存池
# 一.计数器
特点:引用技术如果是0,把这个值从内存中释放掉
a = 100
b = a
print(b)
del b
缺点:在维护引用计数时,又可能数据产生循环引用,造成数据不能删除,造成内存泄漏
lst1 = [1,2]
lst2 = [5,6]
lst1.append(lst2)
lst2.append(lst1)
del lst1
print(lst1)
print(lst2)
# print(lst1)
# print(lst2)

3.简述Python的垃圾回收机制。

Python中的垃圾回收是以引用计数为主,分代收集为辅。引用计数的缺陷是循环引用的问题。 在Python中,如果一个对象的引用数为0,Python虚拟机就会回收这个对象的内存。

笔记:
# 二.垃圾回收:引用计数为主,标记清除和分带回收为辅
标记清除 : 检测标记该对象,避免出现循环引用不能删除的现象
分带回收 :
	把内存中的数据分成三个区域: 新生代0,老年代1,永久代2
	新生代0数据超过700 , 或者老年代1,永久代2数据超过10,自动触发内存中的垃圾回收机制
	新生代0触发将清除所有三代的区域
	老年代1触发会清理1,2代
	永久代2触发只会清理自己
	
	
# 三.内存池
# 在同一个文件当中 (python3.6)
# -->Number 部分
	1.对于整型而言,-5~正无穷范围内的相同值 id一致
	2.对于浮点数而言,非负数范围内的相同值 id一致
	3.布尔值而言,值相同情况下,id一致
	4.复数在 实数+虚数 这样的结构中永不相同(只有虚数的情况例外)
# -->容器类型部分
	5.字符串 和 空元组 相同的情况下,地址相同
	6.列表,元组,字典,集合无论什么情况 id标识都不同 [空元组例外]
# 在不同的文件当中
	小数据池 ; 比如整型默认开辟 -5~256 这么多数据提前在内存中驻留

	


4.请用两个队列来实现一个栈。

public static class TwoQueueStack<E> {
   private Queue<E> queueA;
   private Queue<E> queueB;

   public TwoQueueStack() {
       queueA = new LinkedList<>();
       queueB = new LinkedList<>();
   }

   /**
    * 选一个非空的队列入队
    *
    * @param e
    * @return
    */
   public E push(E e) {
       if (queueA.size() != 0) {
           System.out.println("从 queueA 入队 " + e);
           queueA.add(e);
       } else if (queueB.size() != 0) {
           System.out.println("从 queueB 入队 " + e);
           queueB.add(e);
       } else {
           System.out.println("从 queueA 入队 " + e);
           queueA.add(e);
       }
       return e;
   }

   public E pop() {
       if (queueA.size() == 0 && queueB.size() == 0) {
           return null;
       }

       E result = null;
       if (queueA.size() != 0) {
           while (queueA.size() > 0) {
               result = queueA.poll();
               if (queueA.size() != 0) {
                   System.out.println("从 queueA 出队 并 queueB 入队 " + result);
                   queueB.add(result);
               }
           }
           System.out.println("从 queueA 出队 " + result);

       } else {
           while (queueB.size() > 0) {
               result = queueB.poll();
               if (queueB.size() != 0) {
                   System.out.println("从 queueB 出队 并 queueA 入队 " + result);
                   queueA.add(result);
               }
           }
           System.out.println("从 queueB 出队" + result);
       }
       return result;
   }
}

5.请用Python实现一个链表。

class SingleLinkList(object):
    """单链表"""
    def __init__(self):
        self.__head = None

    def is_empty(self):
        """判断链表是否为空"""
        return self.__head == None

    def length(self):
        """链表长度"""
        # cur初始时指向头节点
        cur = self.__head
        count = 0
        # 尾节点指向None,当未到达尾部时
        while cur != None:
            count += 1
            # 将cur后移一个节点
            cur = cur.next
        return count

    def travel(self):
        """遍历链表"""
        cur = self.__head
        while cur != None:
            print cur.item,
            cur = cur.next
        print ""

6.请用Python实现链表的逆转。

1、单链表结构
2、反转的想法
建立三个变量,L、M、R互相赋值迭代,并建立指向关系,从而实现单链表的反转。

3、python代码实现
class Node(object):
    def __init__(self, data, next=None):
        self.val = data
        self.next = next
 
def fun4(head):
    if head == None:
        return None
    L,M,R = None,None,head
    while R.next != None:
        L = M
        M = R
        R = R.next
        M.next = L
    R.next = M
    return R
#测试用例
if __name__ == '__main__':
    l1 = Node(3)
    l1.next = Node(2)
    l1.next.next = Node(1)
    l1.next.next.next = Node(9)
    l = fun4(l1)
    print (l.val, l.next.val, l.next.next.val, l.next.next.next.val)
 

原文地址:https://www.cnblogs.com/bky20061005/p/12365962.html