python基础面试题

1.Python的特点
  • Python是一种解释性语言【开发过程中没有了编译这个环节,类似于PHP或者Perl语言】
  • Python是交互式语言【可以在一个Python提示符,直接互动执行程序】
  • Python是面向对象语言【Python支持面向对象的风格或代码封装在对象的编程技术】
  • Python是初学者的语言【Python对于初级程序员而言,是一种伟大的语言,他支持广泛的应用程序开发,从简单的文字处理到浏览器再到游戏】
  • Python是跨平台的【它可以运行在Windows、Mac os或者Linux系统上,也就是说,在Windows上书写的Python程序,在Linux上也是可以运行的,类似于Java】
2.Python优缺点

优点:

  • 易于学习【Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单】

  • 易于阅读【Python代码定义的更清晰】

  • 易于维护【Python的成功在于它的源代码是相当容易维护的】

  • 一个广泛的标准库【Python的最大优势之一是丰富的库,跨平台的,在nuix、weindows和mac os上的兼容性很好】

  • 互动模式【互动模式的支持,可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片段】

  • 可移植性【基于其开发源代码的特性,Python已经被移植到许多平台】

  • 可扩展性【如果需要一段运行很快的关键代码,或者想要编写一些不愿开发的算法,可以使用C或者C++完成那部分程序,然后从你的Python程序中调用】

  • 数据库【Python提供所有主要的商业数据库的接口】

  • GUI编程(图形化界面)【Python支持GUI可以创建和移植到许多系统调用】

  • 可嵌入性【可以将Python嵌入到C或者C++程序,让你程序的用户获得“脚本化”的能力】

    点:

  • 运行速度慢【和C程序相比非常慢,因为Python是解释型语言,代码在执行时会一行一行的翻译成CPU能理解的机器码,这个翻译过程非常耗时,所以很慢,而C程序是运行前直接编译成CPU能执行的机器码,所以非常快】

  • 代码不能加密【如果要发布Python程序,实际上就是发布源代码,这一点跟C语言不通,C语言不用发布源代码,只需要把编译后的机器码(就是windows上常见的xxx.exe)发布出去,要从机器码反推出C代码是不可能的,所以,凡是编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去】

3.Python应用场景【面试题】
  • Web开发【通过mod_wsgi模块,Apache可以运行用Python编写的Web程序。Python定义了WSGI标准应用接口来协调Http服务器与基于Python的Web程序之间的通信。一些Web框架,如Django,TurboGears,web2py,Zope等,可以让程序员轻松地开发和管理复杂的Web程序】

  • 操作系统管理、服务器运维的自动化脚本【在很多操作系统里,Python是标准的系统组件。 大多数Linux发行版以及NetBSD、OpenBSD和Mac OS X都集成了Python,可以在终端下直接运行Python。Python编写的系统管理脚本在可读性、性能、代码重用度、扩展性几方面都优于普通的shell脚本】

  • 网络爬虫【Python有大量的HTTP请求处理库和HTML解析库,并且有成熟高效的爬虫框架Scrapy和分布式解决方案scrapy-redis,在爬虫的应用方面非常广泛】

  • 科学计算(数据分析)【NumPy、SciPy、Pandas、Matplotlib可以让Python程序员编写科学计算程序】

  • 桌面软件【PyQt、PySide、wxPython、PyGTK是Python快速开发桌面应用程序的利器】

  • 服务器软件(网络软件)【Python对于各种网络协议的支持很完善,因此经常被用于编写服务器软件、网络爬虫。第三方库Twisted支持异步网络编程和多数标准的网络协议(包含客户端和服务器),并且提供了多种工具,被广泛用于编写高性能的服务器软件】

  • 游戏【很多游戏使用C++编写图形显示等高性能模块,而使用Python或者Lua编写游戏的逻辑、服务器。相较于Python,Lua的功能更简单、体积更小;而Python则支持更多的特性和数据类型】

  • 自动化测试

    搜狐、豆瓣、腾讯、网易、百度、阿里、淘宝、土豆、新浪等都在内部大量的使用Python

4.标识符【面试题】

概念:计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系

合法标识符的命名规则:

  • 只能由数字,字母和下划线组成
  • 不可以是除了下划线之外的其他特殊字符
  • 开头不能是数字或者空格
  • 不能是Python的关键字
  • 严格区分大小写 age Age

标识符的命名规范:

  • 尽量做到见名知意【具有描述性】:尽量使用简单的英文单词表示
  • 遵守一定的命名规范
    • Python官方推荐的命名方式:变量名,函数名和文件名全小写,使用下划线连接,如:stu_name check_qq
    • 驼峰命名法:不同的单词之间使用首字母大写的方式进行分隔,又分为大驼峰和小驼峰,比如:stuName就是小驼峰,StuName就是大驼峰,小驼峰常用于变量或者函数的命名,大驼峰常用于类的命名
5.列出Python中常用的数据类型,至少5种【面试题】
  • 方式一:数字类型,布尔类型,字符串类型,列表类型,元组类型,字典类型,集合类型,字节类型,空值
    方式二:int/float,bool,str,list,tuple,dict,set,bytes,NoneType
6.【面试题】下面那些标识符是合法【规则】的,如果不合法,说明原因
    name
    name1
    name_1
    1name     不合法,数字不能开头
    @java     不合法,只能使用下划线
    abc$123    不合法,只能使用下划线
    xiaoming  
7.【面试题】:打包pack和拆包unpack
##### *:所有

m1,m2,*m3 = 34,56,2,56,56,67,68,8,89
print(m1,m2,m3)
m1,*m2,m3 = 34,56,2,56,56,67,68,8,89
print(m1,m2,m3)
*m1,m2,m3 = 34,56,2,56,56,67,68,8,89
print(m1,m2,m3)

m1,m2,*m3 = 34,56,2,56,56,67,68,8,89
print(m1,m2,*m3)

m1,*m2 = [34,5,6,7,8]
print(m1,m2)
8.【面试题】:交换两个变量的值
##### 方式一:定义第三方变量

a = 10
b = 20
temp = a
a = b
b = temp
print(a,b)

# 方式二           ******

a = 10
b = 20
a,b = b,a
print(a,b)

# 方式三:加减法

a = 10
b = 20
a = a + b  # a = 30
b = a - b  # b = 10
a = a - b  # a = 20
print(a,b)
9.【面试题】:重点:短路原则
a.A and B,如果A为False,不需要计算B的值,整个表达式的结果为False

b.A or B,如果A为True,不需要计算B的值,整个表达式的结果为True

c.andor混合使用

​```
1>表达式从左往右运算,如果or的左侧为True,则会短路or后面所有的表达式【不管是and还是or连接】,整个表达式的结果为True

2>表达式从左往右运算,如果and的左侧为False,则短路后面所有的and,直到or出现,接着计算

3>如果or的左侧为False,或者and的左侧为True,则不能使用短路逻辑判断
​```

注意:所有被短路的表达式均不会被输出
【面试题】
A and B
    如果A为真,则A and B的结果是B
    如果A为假,则A and B的结果是A
10.【面试题】:身份运算符用于比较两个对象的存储单元
is:判断两个标识符是不是引用自一个对象
	is not:判断两个标识符是不是引用自不同对象
"""

"""
【面试题】可变数据类型和不可变数据类型
    可变数据类型:list  dict   set
    不可变数据类型:int  float bool str tuple

【面试题】说明is==的区别和联系
    a.==比较的是内容
    b.is比较的是地址
    c.如果两个变量的内容相同,他们的地址不一定相同,如果两个变量的地址相同,则他们的内容一定相同
"""
11.【面试题】简述break和continue的区别
  • break是一个关键字,可以单独作为一条语句使用
  • break的作用:主要应用在循环中,作用是结束循环
  • 2.continue是一个关键字,可以单独作为一条语句使用
  • continue表示结束本次循环,继续下一次循环
12.【面试题】切片
切片:根据指定的区间,通过某种规律在列表,元组或者字符串中进行截取,形成一个新的列表,元组或字符串
语法:列表[start:end:step]
    start:开始索引,可以省略,默认为0,不省略的情况下包含在内
    end:结束索引,可以省略,默认为最后一个【正数或负数】,不省略的情况下不包含在内
    step:步长,可以省略,默认为1

0   1   2   3   4   5   6   7   8
-9 -8  -7  -6  -5  -4  -3  -2   -1

注意:
    a.只要切片的语法正确,哪怕获取不到元素,都不会报错
    b.切片之后会得到一个新的列表,对原列表没有任何影响
    # 5.start和end都为正数
"""
结论1:
    如果start和end同符号,遵循下面的规律
    a.计算start + step
    b.判断上述结果是否在start和end区间内
    c.如果不在,则结果直接为[],如果在,则依次获取
   # 7.start和end一个为正数,一个为负数
"""
结论:
    如果start和end一个为正数,一个为负数,则以start的正负作为参考
    如果start为正,end为负数,则使用正数索引
    如果start为负,end为正数,则使用负数索引
"""
print(numlist[-6:1:1])    # []
print(numlist[-6:-8:1])   # []

print(numlist[-6:1:-1])   # [44,33]
print(numlist[-6:-8:-1])  # [44,33]
# 6.
"""
列表[start::step]
    step为正数:则从左往右获取
    step为负数:则从右往左获取
"""
print(numlist[6::1])
print(numlist[6::-1])
12.【面试题】append和extend都作为向列表中添加元素的功能,有什么区别和联系
  • 相同点:
  • ​ a.元素都会出现在列表的末尾
  • ​ b.都可以添加单个或多个元素
  • ​ c.都是在原列表的基础直接操作的
  • 不同点:
  • ​ a.append可以追加任意类型的数据,而extend只能添加可迭代对象
  • ​ b.如果向列表中添加一个可迭代对象,append会将可迭代对象整体添加,而extend只会添加可迭代对象中的元素
# 补充:append()和pop()

"""
append()是在列表的末尾添加元素
pop()将列表末尾的元素删除

列表的工作原理:列表的底层维护了一个栈的数据结构,而栈的工作特点:先进后出,后进先出,理解:一个开口向上的容器

队列:先进先出,后进后出,理解:一个水平放置的水管
13.【面试题】列表拷贝
  • 浅拷贝结论:
    一维列表:会将拷贝的列表开辟一份新的内存空间,所以其中一个列表中的元素修改,对另一个列表没有影响
    多维列表:本质是一个浅拷贝,只会拷贝最外层的地址,所以如果一个列表修改内层列表的元素,另一个列表会随着修改。
  • 深拷贝结论:两个列表指向不同的内存空间,不管是几维列表,所有的内容都会被重新拷贝,其中一个列表中的元素发生修改,则访问另一个列表,没有任何影响。
# 面试题一
# a.
a = [1,2,3]
b = [4,5]
c = [a,b]
d = c
e = c.copy()
a.append(6)
print(c,d,e)
"""
c:[[1,2,3,6],[4,5]]
d:[[1,2,3,6],[4,5]]
e:[[1,2,3,6],[4,5]]
"""

a = [1,2,3]
b = [4,5]
c = [a,b]
d = c
e = c.copy()
c.append(6)
print(c,d,e)
"""
c:[[1,2,3],[4,5],6]
d:[[1,2,3],[4,5],6]
e:[[1,2,3],[4,5]]
"""

# 面试题二
a = [1,2,['a','b']]
b = a
c = copy.deepcopy(a)
a[-1].append(3)
print(a,b,c)
"""
a:[1,2,['a','b',3]]
b:[1,2,['a','b',3]]
c::[1,2,['a','b']]
"""

# 面试题三
a = [1,2,['a','b']]
b = a
c = copy.copy(a)
a.append(3)
print(a,b,c)
"""
a:[1,2,['a','b'],3]
b:[1,2,['a','b'],3]
c:[1,2,['a','b']]
"""
14.【面试题】简单算法
# 冒泡排序
# 以升序为例
list1 = [45,6,8,9,2,56,68,98,100,56,4,19]
# 外层循环:控制比较的轮数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,兼顾参与比较的下标
    for j in range(len(list1) - 1 - i):
        # 相邻两个元素比较大小
        # 如果下标小的元素  > 下标大的元素,则交换位置
        if list1[j] > list1[j + 1]:
            list1[j],list1[j + 1] = list1[j + 1],list1[j]
print(list1)
# 选择排序
# 以升序为例
list1 = [45,6,8,9,2,56,68,98,100,56,4,19]
# 外层循环:控制比较的轮数
for i in range(len(list1) - 1):
    # 内层循环:控制的是每一轮比较的次数,兼顾参与比较的下标
    for j in range(i + 1,len(list1)):
        # 相邻两个元素比较大小
        # 如果下标小的元素  > 下标大的元素,则交换位置
        if list1[i] > list1[j]:
            list1[i],list1[j] = list1[j],list1[i]
print(list1)
二分法查找:
# 以升序为例
list1 = [34,6,7,8,9,40,26,7,73,48,737]
list1.sort()
key = 7

left = 0
right = len(list1) - 1

while left <= right:
    # 计算中间下标
    middle = (left + right) // 2
    # 比较
    if key  > list1[middle]:
        # 后半部分:重置left的值
        left = middle + 1
    elif key < list1[middle]:
        # 前半部分:重置right的值
        right = middle - 1
    else:
        print(f"待查找元素{key}在列表中的下标为{middle}")
        # 查找到元素,则提前结束循环
        break
else:
    print(f"待查找元素{key}在列表中不存在")
   
15.【面试题】元组
# a
t1 = (34,5,6,6,2,7,[1,2,3])
print(id(t1[-1]))
t1[-1][0] = 100
print(t1)    # (34, 5, 6, 6, 2, 7, [100, 2, 3])
print(id(t1[-1]))

# b.
# l1 = [3,5,6,7,7,(4,6,7)]
# l1[-1][0] = 100
# print(l1)  # 报错
16.【面试题】列表和字典的区别
  • 格式:列表:[] 字典:{}
  • 存储的数据:列表中可以存储任意类型的数据,
  • 字典中存储的是键值对,其中键只能是不可变的数据类型,值可以是任意的类型
  • 是否可变:列表是可变的,字典是可变的
  • 是否有序:列表是有序的,字典Python3.7之前是无序的,3.7之后是有序的
  • 是否可以存储重复数据:列表中可以存储重复数据,字典中的键是唯一的,值可以重复
  • 使用的场景不同:列表常用与可以存储同类型的数据,字典常用于可以存储同一个对象的不同信息 或者 需要精确定位到某个数据。
17.【面试题】使用不同的方式定义字典,至少两种
# 方式一               ******
info_dict = {"name":"张三","age":18,"hobby":"吹牛逼"}
print(info_dict)

# 方式二                  ******
dict1 = {}
dict1['aaa'] = 10
dict1['bbb'] = 20
print(dict1)

# 方式三:
# dict(key1=value1,key2=value2.....)
dict2 = dict(x=10,y=20,z=30)
print(dict2)  # {'x': 10, 'y': 20, 'z': 30}
# 问题:采用dict(key1=value1,key2=value2.....)方式,字典的key只能是字符串
# d1 = {10:1,20:2}
# d2 = dict(10=1,20=2)

# 方式四
# dict([(key1,value1),(key2,value2).....])
dict3 = dict([('a',11),('b',22),('c',33)])
print(dict3)
dict3 = dict([(10,11),('b',22),('c',33)])
print(dict3)

# 方式五:                  *******
# 映射
# dict(zip([key1,key2....],[value1,value2...]))
dict4 = dict(zip(['name','age','score'],['jack',17,100]))
print(dict4)
dict4 = dict(zip(('name','age','score'),['jack',17,100]))
print(dict4)
dict4 = dict(zip(('name','age','score'),('jack',17,100)))
print(dict4)
dict4 = dict(zip(['name','age','score','height'],['jack',17,100]))
print(dict4)
dict4 = dict(zip(['name','age','score'],['jack',17,100,456,67,8]))
print(dict4)

# 注意:不管通过哪种方式定义字典,字典的key都不能是列表,字典,集合等可变的数据类型
18.【面试题】需求:已知一个字典dict1 = {‘a’:10,“b”:20},交换键值,生成一个新的字典
dict1 = {'a':10,"b":20}
# 方式一
dict2 = {}
for key in dict1:
    dict2[dict1[key]] = key
print(dict2)
# 方式二
dict2 = {}
for key,value in dict1.items():
    dict2[value] = key
print(dict2)
# 方式三
dict2 = dict(zip(dict1.values(),dict1.keys()))
print(dict2)
# 方式四
dict2 = {value:key for key,value in dict1.items()}
print(dict2)
# 方式五:
dict2 = {dict1[key]:key  for key in dict1}
print(dict2)

# 练习:生成一个字典{0:0,1:1,2:4,3:9,4:16,5:25}
dict3 = {i:i ** 2 for i in range(6)}
print(dict3)
19.【面试题】同列表推导式,可以同时使用多个for循环或者多个if语句
list1 = [a + b for a in "xyz" for b in '123']
print(list1) # ['x1', 'x2', 'x3', 'y1', 'y2', 'y3', 'z1', 'z2', 'z3']
dict4 = {a:b for a in "xyz" for b in '123'}
print(dict4)  # {'x': '3', 'y': '3', 'z': '3'}
20.【面试题】:简述列表,元组,字典,集合和字符串的区别
  • 列表的本质:list,是一种有序的,可变的,可以存储重复元素的,可以存储不同类型的集合

  • 元组的本质:tuple,是一种有序的,不可变的,可以存储重复元素的,可以存储不同类型的集合

  • 字典的本质:dict,是一种有序的【Python3.7之后】,可变的,key不可以重复,

    ​ 但是value可以重复,key只能是不可变的数据类型,vlue可以是任意的类型的 集合

  • 集合的本质:set,是一种无序的,可变的,不可以存储重复元素的,可以存储不同类型的集合

  • 字符串的本质:str,是一种有序的,不可变的,可以存储重复字符的集合

21.【面试题】字符串替换
# name = "gouguoQ "
# name.replace("o","p")
# print(name)
# 注意1:默认将原字符串中的old全部替换
name = "gouguoQo3635o54ooo "
d1 = name.replace("o","p")
print(d1)
# 注意2:未省略count,则表示从左往右替换count个字符
d1 = name.replace("o","p",3)
print(d1)

# 注意3:可以采用映射替换设置替换的规则
# 注意4:在映射替换中,创建映射表使用的字符串的长度必须相等
name = "41564518"
table = str.maketrans("123456","abcdef")
print(table)  # {49: 97, 50: 98, 51: 99, 52: 100, 53: 101, 54: 102}
d2 = name.translate(table)
print(d2)
22.【面试题】编码和解码
编码:将字符串类型转换为字节类型,bytes()或encode()
解码:将字节类型转换为字符串类型,str()或decode()

字符串:''   ""
字节:b''   b""

编码格式:
    utf-8
    gbk
"""

# 1.编码
str1 = "3454hajgaj发哈哈%¥#@"
# a.bytes()
r1 = bytes(str1,encoding="utf-8")
print(r1)
print(type(r1))

# b.字符串.encode()
r2 = str1.encode(encoding="gbk")
print(r2)
print(type(r2))

# 2.解码
# 注意:编解码采用的格式必须保持一致
# a.str()
r3 = str(r1,encoding="utf-8")
print(r3)
print(type(r3))

# b.字节.decode()
r4 = r2.decode(encoding="gbk")
print(r4)
print(type(r4))

# 扩展
# f = open(r"file1.txt","w",encoding="gbk")
# f.write("你好hello")
# f.close()
23.【面试题】简述函数传参过程中,值传递和引用传递的区别
 值传递:传参的时候,传递的是不可变的数据类型,如:int/float/bool/str/tuple等,当形参发生修改,实参没有影响
    引用传递:传参的时候,传递的是可变的数据类型,如:list/dict.set等,当形参发生元素的修改,则实参会随着修改
"""

# 1.值传递
def func1(num):
    print(f"修改之前,num的id:{id(num)}")
    num = 100
    print(f"修改之后,num的id:{id(num)}~~~~~")
temp = 45
func1(temp)
print(f"函数调用完毕,temp的id:{id(temp)}")

print("*" * 50)

# 2.引用传递
# a
def func1(num):
    print(f"修改之前,num的id:{id(num)}")
    num = 100
    print(f"修改之后,num的id:{id(num)}~~~~~")
temp = [10,20,30]
func1(temp)
print(f"函数调用完毕,temp的id:{id(temp)}")

# b
def func1(num):
    print(f"修改之前,num的id:{id(num)}")
    num[1] = 100
    print(f"修改之后,num的id:{id(num)}~~~~~")
    print(num)
temp = [10,20,30]
func1(temp)   # num = temp
print(f"函数调用完毕,temp的id:{id(temp)}")
print(temp)
24.【面试题】字符串
name = "fahJFGk"
name.upper()
print(name)   # fahJFGk

name = "fahJFGk"
name = name.upper()
print(name)  # FAHJFGk
25.【面试题】输出
def  func():
    a = []
    for i in range(5):
        # a列表中添加的是函数的定义
        a.append(lambda x:i * x)
    return a
r = func()
print(r)
print(r[0](2))  # 函数的调用,i的值是4,2传值给x,返回值永远都是2 * 4
print(r[1](2))
print(r[2](2))
print(r[3](2))
print(r[4](2))

"""
def x1(x):
    return x * i
def x2(x):
    return x * i
def x2(x):
    return x * i
def x3(x):
    return x * i
def x4(x):
    return x * i
r[0](2) --->x1
r[1](2) ---》x2
"""
26.【面试题】什么是匿名函数,优缺点
  • 是一个lambda表达式,本质上还是一个函数,可以设置必需参数,默认参数,关键字参数和不定长参数
  • ​ 只不过表达式的执行结果就是函数的返回值
  • ​ 优点:
  • ​ 简化代码
  • ​ 减少内存空间的使用
  • ​ 缺点:
  • ​ 只能实现简单的逻辑,逻辑一旦复杂,如果使用,代码的可读性会降低,后期的维护性降低,则不建议使用
27.【面试题】局部变量和全局变量的作用
# a
n = 9
def check():
    n = 1
    print(n)  # 1
check()
print(n)  # 9

# b.
# n = 9
# def check():
#     n += 1   # n = n + 1
# check()
# print(n)

# UnboundLocalError: local variable 'n' referenced before assignment
 # global  n,声明n变量来自于全局变量,则在函数中出现的n将不再是重新定义的新变量
 # nonlocal x,声明x不是局部变量,而是来自于函数作用域的变量
28.【面试题】简述可迭代对象和迭代器之间的区别和联系
  • 区别:
  • ​ 可迭代对象:Iterable,可以直接作用于for循环的对象【可以使用for循环遍历其中元素的对象】,
  • ​ 如:list,tuple,dict,set,str,range(),生成器等
  • ​ 迭代器:Iterator,可以直接作用于for循环,或者可以通过next()获取下一个元素的对象,
  • ​ 如:生成器
  • 联系:
  • ​ 迭代器一定是可迭代对象,可迭代对象不一定是迭代器
  • ​ 但是,可以通过系统功能iter()将不是迭代器的可迭代对象转换为迭代器
29.【面试题】分别解释什么是列表推导式,字典推导式,集合推导式,生成器,可迭代对象,迭代器
30.【面试题】说明sort()和sorted()之间的区别和联系
  • 相同点:
    a.二者都是用来排序的
    b.默认的情况下,二者都是升序,如果要降序,都是设置reverse=True
    c.如果要自定义排序规则,二者都是设置key,key的值都得是一个函数
  • 不同点:
    a.调用方式不同:列表.sort() , sorted(列表)
    b.sort是在原列表内部排序的,sorted是生成了一个新的列表
31.【面试题】:书写一个装饰器,统计下面函数的执行时间
import time
# print(time.time())  # 时间戳:从1970.1.1 00:00:00到当前时间的秒数
# a.
def test():
    for i in range(100000):
        pass
def wrapper(func):
    def get_time():
        # 开始时间戳
        start = time.time()
        func()
        # 结束时间
        end = time.time()
        return  round(end - start,5)
    return get_time
f = wrapper(test)
print(f())

# b.
def wrapper(func):
    def get_time():
        # 开始时间戳
        start = time.time()
        func()
        # 结束时间
        end = time.time()
        return  round(end - start,5)
    return get_time
@wrapper
def test():
    for i in range(100000):
        pass
print(test())
【面试题】:书写一个装饰器,可以统计任意一个函数的执行时间
import  time
def wrapper(func):
    def get_time(*args,**kwargs):
        # 开始时间戳
        start = time.time()
        func(*args,**kwargs)
        # 结束时间
        end = time.time()
        return  round(end - start,5)
    return get_time

print("*" * 30)
32.【面试题】@xxx被称为无参装饰器,@xxxx(value)有参的装饰器
"""
def outter(a):
    def inner(b):
        pass
    return inner

@outter(value)
def func():
    pass
    
工作原理:
    a.自动调用装饰器的内外部函数
    b.将装饰器的参数value传参给外部函数的参数a,将被修饰的函数传参给内部函数的参数b
    c.原函数的函数名指向内部函数的返回值
"""
base_dict = {}
def add(name):  # 111 222  333
    def inner(data):  # func1   func2  func3
        base_dict[name] = data
        data()
        return 23
    return inner
@add("111")
def func1():
    print("func~~~1111")
@add("222")
def func2():
    print("func~~~2222")
@add("333")
def func3():
    print("func~~~3333")
print(base_dict)

print(func1)  # 23
print(func2)  # 23
print(func3)  # 23
33.【面试题】自定义模块的优点:
  • 提高代码的可维护性
  • 提高了代码的复用度,当一个模块书写完毕,可以被多个地方引用
  • 引用其他的模块
  • 避免函数名和变量名的命名冲突

注意:其实一个.py文件就是一个模块

34.【面试题】splitext(path) 路径进行分割
# 结果为一个元组,格式:(父路径,扩展名),如果指定路径是一个文件夹,则扩展名为""
r2 = os.path.splitext(p1)
print(r2)  # ('C:\\Users\\zhangbingbing\\Desktop\\XA2102\\Day11', '')

p2 = r"C:\Users\zhangbingbing\Desktop\XA2102\Day1\notes\Day1笔记.md"
r2 = os.path.splitext(p2)
print(r2)  # ('C:\\Users\\zhangbingbing\\Desktop\\XA2102\\Day1\\notes\\Day1笔记', '.md')
35.【面试题】简述实例属性【对象属性】和类属性之间的区别
  • a.定义的位置不同:类属性直接定义在类中,实例属性可以通过动态绑定 或者 定义在构造函数中
  • b.访问的方式不同:类属性可以通过对象或类名访问,而实例属性只能通过对象访问
  • c.优先级不同:在类属性和实例属性重名的情况下,使用对象访问,优先访问的是实例属性
  • d.在内存中出现的时机不同:类属性优先于实例属性出现在内存中,类属性随着类的加载而出现,实例属性随着对象的出现而出现
  • e.使用场景不同:类属性适用于多个对象共享的数据,实例属性适用于每个对象特有的数据
36.【面试题】普通实例函数和__init__之间的区别和联系
  • 不同点:
  • ​ a.函数名不同:实例函数的函数名需要自定义,但是,__init__是固定的,是系统的函数
  • ​ b.调用不同:实例函数需要手动调用,__init__是在创建对象的过程中自动调用的
  • ​ c.调用的次数不同:对于同一个对象而言,实例函数可以被调用无数次,__init__只会被调用一次
  • 相同点:
  • ​ a.定义在类中,本质上都是实例函数,形参列表的第一个参数都是self
  • ​ b.默认参数,关键字参数,不定长参数都可以使用
  • ​ c.也可以设置返回值
37.【面试题】析构函数的调用时机
38.【面试题:面向对象语言的三大特征是什么?是什么?分别解释怎么使用?有什么作用】
39.【面试题】阅读下面的代码,写出执行结果
"""
class Person():
    @property
    def show(self):
        return 10
p = Person()
# p.show()
# 报错,被@property修饰的函数会被当做属性使用,则p.show的值为show函数的返回值
# 修改方式:p.show()--->r = p.show
40.【面试题】解释下面不同形式的变量出现在类中的意义
  • a:普通属性,在类的外面可以直接访问

  • _a:在类的外面可以直接访问,但是不建议使用,容易和私有化属性混淆

  • __a:私有属性,只能在类的内部被直接访问,类的外面可以通过暴露给外界的函数访问

  • a:在类的外面可以直接访问,但是不建议使用,因为系统的属性和魔术方法都是这种形式的命名,

  • ​ 如:slots,init.del,new,add,sub,mul,gt,lt,eq,ne,__str__等

41.【面试题】写出下面打印结果
class MyClass(object):
    x = 10
class SubClass1(MyClass):
    pass
class SubClass2(MyClass):
    pass
print(MyClass.x,SubClass1.x,SubClass2.x)   # 10  10 10
SubClass1.x = 20
print(MyClass.x,SubClass1.x,SubClass2.x)  # 10 20 10
MyClass.x = 30
print(MyClass.x,SubClass1.x,SubClass2.x)  # 30 20 30
42.【面试题】简述类中的实例函数,静态函数和类函数之间的区别
  • a.定义不同:被@classmethod修饰的函数表示类函数,被@staticmethod修饰的函数表示静态函数,实例函数没有装饰器

  • b.形参列表不同:实例函数的第一个参数是self,表示当前对象,类函数的第一个参数是cls,表示当前类,静态函数的参数没有要求

  • c.调用方式不同:类函数和静态函数都可以通过类名或者对象调用,但是,实例函数只能通过对象调用

  • d.使用场景不同:如果要封装一个工具类,则尽量使用类函数或静态函数,在实际项目开发中,常用实例函数

  1. 【面试题】编写程序,定义一个学生类,统计该类总共实例化了几个学生

    # 方式一
    class Person(object):
        __count = 0
        @classmethod
        def __init__(cls,name,age):
            cls.__count += 1
            cls.name = name  # 类属性
            cls.age = age
        @property
        def count(self):
            return self.__count
    
    # 方式二
    class Person1(object):
        __count = 0
        def __new__(cls, *args, **kwargs):
            cls.__count += 1
            return super().__new__(cls)
        def __init__(self,name,age):
            self.name = name  # 实例属性
            self.age = age
    
    # p1 = Person('a',5)
    # p2 = Person('b',67)
    # p3 = Person('c',10)
    # print(p2.count)
    # print(p3.count)
    # print(p1.count)
    
  2. 【面试题】下面哪些打开文件的方式,可以自动创建一个新的文件

    a.open('f1.txt','w',encoding='utf-8')     b.open('f1.txt','wb',encoding='utf-8')
    c.open('f1.txt','w+',encoding='utf-8')    d.open('f1.txt','a',encoding='utf-8')
    e.open('f1.txt','r',encoding='utf-8')
    
  3. 【面试题】执行with上下文的时候,底层的工作原理

    # 1.with读
    # f表示打开的文件对象
    # with  open(r"致橡树.txt",'r',encoding="gbk") as f:
    #     r = f.read()
    #     print(r)
    
    # 2.with写
    # with open(r"f1.txt","a",encoding="utf-8") as f1:
    #     f1.write("ajgh")
    
    # 3.with上下文的工作原理
    """
    语法:
    with  对象  as  变量名:
        处理事务
    """
    class Person(object):
        # 进入
        def __enter__(self):
            print("进入with上下文管理~~~")
            return self
        # 退出
        def __exit__(self, exc_type, exc_val, exc_tb):
            # except异常
            print("退出with上下文管理~~~")
            return True
    
        def show(self):
            print("showing")
    
    with Person() as p1:
        print("处理事务~~~~")
        p1.show()
    
  4. 【面试题】列出常见的异常并说明出现异常的原因,至少5个

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值