Python笔试/面试题

文章目录

1. 为什么学习python

高级语言,不需要如何考虑如何管理你的程序使用的内存一类的底层细节等;
可移植性,由于python开源的特性,它已经被移植到许多平台上;
面向对象的,python不仅支持面向过程的编程,也支持面向对象的编程;
可扩展性,python编辑的程序可以直接调用用部分c或者c++开发的程序;
可嵌入性,可以把python嵌入c/c++程序,从而向程序用户提供脚本功能;
丰富的库:python庞大的标准库可以帮助我们处理各种工作,几乎无所不能;
规范的代码:python不需要编译成二进制代码的强制缩进方式,使得代码具有较好的可读性。
总结:语言本身简洁,功能强大,跨平台性强,从桌面应用到web开发,再到自动化运维、爬虫、人工智能、大数据都可以做。

2. python和java,php,C,C++,C#等语言的对比

C语言由于其底层操作特性和历史的积累,在嵌入式领域是当之无愧的。php跨平台,性能优越,和linux结合比和windows结合性能强45%。开发成本低,php5已经有了成熟的面向对象特性,适合开发大型项目。java是简单的、面向对象的语言。具有健壮、跨平台、高性能(自动垃圾回收机制)、多线程、动态和安全等特性。

3. 简述编译型语言和解释型的语言

编译性语言:编译型语言在执行前需要经过编译器的编译处理,将程序翻译成机器语言。因为在执行前编译型语言就已经被翻译成机器语言,所以在执行的时候会很快。例如C和C++是编译型语言。

解释型语言:解释型语言是在运行的时候将程序翻译成机器语言,所以运行速度相对于编译型语言要慢一些。例如:Python、Java、C#、JavaScript是解释型语言。

4. python解释器种类以及特点

CPython解释器:由C语言开发,所以叫CPython,在命令行的下面运行python,启动的就是CPython解释器,CPython是使用最广的python解释器。

Jython:运行在java平台上的python解释器,直接把python代码编译成java字节码执行。

IPython:IPython是基于CPython之上的一个交互式解释器,也就是说,IPython只是在交互上有所增强,但是执行代码的功能和CPython是完全一样的。

5. 位和字节的关系

位是计算机存储信息的最小单位,二进制中一个0或1是一位。计算机存储容量最的单位是字节,8个二进制位组成一个字节,一个标准的英文字母占用一个字节,一个标准的汉字占用两个字节。

6. b、B、KB、MB、GB关系
8b = 1B
1024B = 1KB
1024KB = 1MB
1024MB = 1GB
7. 请列举5个PE8规范
1. 4个空格的缩进,不使用Tab,更不能混合使用Tab和空格。
3. 类中的方法定义之间空一行
4. 在一段代码前增加的注释,在'#'后加一空格
5. 逗号,冒号前不加空格
6. 函数的左括号前不要加空格
7. 序列的左括号前不要加空格
8. 操作符左右各加一个空格
9. 函数默认参数使用的赋值符号左右省略空格
10.不要将多个语句写在同一行,允许使用分号
11. ifforwhile语句中即使执行语句只有一句,也必须另起一行
12. 类的方法第一个参数必须是self,而静态方法第一个参数必须是cls
8. 通过代码实现如下转换

1. 二进制转换成十进制:v = "0b1111011"

In [1]: v = '0b1111011'              
In [2]: ret = int(v,2)
In [3]: print(ret)                                                              
123

2. 八进制转换成十进制:v = "0o11"

In [5]: v = '0o11'                                                              
In [6]: ret = int(v,8)                                                          
In [7]: print(ret)  
9

3. 十六进制转换成十进制:v = "0x12"

In [9]: v = '0x12'
In [10]: ret = int(v,16)
In [11]: print(ret)                        
18

4. 十进制转换成二进制:v = 18

In [12]: v = 18                                                                 
In [13]: val = bin(18)                                                          
In [14]: print(val)                                                             
0b10010

5. 十进制转换成八进制:v = 30

In [15]: v = 30                                                                 
In [16]: val = oct(v)                                                           
In [17]: print(val)                                                             
0o36

6. 十进制转换成十六进制:v = 87

In [18]: v = 87                                                                 
In [19]: val = hex(v)                                                           
In [20]: print(val)                                                             
0x57
9. 请编写一个函数实现将ip地址转换成一个整数

首先需要将每个十进制数分别转换成二进制数再将这些二进制数拼接在一起,然后转换成十进制整数。我们可以在vim编辑器编写代码如下

def ip_zh(ip):
    ip_list = ip.split('.')
    # print(ip_list)
    sum = ''
    for item in ip_list:
        # print(type(int(item)))
        # print(bin(int(item)))
        # print(type(bin(int(item))))
        ret = bin(int(item))[2:]
        if len(ret) < 8:
            ret = (8 - len(ret)) * '0' + ret
        # print(ret)
        sum += ret
    return int(sum,2)

print(ip_zh('10.3.9.12'))
10. python递归的最大层数

python中默认递归限制的最大次数是1000层,查看默认最大层数:

In [21]: import sys 
In [22]: sys.getrecursionlimit
Out[22]: <function sys.getrecursionlimit>
In [23]: sys.getrecursionlimit()
Out[23]: 3000
11. 求结果
1、v = 1 or 3							# 如果1是真结果就是1,否则是3。所以,本题结果是1
2、v = 1 and 3						# 如果1是假,结果就是1,如果1是真,结果就是3。所以,本题结果是3
3、v = 0 and 2 and 1 			# 从前到后计算,先看前一个and,因为0是假,所以结果是0。后一个and,0是假,所以结果是0
4、v = 0 and 2 or 1			    # 因为0是假,所以前两个的结果是00是假但是1是真,所以结果是1
5、v = 0 and 2 or 1 or 4 	# 因为0是假,所以前两个结果是0。对于0  or 10是假,但是1是真,所以结果是1。对于1  or 41是真结果就是16、v = 0 or Flase and 1		# 因为0是假,所以结果是False。对于False and 1因为False是假,所以结果是False
12. 简述ASCII、Unicode、GBK、UTF-8编码的区别

ASCII:使用一个字节编码,所以它的范围基本是只有英文字母、数字和一些特殊符号 ,只有256个字符,使用8位二进制表示信息。

Unicode:使用32位表示信息,Unicode一般用于计算机内存中做计算。

GBK:只用来编码汉字的,GBK全称《汉字内码扩展规范》。使用双字节编码,一个中文占2个字节。

UTF-8:压缩Unicode,使用8位二进制表示信息,用尽量少的位数来表示信息,节省存储空间。UTF-8中一个中文占3个字节,UTF-8一般可用于网络传输和数据存储。

13. 字节码和机器码的区别

字节码是一种已经经过编译需要通过翻译后才能成为机器码的中间码,字节码通常不像源码一样可以让人阅读。字节码主要是为了实现特定软件的运行与软件环境和硬件环境无关的,字节码的实现方式是通过编译器和虚拟机。编译器将源码编译成字节码,特定平台上的虚拟机把字节码可以直接翻译成可执行的指令。字节码典型的应用是java语言。总而言之,字节码是一种中间状态的二进制代码(中间码),需要直接翻译才能成为机器码。

机器码是计算机可以直接执行并且执行速度最快的代码,由0和1组成的二进制代码序列。

14. 三元运算规则以及应用场景
15. python2和python3的区别

print。在python2中print被视为一条语句,而不是一个函数。如果在python2中输出一个字符串,不要加括号。但是,在python3中,print被视为函数。输出的字符串需要放到print函数中。【python3使用print必须以小括号包裹打印内容,python2 既可以使用带小括号的方式,也可以使用一个空格来分隔打印内容。】

python2中range函数返回列表,而python3返回迭代器,节约内存。

python2中使用ASCII编码,python3中使用UTF-8编码。

python2中Unicode表示字符串,str表示字节。而python3中str表示字符串,byte表示字节。【python2 中的 unicode 类型是 python3 中的 str 类型,python2中的str类型是 python3 中的bytes类型。所以对于网络传输,python2使用str类型,python3使用bytes类型。】

python2中为正常显示中文,引入coding声明,python3中可以不用声明。

python2中的raw_input()函数是python3中input()函数

对包的定义,python2中必须要有_ _ init _ _.py文件;python3中不是必须使用这个文件

对于map和filter:python2中返回列表,python3中返回迭代器

``

16. python2和python3中int和long的区别

python2中有int和long类型,但是python3已经废弃了long类型,统一使用int类型。

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

a , b = b , a

18. range和xrang函数的区别

range和xrange都在循化中使用,输出的结果一样

range返回的是list对象,而xrange返回的是一个生成器对象(xrange object)

xrange不会直接生成一个list,而是每次调用返回其中的一个值,内存空间使用极少,因而性能高

python3中已经去掉了xrange函数,全部用range代替。

19. 文件操作时:xreadlines和readlines的区别

二者使用相同,但返回值类型不同,xreadlines返回的是一个生成器,readlines返回的是list

20. 列举布尔值为False的常见值

0,None,空(空字符串、空列表、空字典、空元组)

21. 列举字符串列表元组和字典常用的5个方法
22. lambda表达式的格式以及应用场景
23. pass的作用

pass可作空语句,表示什么也不做;也可以保证格式的完整,保证语义的完整。

# 可做空语句,表示什么也不做
if true:
    pass
else:
    pass
# 保证格式的完整
def foo():
    pass
# 保证语义的完整
while True:
    pass
24. *args和**kwargs的作用

args不支持关键字传参,只支持位置传参,可以接收任意个数的位置参数,并将参数转换成元组

kwargs可以接收任意数量的关键字参数,并将参数转换为字典。

25. is和==的区别

==用于比较值是否相等,is用于比较内存地址是否相等。

26. 可变类型与不可变类型

可变类型内部不能被修改的,只能重新赋值,如 int、str、bool、tuple
不可变类型的内部可以被修改的,如list、set、dict

27. 至少列举8个常用模块

django、flask、pip、pygame、pymysql、numpy、pandas、hashlib、json、datetime、time、os、sys、logging等等……

28. 列举常见的内置函数

29. 装饰器的写法以及应用场景

装饰器的写法:

def x(func):
	def inner(*args,**kwargs):
		data = func(*args,**kwargs)
		return data
	return inner

应用场景:在flask框架和django框架中都有应用,如路由、权限等

30. 如何安装第三方模块

python中,安装第三方模块,是通过setuptools这个工具完成的。python有两个封装了setuptools的包管理工具:easy_install和pip,目前官方推荐使用pip。

31. 你使用哪些第三方模块

jinjia2、requests、、、、

32. 如何实现"1,2,3"与[1,2,3]互相转换

对于字符串"1,2,3"转换成[1,2,3],可以使用split(',')方法以逗号分割将字符串分割成列表[1,2,3],然后把每个list的元素转换成int类型。

对于[1,2,3]转换成"1,2,3"可以先见列表中每个元素转换成字符串,然后使用列表的join方法以逗号的方式将元素连接成字符串。

33. 求结果
1 or 2						# 1
1 and 2					# 2
1 < (2==2)			# 比较大小的时候要转换成bool类型,2==2是真为True,1< True等价于True < True,所以为False
1 < 2 = 2 				# 1 < 2 为真得True,True = 2等价于True = True,所以为True
34. 如何用一行代码生成[1,4,9,16,25,36,49,64,81,100]

[i**2 for i in range(1,11)],考察的是列表生成式。

35. 一行代码实现删除列表中重复的值

list(set([1,2,1,2]))

36. 比较[1,2,3] 和[(1),(2),(3) ]以及[(1,),(2,),(3,) ] 的之间的区别

[1,2,3] 列表和 [(1),(2),(3)] 列表是等价的,元素都是整型。[(1,),(2,),(3,)] 列表中的元素都是元组类型。

37. 定义数的这种写法def func(a,b=[])有什么特点

将可变对象作为默认参数,若多次调用时使用默认参数,默认参数会保留上次调用时的状态。可以在函数体中判断如果b不是空列表就让为空列表,即:if b:b=[]

38. 计算结果
[ i % 2 for i in range(10) ]			# 是一个列表:[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
( i % 2 for i in range(10) )			# 是一个元组,所以结果是一个生成器对象
39. 如何在函数中设置一个全局变量

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

40. 什么是正则的贪婪匹配

贪婪匹配是尝试匹配尽可能多的字符,非贪婪匹配是尝试匹配尽可能少的字符。

import re

code = 'thanlonkikuthanlon'
ret1 = re.findall('a.*lon', code)  # 贪婪匹配
print(ret1)  # ['anlonkikuthanlonlon']
ret2 = re.findall('a.*?lon', code)  # 非贪婪匹配
print(ret2)  # ['anlon', 'anlon']
41. logging模块的作用以及应用场景

loggin模块的作用:可以更好的管理我们的日志,并且可以将标准输入输出保存到日志文件,而且利用logging模块可以部分代替debug的功能,给程序排错。

应用场景:设置登录日志,将系统错误信息写入日志等等。

42. re的match和search区别

match函数在字符串第一个位置(0索引)匹配成功才会返回,不是第一个位置匹配成功则返回None:

In [1]: import re                                                               

In [2]: re.match('thanlon','thanlonlovekiku')                                   
Out[2]: <re.Match object; span=(0, 7), match='thanlon'>

search函数会扫描整个字符串返回第一个成功匹配:

In [3]: re.search('thanlon','kikulovethanlon')                                  
Out[3]: <re.Match object; span=(8, 15), match='thanlon'>
43. 请用代码简单实现stack
'''
基于列表实现栈
'''
class Stack(object):
    def __init__(self):
        self.data = []

    def push(self, val):
        self.data.append(val)

    def pop(self):
        return self.data.pop()

    def top(self):
        return self.data[-1]

stack = Stack()
stack.push('Thanlon')
stack.push('Kiku')
print(stack.data)
print(stack.pop())
print(stack.pop())
'''
['Thanlon', 'Kiku']
Kiku
Thanlon
'''
44. python的垃圾回收机制

引用计数可以用于跟踪和回收垃圾。标记清除,解决容器对象可能产生的循环引用问题。分代回收,以空间换取时间进一步提高垃圾回收的效率。

45. python的可变类型和不可变类型

可变类型:可变类型有list、dict,可变类型的内部是可以被修改的。不可变类型只要值相同就不会指向同一地址。

不可变类型:不可变类型有int、string和tuple,不可变类型的内部是不可以被修改的。可变类型只要值相同就指向同一个内存地址(除非进行复制操作,那么他们将会指向同一个地址)。

46. == 和 is 的区别

==用于比较值是否相等
is用于比较内存地址是否相等

47. filter、map、reduce的作用

filter是对序列中的元素进行筛选,最终获取符合条件的序列。

map是用同样方法把所有数据都改成别的。

reduce是用某种方法依次把所有数据丢进去最后得到一个结果。

48. os和sys模块的作用

os模块可以获取与操作系统相关的数据,是一个用于访问操作系统功能的模块;sys模块中包含pthon解释器相关的数据,用于提供对python解释器相关的操作。

49. 如何生成一个随机数

使用random函数可以生成一个随机数,如:

随机整数:random.randint(a,b),得到值x在a<=x<=b

返回一个范围在start和stop之间且步长为step的随机整数,不包括结束值:random.randrange(start,stop,step)

返回0到1之间的浮点数:random.random( )

返回指定范围内的浮点数:random.uniform(a,b)

50. 如何使用python删除一个文件

可以使用python内置模块 shutil 中的 rmtree 方法,也可以使用os.remove(path)来删除文件。

51. 如何判断是函数还是方法

一般我们认为在类中是方法,写在外面的是函数。其实,这样判断是函数还是方法是不精准的。方法和函数的区分,不仅和定义的位置有关系,还和方法或函数的调用者有关系。如果通过“对象.xxx”调用,那么xxx就是方法。如果通过“类.xxx”调用或者直接执行xxx,那么xxx就是个函数。

52. 列举面向对象中带下划线的特殊方法

__init__、__new__、__call__、__enter__、__exit__、__getitem__、__ setitem__、__ delitem__、 __ add __

53. __new__与__init__的区别

__new__是一个静态方法,__init__是一个实例方法。__new__方法会返回一个创建的实例,而__init__什么都不返回。只有在__new__返回一个类的实例时,后面的__init__才能被调用。当创建一个新实例时调用__new__,初始化一个实例时用__init__。

53. 是否使用过functools中的函数,它的作用是

functools模块用于高阶函数,是作用于函数或者返回其他函数的函数。使用过functools模块中的reduce函数,用某种方法依次把所有数据丢进去最后得到一个结果。

functools的作用是提供一种用于对函数固定属性的函数。

54. 面向对象中super的作用

super不是指父类(基类),而是按照类的继承顺序指下一个类。可以写一个帮助理解的程序:

# coding:utf-8
class Base(object):
    def f1(self):
        print('Base.f1()')
        pass

class Foo1(object):
    def f1(self):
        super().f1()

class Foo2(object):
    def f1(self):
        print('Foo2.f1()')

class Info(Foo1, Foo2):
    pass

obj = Info()
obj.f1()
'''
先找Info类中有无f1方法,确认Info类中没有f1方法
下面按照类的继承顺序,找下一个类Foo1
Foo1中找到f1方法,Foo1中的f1方法执行super().f1()
super().f1()即:按照Info类的继承顺序找下一个类(注意:并不是去Foo1的基类object中找f1),看有无f1方法
下一个类是Foo2,在Foo2中找到了f1方法,所以执行Foo2类中的f1方法
'''
55. 静态方法和类方法区别

静态方法:如果方法无需使用对象中封装的值,那么就可以使用静态方法。写静态方法时,方法上方需要写@staticmethod,方法中参数可有可无,参数中不可以用self会出错,解释器执行时也不会将self自动传入参数列表。

类方法:如果在方法中会使用到当前类,那么就可以使用类方法。定义类方法时,方法上方写@classmethod,方法中至少有一个参数cls。定义类方法时,方法上方写@classmethod,方法中至少有一个参数cls。

56. isinstance作用以及应用场景

判断对象是否是某一个指定类或其及父类的实例。

57. 如何解决json序列化时默认遇到中文会转换成unicode

可以设置 json 模块的 dumps 函数里的参数 ensure_ascii=False,默认 ensure_ascii = True。json.dumps(v, ensure_ascii=False)

58. json序列化时可以处理的数据类型有哪些

int、bool、str、list、dict、tuple、None(除了集合)

59. json序列化时如何定制支持datetime类型

将datetime类型通过字符串的 strftime 方法转换成字符串类型,然后序列化字符串。

60. 提高python运行效率的方法

1、使用生成器,因为可以节约大量内存
2、循环代码优化,避免过多重复代码的执行
3、核心模块用Cython、PyPy等,提高效率
4、使用多进程、多线程、协程
5、多个if elif条件判断,可以把最有可能先发生的条件放到前面写,这样可以减少程序判断的次数,提高效率。

61. 简述yield和yield from

yield:生成器每次循环都会获取yield返回的值。
yield from:从当前生成器跳到另一个生成器。

62. 使用代码列举目录下的所有文件

需要使用到os模块,

import os
res = os.walk(r'E:\pycharmProjects\practice')
for a, b, c in res:
    '''
    a:正在查看的目录
    b:此目录下的文件夹
    c:此目录下的文件
    '''
    # print(a)
    # print(b)
    # print(c)
    '''
    E:\pycharmProjects\practice
    ['.idea', 'test']
    ['test.py']
    E:\pycharmProjects\practice\.idea
    []
    ['misc.xml', 'modules.xml', 'practice.iml', 'workspace.xml']
    E:\pycharmProjects\practice\test
    []
    ['index.html', 'log.txt']
    '''
    for item in c:
        path = os.path.join(a, item)
        print(path)
    '''
    E:\pycharmProjects\practice\test.py
    E:\pycharmProjects\practice\.idea\misc.xml
    E:\pycharmProjects\practice\.idea\modules.xml
    E:\pycharmProjects\practice\.idea\practice.iml
    E:\pycharmProjects\practice\.idea\workspace.xml
    E:\pycharmProjects\practice\test\index.html
    E:\pycharmProjects\practice\test\log.txt
    '''
63. 字符串、列表、元组、字典常用的5个方法

字符串:len、join、split、strip、upper、lower、replace、isdigit、startwith、endwith、format
列表:len、append、insert、pop、remove、clear、expend、reverse、sort
元组:len
字典:keys、values、items、get、pop、update

63. 常用字符串格式化哪几种

第一种:print('%s,%s'%('thanlon','kiku')),最方便的,需要一个个格式化。
第二种:print('{},{}'.format('thanlon','kiku'))、print('{first},{second}.format(first='thanlon',second='kiku')'),最先进的,可读性强
第三种:print('%(first)s,%(second)s'%{'first':'thanlon','second':'kiku'}),最好用的,不需要一个个格式化,可以用字典的方式,缩短时间。

64. 简述 生成器、迭代器、可迭代对象以及应用场景

迭代器:访问集合元素的一种方式,从集合的第一个元素开始访问,直到所有元素被访问结束。其优点是不需要事先准备好整个迭代过程中的所有元素,仅在迭代到某个元素时才开始计算该元素。适合遍历比较巨大的集合。__iter__方法返回迭代器本身, __next__方法用于返回容器中下一个元素或数据。

生成器:带有yield的函数不再是一个普通函数,而是一个生成器。当函数被调用时,返回一个生成器对象。不像一般函数在生成值后退出,生成器函数在生成值后会自动挂起并暂停他们的执行状态。【生成器用来一点一点产生数据的。生成器只有被for循环时,生成器函数内部的代码才会被执行,生成器每次循环都会获取yield返回的值。】

可迭代对象:可以被for循环且对象中具有__iter__方法,还要返回一个迭代器(或生成器)

65. 什么是反射以及反射的应用场景

反射:实质上是利用字符串的形式去对象(模块)中操作(查找/删除/添加)成员,是一种字符串的时间驱动。【反射主要是指程序可以访问、检测和修改它本身状态或行为的一种能力(自省)。python面向对象中的反射就是通过字符串获取模块、对象或类的属性,进行操作。】

应用场景:需要执行对象中的某个方法或者调用对象中的某个变量,但是种种原因无法确定方法或变量是否存在。

66. 1,2,3,4,5 能组成多少个互不相同且无重复的三位数
num = 0
for i in range(1, 6):
    for j in range(1, 6):
        for k in range(1, 6):
            if i != j and i != k and j != k:
                num += 1
print(num)  # 60
67. 求结果

v = dict.fromkeys(['k1','k2'],[])
v['k1'].append(666)
print(v)
v['k1'] = 777
print(v)

v = dict.fromkeys(['k1', 'k2'], [])  # {'k1': [], 'k2': []}
v['k1'].append(666)
print(v)  # {'k1': [666], 'k2': [666]}
v['k1'] = 777
print(v)  # {'k1': 777, 'k2': [666]}
68. 三元运算规则以及应用场景

三元运算规则:对于v = value1 if 条件 else value2,如果条件成立,v = value1,否则 v = value2。

三元运算应用场景:简单的 if else 结构

69. lambda表达式格式以及应用场景

lambda表达式格式:函数名 = lambda 参数:函数返回

lambda表达式的应用场景:lambda可以用来定义一个匿名函数,可以用来解决简单的函数

70. python面向对象中的继承有什么特点和优点

优点:1. 建造系统中的类,避免重复操作。2. 新类经常是基于已经存在的类,这样就可以提升代码的复用程度。
特点:1. 在继承中基类的构造方法(__init__)不会被自动调用,它需要在其派生类的构造中方法中专门调用;2. 在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。3. python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。

71. 谈谈你对面向对象的理解

面向对象中有封装、继承、多态、

所谓的面向对象的封装就是将我们的程序模块化,对象化,把具体事物的特性属性和通过这些属性来实现一些动作的具体方法放到一个类里面,这就是封装。封装是我们所说的面相对象编程的特征之一。【面向对象中的最重要的是封装,可以将实现归类和打包。归类:将相似功能的函数放到一个类中;打包:可以将数据打包放到对象中。】

继承是实现代码的复用,一个类可以继承另外一个类,被继承的类称为父类,继承的称为字类。面向对象里的继承也就是父类的相关的属性,可以被子类重复使用,子类不必再在自己的类里面重新定义一回。需要用到的新的属性和方法时,子类也可以自己来扩展。增加了类的耦合性,使得代码更加规范化、合理化。

多态:在子类里面把父类里面定义的方法在子类里面重新实现一遍,多态包含了重载和重写。 重载就是类里面相同方法名,不同形参的情况,可以是形参类型不同或者形参个数不同,或者形参顺序不同,但是不能使返回值类型不同。重写很简单就是把子类从父亲类里继承下来的方法重新写一遍,覆盖父类的方法。

72. 谈谈你对闭包的理解

闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用,这样就构成了一个闭包。闭包为函数创建一块区域为其维护自己的数据,以后执行时方便调用。闭包的应用场景之一就是装饰器。下面是闭包的例子:

def outer():			# 外部函数 
	b = 10
	def inner():     # 内部函数
		print(a+b)	# 调用外部函数的形式参数
	return inner 	#  返回内部函数

一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。

73. 列举面向对象中的特殊成员以及应用场景

__init__:类名(),自动执行__init__方法

__call__:对象(),自动执行__call__方法

__getitem__:对象[],自动执行__getitem__方法

__setitem__:对象['xxx']=xx,自动执行__setitem__方法

__delitem__:del 对象,自动执行__delitem__方法

__add__:对象+对象,自动执行__add__方法

__enter__与__exit__:with 对象,自动执行__enter__和__exit__方法

__new__:类(),其实是先执行__new__方法,再执行__init__方法

发布了54 篇原创文章 · 获赞 138 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/Thanlon/article/details/102563738