python笔试常见

python笔试常见,第1张

最近笔试自用整理,这几天太忙了有时间一定把格式整理好看点
写的好挺好的一些python整理
https://cloud.tencent.com/developer/article/1729102
https://zhuanlan.zhihu.com/p/54430650
https://www.php.cn/python-tutorials-392800.html
https://juejin.cn/post/6982004803945627661#heading-15
https://juejin.cn/post/6844903654143557646
https://www.cnblogs.com/chongdongxiaoyu/p/9054847.html

目录
    • Q2.Python是如何进行内存管理的
    • Q3. 列表和元组之间的区别是?
    • Q4. is和==的区别(高频,简单)
    • Q5. 浅拷贝与深拷贝
    • Q6. __new__和__init__区别
    • __call__方法
    • __str__
    • 可变对象与不可变对象总结
    • set和dict比较
    • pass
    • 装饰器
    • @为装饰器用法
    • *
    • get
    • split和strip
    • count是类变量
    • @property
    • count
    • enumerate
    • sorted
    • filter(function, iterable)

Q2.Python是如何进行内存管理的


一、垃圾回收:python不像C++,Java等语言一样,他们可以不用事先声明变量类型而直接对变量进行赋值。


对Python语言来讲,对象的类型和内存都是在运行时确定的。


这也是为什么我们称Python语言为动态类型的原因(这里我们把动态类型可以简单的归结为对变量内存地址的分配是在运行时自动判断变量类型并对变量进行赋值)。




二、引用计数:一个对象被引用时,引用计数加1,当对象被del时,引用计数减去1,为0时,对象就被清除,一般情况下用户不会去 *** 作Python 的垃圾回收机制,但它留有API接口。




三、内存池机制Python的内存机制以金字塔行,-1,-2层主要有 *** 作系统进行 *** 作,
第0层是C中的malloc,free等内存分配和释放函数进行 *** 作;
第1层和第2层是内存池,有Python的接口函数PyMem_Malloc函数实现,当对象小于256K时有该层直接分配内存;
第3层是最上层,也就是我们对Python对象的直接 *** 作;
在 C 中如果频繁的调用 malloc 与 free 时,是会产生性能问题的.再加上频繁的分配与释放小块的内存会产生内存碎片. Python 在这里主要干的工作有:
如果请求分配的内存在1~256字节之间就使用自己的内存管理系统,否则直接使用 malloc.
这里还是会调用 malloc 分配内存,但每次会分配一块大小为256k的大块内存.
经由内存池登记的内存到最后还是会回收到内存池,并不会调用 C 的 free 释放掉.以便下次使用.对于简单的Python对象,例如数值、字符串,元组(tuple不允许被更改)采用的是复制的方式(深拷贝?),也就是说当将另一个变量B赋值给变量A时,虽然A和B的内存空间仍然相同,但当A的值发生变化时,会重新给A分配空间,A和B的地址变得不再相同

python的内存管理机制=垃圾回收机制+内存池机制
(1)垃圾回收机制
垃圾回收机制以引用计数法为主,标记-清除为辅。



1.引用计数法
因为自动回收,所以没有内存泄漏的风险。



引用计数法是指在每个对象的结构体PyObject中定义一个计数变量ob_refcnt,计算该对象被引用的次数,有以下4种情况会造成引用计数变量的增加:1.该对象被引用;2.该对象被加入某容器(列表、字典等);3.对象被创建;4.该对象被作为参数传到函数中。



对应的python计数减少的情况为:1.该引用被释放,也就是说引用该对象的变量换了引用对象;2.该对象被从容器中删除;3.用del删除该对象;4.一个对象离开它的作用域,例如func函数全部执行完毕,非全局变量的对象引用计数器-1(这个引用是指创建引用的副本吗,为什么全局变量的对象计数器不变呢?)
当计数变量减少至0时,自动释放该变量。



优点:高效,自动释放,实时性高,即一旦没有引用立即释放;
缺点:1.增加存储空间,维护引用计数消耗资源;2.无法解决循环调用(一组未被外部使用、但相互指向的对象)的情况。



2.标记-清除法
标记-清除被作为解决循环调用的情况,辅助python进行垃圾回收
过程:①首先创建对象时,python会将其加入零代链表;②遍历零代链表,如果被本链表内的对象引用,自身的被引用数-1;③清除被引用数为0的对象;④其余未被回收的“活动对象”升级为一代链表 一代同样可能会触发gc机制,从而对一代链表标记清除,将剩下的活动对象升级为二代链表。


Q3. 列表和元组之间的区别是?

答:二者的主要区别是列表是可变的,而元组是不可变的

Q4. is和==的区别(高频,简单)

is判断两个对象的内存地址是否相同 而==判断两个对象的值是否相同

python中对于小整数对象有一个小整数对象池,范围在[-5,257)之间。


对于在这个范围内的征数,不会新建对象,直接从小整数对象池中取就行。



id(object)是python的一个函数用于返回object的内存地址。


但值得注意的是,python 为了提高内存利用效率会对一些简单的对象(如数值较小的int型对象,字符串等)采用重用对象内存的办法。


Q5. 浅拷贝与深拷贝

Object是对象

Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。


但是 Object.assign() 进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。



当object只有一层的时候,浅拷贝=深拷贝

浅拷贝跟深拷贝的区别吧
对于字典、列表、集合来说,浅拷贝只拷贝对应的内存地址,而深拷贝会完全复制拷贝一份新的
而对于字符串、数字这些,浅拷贝跟深拷贝都是一样拷贝一份新的。



old_dicts = {‘name’: tom, ‘age’: 18, ‘like’: [1,2,3]} 浅拷贝 new_dicts = old_dicts. copy() 修改name 或者 age (字符串和数字)时,不会相互影响,而修改like时,会互相影响。



深拷贝 new_deep_dicts = old_dicts. deepcopy() 就是完完全全复制了一份新的,从头复制到尾,是相互独立的两个字典了,不管怎么修改都不会影响到对方

Q6. __new__和__init__区别

__new__方法接受的参数虽然也是和__init__一样,但__init__是在类实例创建之后调用,而 __new__方法正是创建这个类实例的方法
所以,init 和 new 最主要的区别在于:
1.init 通常用于初始化一个新实例,控制这个初始化的过程,比如添加一些属性, 做一些额外的 *** 作,发生在类实例被创建完以后。


它是实例级别的方法。



2.new 通常用于控制生成一个新实例的过程。


它是类级别的方法。


__call__方法

call()的作用是使实例能够像函数一样被调用,同时不影响实例本身的生命周期(call()不影响一个实例的构造和析构)。


但是__call__()可以用来改变实例的内部成员的值。


str

如何调用父类(super),以及面向对象的特性

  1. 可以继承父类的方法也可以有自己新的方法
  2. 调用多个父类
可变对象与不可变对象总结

可变对象:list、dict、set 可变对象是指对象的内存值可以改变
不可变对象:int、tuple、str、bool 不可变对象是指对象的内存值不可以被改变。


改变变量时,其实质是变量指向新的地址,即变量引用新的对象

set和dict比较

set和dict一样,只是没有value,相当于dict的key集合,由于dict的key是不重复的,且key是不可变对象因此set也有如下特性:

  1. 不重复
  2. 元素为不可变对象
  3. Python 中的 tuple 结构为 “不可变序列”,用小括号表示。


    为了区别数学中表示优先级的小括号,当 tuple 中只含一个元素时,需要在元素后加上逗号。


    (1, )而不能用(1)

元组本身所指向的内存,实际上保存的是元组内数据的内存地址集合,元组一旦建立,这个内存地址集合就不能修改和删除了。


一旦集合内的地址发生改变,就必须重新分配元组空间保存新的内存地址集。



tup = (1,3,2)
a = id(tup)
tup += (4,5)
b = id(tup)
a和b地址不同
lambda
https://blog.csdn.net/PY0312/article/details/88956795
lambda [arg…]:expression
[arg…] 是参数列表,它的结构与 Python 中函数(function)的参数列表是一样的。



[arg…] 可以有非常多的形式。


例如:a, b 或 a=1, b=2
常见用法
add = lambda x, y: x+y
add就是xy的和
map函数
map(function, iterable, …)
第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表

pass

pass 一般用于占位置。



因为如果定义一个空函数程序会报错,当你没有想好函数的内容是可以用 pass 填
find和rfind
rfind()函数用于返回字符串最后一次出现的位置(从右向左查询)
find是从前往后找,返回成功匹配的第一个字符的位置索引
rfind也是从前往后找,但是返回最后一次成功匹配的字符的位置索引

装饰器

def dec(f):
n = 3
def wrapper(*args,**kw):
return f(*args,**kw) * n
return wrapper

@dec #上边函数的名字
def foo(n):
return n * 2
@函数名 装饰器,先执行dec(), 并将 @函数名 下面的 函数 作为dec()的参数。


(装饰器的作用:为已经存在的对象添加额外的功能)
foo(2)
1.先运行被修饰的函数
n=3
f * n
2.将被修饰的函数作为参数
f * 3
3.运行修饰函数
(2 * 2) * 3

@为装饰器用法

在fun()顶部写@outer 等同于将fun函数作为一个参数传入outer 写法如: fun = outer(fun)
所以先执行print (‘outer’)
return inner没有()因此inner函数不执行
pop()
list 未定义默认删最后一个
print中的pop也会删除
字典pop(key[,default]) key值必须写,否则default报错
列表乘加
a = [1,2]
b = a * 2 # [1, 2, 1, 2]
b中【1,2】地址一样,改一个都改
a = [1, 2, 3]
print(a+b)
输出:[1, 2, 3, 4, 5, 6]
b = [4, 5, 6]
print(a+b)
正则化
re模块实现正则的功能
re.match(正则表达式,要匹配的字符串,[匹配模式])

要匹配的字符串为str1 = “Python’s features”

正则表达式r’(.)on(.?) .
r表示后面的字符串是一个普通字符串(比如\n会译为\和n,而不是换行符)
()符号包住的数据为要提取的数据,通常与.group()函数连用。



.匹配单个任意字符
匹配前一个字符出现0次或无限次
?匹配前一个字符出现0次或1次
(.
)提取的数据为str1字符串中on左边的所有字符,即Pyth
(.
?)提取的数据为str1中on右边,空格前面,即’s

.group(0)输出的是匹配正则表达式整体结果
.group(1) 列出第一个括号匹配部分,.group(2) 列出第二个括号匹配部分

list Insert
Insert函数用于将指定对象插入列表的指定位置,从另一方面理解,新插入的数据代替了原来该位置的数据,视觉上是在指定位置的‘前面’插入了一个对象。


不会剥掉外面【】
replace
strs.replace(‘a’, ‘‘, 2):将strs中的头2个(如果有)字符’a’替换为’’,2为最大替换次数
remove
remove()函数用于移除列表中某个值的第一个匹配项。



除法
Python2 中除法默认向下取整,因此 1/2 = 0,为整型。


而 Python3 中的除法为正常除法,会保留小数位,因此 1/2 = 0.5,为浮点型。


● Python中,打开文件语法为
1 text = oepn(filePath, *** 作方式,编码方式)
● 常见 *** 作方式
○ ‘r’:读
○ ‘w’:写
○ ‘a’:追加
● 常见编码方式
○ utf-8
○ gbk

*

如果你希望强迫调用者使用某些参数,且必须以关键字参数的形式传参,那么你只需要在所需位置的前一个位置放置一个*。


def f1(a, *, b, c): return a + b + c 对于上面这个函数而言,调用时参数a可以任意值, 但b,c参数一定要以关键字参数的形式传参,如f1(1, b=4, c=5),否则将会报错。


def fun(a,*args,b):
print(b)
def fun1(a,b=1,*args):
print(args)

#fun(1,2,3,4) # TypeError: fun() missing 1 required keyword-only argument: ‘b’
fun1(1,2,3,4) # (3, 4)

def test(a,b,*args)
a,b位置参数;*args为不定长位置参数,传入的参数被放入一个元祖里。



所以,a,b分别被赋值11、22,而其他的数被存到一个元组里。


get

获取字典dict中key的值:dict.get(key,default=None),如果key在dict中则返回对应的值,否则返回default的值,其中default的值可自己指定

set去重
set 类型的特性是会移除集合中重复的元素,因此变量 nums 实际上等于:
1 nums ={1, 2, 3, 4}
B项:字典去重
b = {} # 字典
a = [1,2,3,1,2,4,6]

#利用字典去重
dic = b.fromkeys(a) # {1: None, 2: None, 3: None, 4: None, 6: None}
b = list(dic) # <==> list(dic.keys())
C项:列表推导去重
a.sort()
b = []
i = 0
while i < len(a):
if a[i] not in b:
b.append(a[i])
else:
i += 1
print
打印中的函数会再调用一次!!!

split和strip

(1)str.split(str=“”, num=string.count(str)) str – 分隔符,默认为所有的空字符,包括空格、换行(\n)、制表符(\t)等。


num – 分割次数。


没有数值, 即分隔所有。


有数值num,就分割num次,后面再出现分割条件,次数超出,不再进行分割。



(2)str.strip([chars]) chars – 移除字符串’头尾’指定的字符序列。



split(" "):按一个空格分隔;
strs:首尾空格只有一个;
strip():仅删除首尾空格;

strs = ’ I like python ’
one = strs.split(’ ‘)
two = strs.strip()
print(one)
print(two)
首尾空格也被分出来
[’ ', ‘I’, ‘like’, ‘python’, ’ '],‘I like python’

dict中fromkey和str中的format
tmp = dict.fromkeys([‘a’, ‘b’], 4)
print(tmp)
{‘a’: 4, ‘b’: 4}

Python 字典 fromkeys() 函数用于创建一个新字典,以序列 seq 中元素做字典的键,value 为字典所有键对应的初始值。



seq=[‘a’, ‘b’]
value=4

字典的键要求可哈希,不可哈希,会报错
可哈希对象:数字类型(int,float,bool)、字符串str、元组tuple、自定义类的对象
不可哈希对象:列表,集合和字典
超出切片索引
对于py3列表切片lists[start:end],当start为自然数且超出索引时,默认返回空列表[ ]
当end超出索引,截取到最后

类和对象变量赋值
class Base(object):
count = 0
def init(self):
pass
b1 = Base()
b2 = Base()
b1.count = b1.count + 1
print(b1.count,end=" “)
print(Base.count,end=” ")
print(b2.count)
返回 1 0 0

count是类变量

● 通过类名修改类变量,会作用到所有的实例化对象
● 通过类对象是无法修改类变量的。


通过类对象对类变量赋值,其本质将不再是修改类变量的值,而是在给该对象定义新的实例变量

@property

使用@property将方法转换为只读属性,只能访问不能修改
表示我们可以使用@property装饰器来创建只读属性,@property装饰器会将方法转换为相同名称的只读属性,可以与所定义的属性配合使用,这样可以防止属性被修改。



● A 我们在使用属性的时候 只需要 rectangle.area即可 后面不需要加括号
● B 只读不可修改了
● C __init__每次实例化对象的时候自动调用,所以C正确
● D python里面没有严格的私有属性,还是可以访问的,rectangle_Rectangle__width访问width属性
rectangle_Rectangle__height访问height属性
列表超范围

类型转换

count

需要考虑大小写
A搜不到a

enumerate

enumerate() 函数用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在 for 循环当中。



1 enumerate(sequence, [start=0]) #enumerate语法
i j
0 1
1 2
2 3
3 4
其中i为索引,j为数据对象list中元素,所以tmp = 0x1+1x2+2x3+3x4 = 20

sorted

方法返回一个新的列表,id指向内存空间,不一致
[1,2]+[3,4]地址不变
逻辑顺序
优先级从高往低依次为not、and、or
函数调用
return inner()才会被调用
inner没括号,返回的是inner函数的地址
set tuple
set是去重 集合
tuple是不可更新 地址会换 元祖

filter(function, iterable)

filter函数是python中的高阶函数, 第一个参数是一个筛选函数, 第二个参数是一个可迭代对象, 返回的是一个生成器类型, 可以通过next获取值. 这里大致讲述下原理, filter()把传入的function依次作用于iterable的每个元素, 满足条件的返回true, 不满足条件的返回false, 通过true还是false决定将该元素丢弃还是保留.
所以对2和4取余为0舍弃1.3.5取余为1为真保留;
数据分析之机器Python高频面试题及答案

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/577902.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-11
下一篇 2022-04-11

发表评论

登录后才能评论

评论列表(0条)

保存