ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python面试题汇总

2021-04-13 20:59:05  阅读:152  来源: 互联网

标签:__ 面试题 Python 函数 python 汇总 列表 对象 print


title: python面试题
date: 2021-04-07 20:12:03
tags:
top: 6

持续更新中…

  1. python的特点

     python是一种解释性语言
    
     python是交互式语言
    
     python是面向对象的语言
    
     python易于学习,易于阅读
    
     python可跨平台运行
    

2.Python优缺点

优点:

	易于学习、易于维护、易于阅读

	一个广泛的标准库

	支持交互,在终端敲命令的形式得到运行的结果

	可移植性

	可扩展性【可以调用C或C++写的代码】

	数据库【python提供所有商业数据接口】

	GUI编程(图形化界面)

	可嵌入式

缺点:

	运行速度相比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则支持更多的特性和数据类型】

4.交换两个变量的值

a.设置新变量当中转空间

a = 10
b = 20
temp = 0
temp = a
a = b
b = temp

b.加减法

a = 10
b = 20
a = a + b  # a = 10 + 20
b = a - b  # b = 30 - 20
a = a - b  # a = 30 - 10

c.python专有的交换方式

a = 10
b = 20
a, b = b, a

d.异或,计算机二进制运算按位异或

一个数异或一个数两次,这个数不变

a = 10
b = 20
a = a ^ b        # a = a ^ b
b = a ^ b ^ b    # b = a
a = a ^ b        # a = a(a ^ b) ^ a

5.Python中的内存管理机制

定义变量的机制:定义一个变量相当于在计算机内存中开辟了一块空间,用于存储指定的数据。

变量的本质:变量实际上存储的是数据的地址。

计算机的内存:

	栈:引用【变量名】

	堆:实际的数据【对象】

6.进制问题

print(int("0b1102", base=16))

分析:进制问题,注意2进制只能由1和0组成,8进制的范围是07,16进制的范围是09 + a~f

虽然是0b开头,但是中间出现了2,那么这个数是能是16进制。

7.python2.x和python3.x的版本的区别

print 函数

	Python3.x当中打印方式为print()函数

print("HelloWorld")

	Python2.x当中打印方式为prin语句

print "HelloWorld"

	Python2.6和Python2.7为二者的过渡版本,上面两种方法都支持。

Unicode 编码表

Python 2.x 有 ASCII str() 类型,unicode() 是单独的,不是 byte 类型。

Python3.x有了Unicode(utf-8)字符串,以及一个字节类:byte和bytearrays。

中国 = 123

Python3.x支持上面这个写法,Python2.x不支持

除法

” / “

Python2.x当中,整型数字之间相除,产生的结果会舍去小数部分,结果也为整型。

Python3.x当中,整型数字之间相除,产生的是一个浮点数。

” // “整除

Python2.x和Python3.x运算规则一样。

异常

捕获异常的语法由 except exc, var 改为 except exc as var

使用语法except (exc1, exc2) as var可以同时捕获多种类别的异常

在2.x时代,所有类型的对象都是可以被直接抛出的,在3.x时代,只有继承自BaseException的对象才可以被抛出。

2.x raise语句使用逗号将抛出对象类型和参数分开,3.x取消了这种奇葩的写法,直接调用构造函数抛出对象即可。

在2.x时代,异常在代码中除了表示程序错误,还经常做一些普通控制结构应该做的事情,在3.x中可以看出,设计者让异常变的更加专一,只有在错误发生的情况才能去用异常捕获语句来处理。

xrange

在 Python 2 中 xrange() 创建迭代对象的用法是非常流行的。比如: for 循环或者是列表/集合/字典推导式。

这个表现十分像生成器(比如。“惰性求值”)。但是这个 xrange-iterable 是无穷的,意味着你可以无限遍历。

由于它的惰性求值,如果你不得仅仅不遍历它一次,xrange() 函数 比 range() 更快(比如 for 循环)。尽管如此,对比迭代一次,不建议你重复迭代多次,因为生成器每次都从头开始。

在 Python 3 中,range() 是像 xrange() 那样实现以至于一个专门的 xrange() 函数都不再存在(在 Python 3 中 xrange() 会抛出命名异常)。

八进制字面量表示

八进制数必须写成0o777,原来的形式0777不能用了;二进制必须写成0b111。

新增了一个bin()函数用于将一个整数转换成二进制字串。 Python 2.6已经支持这两种语法。

在Python 3.x中,表示八进制字面量的方式只有一种,就是0o1000。

不等运算符

Python 2.x中不等于有两种写法 != 和 <>

Python 3.x中去掉了<>, 只有!=一种写法

去掉repr表达式"

Python 2.x 中反引号``相当于repr函数的作用

Python 3.x 中去掉了``这种写法,只允许使用repr函数

数据类型

Python3.x中去掉了Python2.x当中的long数据类型,新增了bytes类型

str 对象和 bytes 对象可以使用 .encode() (str -> bytes) 或 .decode() (bytes -> str)方法相互转化

8.简述if语句中的单分支、双分支和多分支的区别

单分支:

判断条件是否成立,成立执行if所属下面的语句,不成立不执行。

双分支:

if—else语句:条件成立执行if所属下面的语句,不成立执行else所属下面的语句。

多分枝:

if-elif…else语句,实现多选一,从上往下依次判断,只要有一个条件成立,那只执行对应的分支语句,执行完毕,整个if语句结束,所有条件不成立,执行else当中的语句。

9.break和continue的区别

break:

	作用:跳出整个循环体【结束循环,执行循环后面的语句】

	注意:break讲究就近原则,跳出距离最近的循环

continue:

	作用:跳过当前正在执行的循环,然后进行下一轮循环【结束本次循环,执行下一次循环】

10.is 和 == 的区别

is 是比较两个变量的【对象】的地址

== 是比较两个变量【对象】的内容

如果两个变量的地址相同,则这两个变量的内容一定相同

如果两个变量的内容相同,则这两个变量的地址不一定相同

11.短路原则

1.A and B,如果A为False,不需要计算B的值,整个表达式结果为False

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

3.and 和 or 混合使用

a.表达式从左往右运算,如果or的左侧为True,则会短路or后所有的表达式【不管后面连接了and还是or】

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

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

注意:被短路的表达式都不会执行

12.身份运算符

身份运算符用于比较两个对象的存储单元【地址】

is:判断两个标识符是不是引用自一个对象

is not:判断两个标识符是不是引用自不同对象

13.什么是列表切片?请举例说明

通过指定的区间和指定的步长,获取指定列表中的指定元素,生成一个新的列表。

切片之后的结果要么非空,要么为空,不会报错

list1 = [1, 2, 3, 4, 5]
list2 = list1[1:3:]
list2 = [2, 3]

print(list1[100:])  # []
print(list1[0:-1])  # 等价于[0:4]  [1,2,3,4]
print(list1[5:100]) # []
print(list1[::1])   # 顺序
print(list1[::-1])  # 倒叙
print(list1[-1:0])) # 相当于list1[-1:-5:1]   []
print(list1[-1:0:-1]) # 相当于list1[-1:-5:-1]  [5,4,3,2]

14.列表操作中,append和extend的区别和联系

相同点:

	1.都是向列表添加元素,并且都是添加在末尾。

	2.二者一次只能传递一个数据

	3.二者都是在原列表的基础上添加元素的,所以返回值都为None

不同点:

	1.append可以向列表添加任何类型的元素,extend只能向列表添加可迭代对象。

	2.append添加序列的时候会把整个序列当作一个元素添加到列表里面,extend会把序列里面的元素一个个依次添加到列表类面。

15.代码阅读

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

# 最开始c = [[1, 2, 3], [4,5]]  d = [[1, 2, 3], [4,5]]
# e =  = [[1, 2, 3], [4,5]]
# d属于直接引用
# e属于浅拷贝
# a.append(20) ————》 a = [1, 2, 3, 20] 在a的末尾添加元素20
# 由于都不是深拷贝,所以内层元素发生改变,其他列表也会随着发生改变
c = [[1, 2, 3, 20], [4,5]]
d = [[1, 2, 3, 20], [4,5]]
e = [[1, 2, 3, 20], [4,5]]

16.代码阅读

a = [1, 2, ['a', 'b']]
b = a 
c = copy.deepcopy(a)
a[-1].append(3)
print(b)
print(c)

解析:

# b是直接引用a
# c是深拷贝a
# 所以,a内部元素变化会对b 造成影响,但不会对c造成影响
b = [1, 2, ['a', 'b', 3]]
c = [1, 2, ['a', 'b']]

17.代码阅读

a = [1, 2, ['a', 'b']]
b = a
c = copy.deepcopy(a)
a.append(3)
print(b)
print(c)

解析:

"""
c是深拷贝a
b是直接引用
a.append(3)改变了a 的外层元素,
对深拷贝没有影响,但对于直接引用有直接的影响
"""
b = [1, 2, ['a', 'b',], 3]
c = [1, 2, ['a', 'b']]

18.引用赋值、浅拷贝、深拷贝

引用赋值:不管是几维列表,一个列表的元素改变,另一个随着改变

列表.copy()和copy.copy():

	对于一维列表,一个列表的元素改变,另一个不会改变

	对于二维列表,一个列表的元素改变另一个会随着改变

对copy.deepcopy():不管是几维列表,一个列表的元素改变,另一个都不会改变。

19.可变数据类型和不可变数据类型的区别

不可变数据类型:int, float, bool, str, tuple,通过变量赋值的方式操作,一个变量的值发生改变,另一个变量不受影响。

可变数据类型:list, dict, set,通过变量赋值的操作,一个变量内部的元素改变,另一个变量会随着改变。

20.元组和列表的区别和联系

相同点:

	1.二者都是有序的

	2.二者都可以存储不同类型的元素

	3.二者都可以存储重复元素

	4.二者的遍历方式完全相同

不同点:

	1.表示方式:元组::(),列表:[]

	2.可变性:元组是不可变,列表是可变的

	3.使用场景:在多线程的使用场景中,为了避免多线程访问同一个数据造成的混乱,则可以使用元组。如果涉及到元素的增加或者删除,则可以使用列表。

	4.元组在创建时间和占用空间都优于列表。

21.创建字典的五种方式

方式一:创建并传入键值对

dict1 = {"aa": 10, "bb": 20}
print(dict1)

方式二:先创建,再传入键值对

dict2 = {}
dict2["aa"] = 10
dict2["bb"] = 20
print(diict2)

方式三:dict3 = dict(key = value, …)

dict3 = dict(name = "xiaokeai", age = 10)
print(dict3)

方式四:dict([(key1,value1), (key2, value2)])

dict4 = ([("a",11), ("b",22),("c",33)])
print(dict4)

方式五:dict(zip[所有的key], [所有的value])

dict5 = {zip[11,22,33],["a","b","c"]}
print(dict5)

22.字典的update()方法

update():更新,合并字典,将指定字典中的键值对添加到原字典中

23.区分字典zip方法和dict.fromkeys创建字典的区别

 dict1 = dict(zip([11,22],["a","b"]))
 print(dict1) # {11:"a", 22:"b"}

 dict2 = dict.fromkeys([11,22],["a", "b"])
 print(dict2) # {11:["a", "b"], 22:["a", "b"]}

24.add 和uptate之间的区别和联系

相同点:

	1.都是向集合中添加元素

	2.都只能识别一个元素

不同点:

	1.add只能添加不可变的数据类型

	2.update只能添加可迭代对象【list,str,tuple,dict】

	3.如果添加的数据为元组,add会将整个元组当作元素添加到集合当中,update只会将元组里面的元素添加到集合当中。

25.集合间的运算

1.交集 &

set1 = {1,2,3} set2 = {3,4,5} # 算术运算符 set3 = ste1 & set2 # 系统功能 set4 = set1.intersection(set2)

2.并集 |

set1 = {1,2,3} set2 = {3,4,5} # 算术运算符 set3 = ste1 | set2 # 系统功能 set4 = set1.union(set2)

3.差集 -

set1 = {1,2,3} set2 = {3,4,5} # 算术运算符 set3 = ste1 - set2 # 系统功能 set4 = set1.differance(set2)

4.差集的并集/并集 - 交集

set1 = {1,2,3} set2 = {3,4,5} # 算术运算符 set3 = ste1 ^ set2

26.阅读下面代码,输出结果

def test(num1,num2,*num3,num4):
    print(num1,num2,num3,num4)

test(6,4,5,65,566,88,89,88)

分析:结果会报错,不定长参数出现在形参列表的中间,在传递实参的时候,在可变长参数后面的参数不是关键字参数,会导致可变长参数接收num2以后的所有数据,结果导致num4接收不到参数而报错。

注意:在形参列表中,不定长参数最好出现在形参列表的最后,如果出现在形参列表的中间位置,则可以在实参列表中借助于关键字参数解除歧义。

27.简述值传递和引用传递的作用

值传递:实参是不可变数据类型

引用传递:实参是可变的数据类型

28.阅读下面的代码,写出执行结果

def func():
    a = []
    for i in range(5):
        a.append(lambda x:i * x)
        
    return a
result = func()
print(result[0](2))
print(result[1](2))
print(result[2](2))
print(result[3](2))
print(result[4](2))

分析:result = func()调用函数func()产生了五个匿名函数,并且存放到列表a当中,后面的五句代码是在调用存在列表a当中的五个匿名函数,由于第一次调用func()的时候i已经变成了4,所以五个函数中的i都是4,则结果为:8, 8, 8, 8, 8

29.什么是匿名函数,优缺点

是一个lambda表达式,本质上还是一个函数,可以设置参数,也可以进行调用,表达式本身就是函数运算的结果

优点:简化代码、减少内存空间的使用

缺点:只能实现简单的逻辑,逻辑一旦复杂,代码的可读性会降低,则不建议使用

30.全局变量的使用场景

问题:当全局变量和局部变量重名,在函数内部对变量直接进行运算,因为系统不能识别是对那个变量进行运算,所以报错

解决:使用global对变量进行声明,表示参与运算的变量来自全局

a = 28
def func():
    global a
    a += 1
func()
print(a)

31.简述可迭代对象和迭代器之间的区别和联系

区别:

	可迭代对象:Interable,可以直接作用于for循环,如:list,tuple,tr,dict,set,生成器等

	迭代器:Iterator,可以直接作用于for循环和next的数据,如:生成器

联系:

	迭代器一定是可迭代对象,可迭代对象不一定是迭代器但是,可以通过iter()将不是迭代器的可迭代对象转换位迭代器

32.代码阅读题

def func(li[]):
    li.append("abc")
    return li
print(func())  
# 调用func()函数,会往默认列表li里面添加"abc"  结果为["abc"]

print(func([3])) 
# func([3]),表示传入新的列表,列表里面已经有元素3, 所以结果为[3, "abc"]

print(func()) 
# 再次调用func()函数,会在之前调用之后li列表的基础上,
# 再次添加"abc"  结果为:["abc", "abc"]

print(func([3])) 
# 传入新的列表,注意:虽然里面元素跟前面一样,但这是两个不同的列表。
# 所以结果为[3,"abc"]

33.需求:书写一个装饰器,可以统计任意一个函数的执行时间

import time
def get_time(func):
    inner(*args,**kwargs):
        # 开始时间
        start_time = time.time()
        func(*args,**kwargs)
        # 结束时间
        end_time = time.time()
        return round(end_time - start_time, 3)
    # 返回内部函数的引用
    return inner
@get_time
def test():
    for _ in range(10**8):
        pass
    return 100

34.斐波那契数列(递归)

def func(n):
    if n == 1 or n == 2:
        return 1 
    else:
        return func(n-1) + func(n-2)

35.简述变量的作用域有哪些,全局变量和局部变量有什么区别

变量作用域分类:

	全局作用域:Global

	函数作用域:Enclosing

	局部作用域:ocal

	内置作用域:Built-in

全局变量:定义在函数的外部的变量,可以在整个程序中被访问

局部变量:定义在函数内部的变量,仅限于在该函数的内部被访问

36.简述类属性和实例属性的区别和联系/简述类的字段和对象的字段的区别和联系

1.定义的位置不同:类属性直接定义在类中,实例属性:动态绑定或者定义在构造函数中

2.访问方式不同:类属性可以通过对象或者类名访问,实例属性只能通过对象访问

3.在内存中出现的实际不同:类属性随着类的加载而出现,实例属性随着对象的创建而出现

4.优先级不同:当类属性和实例属性重名的时候,使用对象优先访问实例属性

5.使用场景不同:如果是多个对象共享的数据则定义位类属性,如果是对象特有的数据,则定义位实例属性。

37.new和init的工作原理

1.当代码执行变量 = 类名() 语法是,可以创建一个对象出来,主要是因为先调用了new,然后调用了init

2.创建对象的时候会自动调用new,该函数的返回值就是被当前创建的对象【实例】

3.当对象创建完毕之后,会自动调用init,在该函数内部给对象赋初始值

4.不管是new还是init是否显式的书写在类中,永远都是先调用new,然后再调用init

5.首先将指定类传参给new,创建一个对象并返回,然后将该对象传参给init,则可以给对象设置初始值

38.构造函数init和普通函数的区别

不同点:

1.函数名不同:实力函数的函数名可以自定义,init的函数名是固定的

2.调用不同:init是在创建对象的过程中被自动调用的,而实例函数必须手动调用

3.调用次数:对于同一个对象而言,init一般只会被调用一次,而实例函数可以根据需求调用多次

相同点:

1.二者都定义在类中,形参列表的第一个参数都是self,二者都可以被称为实例函数。

2.形参列表可以设置为默认参数,不定长参数,实参列表也可以使用关键字参数

3.二者都可以根据需求设置返回值

39.面向对象的特征是什么,怎么使用,有什么作用?

封装:

a.将不希望被外界直接访问的属性进行私有化,在定义属性的时候在属性名前家两个下划线

作用:为了提高数据的安全性,为了提高数据的复用性

b.封装式定义类的准则【根据各个对象的特点,将相同的属性和行为提取出来一个新的类,还可以进行属性私有化】

继承:

a.将多个相似类中的属性和函数提取出来,形成一个父类,子类将会继承父类中未被私有化的属性和函数

作用:简化代码,提高了代码的复用性,提高了代码的可扩展性

b.继承是设计类的技巧【父类和子类,为了代码的复用性】

多态:

a.在继承的前提下,当代码运行的时候,根据传入的对象确定该对象是什么类型,可以调用哪个函数

作用:增加代码的灵活性

b.多态式调用函数的技巧【不同的子类可以调用不同的函数,产生不同的结果】

40.代码阅读题

@property装饰器装饰类函数,表示将函数转换为属性使用

阅读下面代码,写出执行结果

class Person(boject):
    @property
    def show(self):
        print("show")
p = Person()
print(p.show)

分析:p.show表示对象p调用函数show,控制台会打印show,然后print(p.show)表示打印show函数的返回值,而show函数返回值为None所以打印结果为:

show

None

41.解释下面不同书写形式的属性的含义

a:普通属性/公开属性,在类的内外可以直接访问

_a:一般称为保护属性,在类的内外都可以直接访问,但是,一般不建议使用

__a:私有属性,只能在类的内部被访问,在类的外面一般借助于暴露的函数

a:自定义的变量不建议使用 ,一般体现为系统属性或者系统函数的用法,如:init、new、str、repr

42.继承的特点和优点

继承的特点:

1.子类对象可以直接访问父类中为被私有化的属性

2.子类对象可以直接调用父类中为被私有化的函数

3.父类对象不能访问子类中特有的属性和函数

继承的优点:

1.可以简化代码

2.提高了代码的可复用性

3.提高了代码的可扩展性

4。继承是多态的前提

43.类属性

class Mclass1(object):
    x = 10
class Myclass2(Mclass1):
    pass
class Myclass3(Myclass1):
    pass

print(Myclass1.x,Myclass2.x,Myclass3.x)
Myclass2.x = 20
print(Myclass1.x,Myclass2.x,Myclass3.x)
Mclass1.x = 30
print(Myclass1.x,Myclass2.x,Myclass3.x)

分析:

第一次打印:都继承自父类Myclass1的属性,打印结果为:10 10 10

第二次打印:Myclass2修改了属性的指向,Myclass3还是继承自父类Myclass1的属性,打印结果为:10 20 10

打三次打印:父类修改类指向,Myclass2指向是属于自己定义的指向,不会继承父类的属性,所以打印结果为:30 20 30

44.继承树/菱形冲突

结论:

在多继承中,如果多个类之间的继承关系比较复杂,则被称为继承树或者菱形冲突

在多继承中,如果在中间某层有向上解析的迹象,则按照父类列表中弗雷德排序顺序进行广度排序

45.简述实例函数、类函数、静态函数之间的区别和联系

相同点:

本质上都是函数,所以默认参数,关键字参数,不定长参数都可以正常使用,也可以设置返回值

不同点:

1.是否有装饰器:类函数需要@classmethod装饰器修饰,静态函数需要staticmethod装饰器修饰,实例函数不需要装饰器修饰。

2.参数列表不同:类函数第一个参数必须为cls,实例函数第一个参数必须为self,静态函数对参数列表没有要求

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

4.使用场景不同:

			a.如需要在函数内部创建当前类的对象,则选择类函数

			b.如果需要封装一个工具类,为了简化函数的调用,建议使用类函数或者静态函数

			c.如需要在函数内部获取对象的属性,则选择实例函数

46.统计创建对象的个数

方式一:new

class Person(object):
    __per_count = 0
    def __new__(cls,*args**kwargs):
        print("new方法被调用了")
        cls.__per_count += 1
        return object.__new__(cls)
    def __init__(self):
        print("init被调用了")
    @classmethod
    def get_count():
        return cls.__per_count

方式二:init

class Person(object):
    __per_count = 0
    @classmethod
    def __init__(cls):
        print("hello",cls)
        cls.__per_count += 1
    @classmethod
    def get_count(cls):
        return cls.__per_count

47.什么是单例设计模式?

定义一个普通类,该类可以创建无数个对象,定义一个类,让该类只能创建一个对象,该类被称为单例类,单例:单个实例【对象】

程序运行过程中,确保某一个类只有一个实例【对象】,不管在哪个模块去这个类的对象,获取到的都是同一个对象。该类有一个静态方法,像整个工程提供这个实例,例如:一个国家只有一个主席

单例设计模式的核心:一个类有且只有一个实例,并且这个实例需要应用于整个程序中,该类被称为单例类

48.两种实现方式单例设计模式

类属性实现单例设计模式

"""
设计模式
    经过总结,优化,对我们经常遇到的问题所提出的一些可重用的方案
    设计模式是一种必须在特定的情境下使用的一种解决问题的犯案,不绑定编程语言
    23种设计模式,常用的单例,MVC(MTV),生产者消费者设计模式

单例设计模式:
    单例:单个实例,单个对象
    程序在运行过程中,确保一个类只能创建一个实例,不管在当前程序中哪个模块中获取该类对象,获取到的都是同一个对象
单例设计模式的核心:一个类仅有一个实例,该实例还需被应用在整个程序中
"""


class Person(object):
    __instance = None

    def __new__(cls, *args, **kwargs):
        if not cls.__instance:
            cls.__instance = super(Person, cls).__new__(cls)
        return cls.__instance


class A(object):
    """
    每次创建对象,都会调用__new__和__init__,只有第一次调用时__init__是动态绑定属性,
    后面调用都是对属性的重新赋值

    """
    __isinstance = None

    def __new__(cls, *args, **kwargs):
        if cls.__isinstance is None:
            cls.__isinstance = super(A, cls).__new__(cls)
        return cls.__isinstance

    def __init__(self, name, age):
        self.name = name
        self.age = age


a1 = A('jack', 12)
a2 = A('tom', 13)
print(id(a1))
print(id(a2))

装饰器实现单例设计模式

# 1.装饰器装饰类
def singleton(cls):
    instance = None

    def getinstance(*args, **kwargs):
        nonlocal instance
        # 构造函数只会在第一次创建对象的时候被调用
        if instance is None:
            instance = cls(*args, **kwargs)
        return instance

    return getinstance


@singleton
class A(object):
    pass


a1 = A()
a2 = A()
print(id(a1))
print(id(a2))

49.异常

当函数中使用了try_except_finally语句,如果在try或者except中使用return语句,finally不受影响,仍然会执行

def test(): 
    try:
        num = = int(input("请输入一个数字:"))
        list1 = [2,2,3]
        print(list1[num])
        return
    except ValueErroy as e:
        print(e)
    except IndexErroy as e:
        print(e)
    finally:
        print("finally执行了")

50.with 上下文件管理异常工作原理

class Check(object):
    def __enter__(self):
        # 当对象进入上下文件管理时,主要是为了初始化相应的资源,如,打开文件
        print("enter")
        return self
    def __exit__(self,exc_type,exc_val,exc_tb):
        print("exit")
        # exc_type异常类型,exc_val异常值
        # 如果出现异常,系统内部会自己处理,不会向Python解释器抛出异常
        return True
with Check() as c:
    print(c)

51.闭包

当一个嵌套函数在其外部区域引用了一个值时,该嵌套函数就是一个闭包,以下代码输出值为:

链接:https://www.nowcoder.com/questionTerminal/d173f0f517de45cb88eff23f8901f2d1?toCommentId=8049851
来源:牛客网

def adder(x):
    def wrapper(y):
        return x + y
    return wrapper
adder5 = adder(5)
print(adder5(adder5(6)))
  • A.10
  • B.12
  • C.14
  • D.16

解析:

1.得出adder5的结果:

adder5 = adder(5) —> x=5, 并返回wrapper的引用

2.由adder5得出adder5(adder5(6))的结果:

adder5(adder5(6))

----->x=5,wrapper(x=5,wrapper(6))

----->x=5,wrapper(11)

----->5 + 11 = 16

标签:__,面试题,Python,函数,python,汇总,列表,对象,print
来源: https://blog.csdn.net/m0_49397655/article/details/115678488

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有