震惊!!! Python面试题居然可以这样整理~

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

众所周知:

了解语言的底层原理,熟悉语言的特点,有助于我们更好地掌握和运用该门语言。底层原理,算法和数据结构及其相关的

仅以本文来汇总Python面试题

1.Python的特点

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

2.Python优缺点

2.1 优点:

  • 易于学习【Python有相对较少的关键字,结构简单,和一个明确定义的语法,学习起来更加简单】
  • 易于阅读【Python代码定义的更清晰】
  • 易于维护【Python的成功在于它的源代码是相当容易维护的】
  • 一个广泛的标准库及第三方库【Python的最大优势之一是丰富的库,跨平台的,在unix、windows和mac os上的兼容性很好】
  • 互动模式【互动模式的支持,可以从终端输入执行代码并获得结果的语言,互动的测试和调试代码片段】
  • 可移植性【基于其开发源代码的特性,Python已经被移植到许多平台】
  • 可扩展性【如果需要一段运行很快的关键代码,或者想要编写一些不愿开发的算法,可以使用C或者C++完成那部分程序,然后从你的Python程序中调用】
  • 数据库【Python提供所有主要的商业数据库的接口】
  • GUI编程(图形化界面)【Python支持GUI可以创建和移植到许多系统调用】
  • 可嵌入性【可以将Python嵌入到C或者C++程序,让你程序的用户获得“脚本化”的能力】

2.2 缺点:

  • 运行速度慢【和C程序相比非常慢,因为Python是解释型语言,代码在执行时会一行一行的翻译成CPU能理解的机器码,这个翻译过程非常耗时,所以很慢,而C程序是运行前直接编译成CPU能执行的机器码,所以非常快】
  • 代码不能加密【如果要发布Python程序,实际上就是发布源代码,这一点跟C语言不通,C语言不用发布源代码,只需要把编译后的机器码(就是windows上常见的xxx.exe)发布出去,要从机器码反推出C代码是不可能的,所以,凡是编译型的语言,都没有这个问题,而解释型的语言,则必须把源码发布出去】

3. Python2.x和Python3.x版本的区别

一、核心类差异

  1. Python3 对 Unicode 字符的原生支持。
    Python2 中使用 ASCII 码作为默认编码方式导致 string 有两种类型 str 和 unicode,Python3 只
    支持 unicode 的 string。Python2 和 Python3 字节和字符对应关系为:
  2. Python3 采用的是绝对路径的方式进行 import
    Python2 中相对路径的 import 会导致标准库导入变得困难(想象一下,同一目录下有 file.py,如
    何同时导入这个文件和标准库 file)。Python3 中这一点将被修改,如果还需要导入同一目录的文件必须使用绝对路径,否则只能使用相关导入的方式来进行导入。
  3. Python2 中存在老式类和新式类的区别,
    Python3 统一采用新式类。新式类声明要求继承 object,
    必须用新式类应用多重继承。
  4. Python3 使用更加严格的缩进。
    Python2 的缩进机制中,1 个 tab 和 8 个 space 是等价的,所以在缩进中可以同时允许 tab 和 space 在代码中共存。这种等价机制会导致部分 IDE 使用存在问题。
    Python3 中 1 个 tab 只能找另外一个 tab 替代,因此 tab 和 space 共存会导致报错:TabError:
    inconsistent use of tabs and spaces in indentation.

二、废弃类差异

  1. print 语句被 Python3 废弃,统一使用 print 函数
  2. exec 语句被 python3 废弃,统一使用 exec 函数
  3. execfile 语句被 Python3 废弃,推荐使用 exec(open("./filename").read())
  4. 不相等操作符"<>“被 Python3 废弃,统一使用”!="
  5. long 整数类型被 Python3 废弃,统一使用 int
  6. xrange 函数被 Python3 废弃,统一使用 range,Python3 中 range 的机制也进行修改并提高
    了大数据集生成效率
  7. Python3 中这些方法再不再返回 list 对象:dictionary 关联的 keys()、values()、items(),zip(),
    map(),filter(),但是可以通过 list 强行转换:
    mydict={“a”:1,“b”:2,“c”:3}
    mydict.keys() #<built-in method keys of dict object at 0x000000000040B4C8>
    list(mydict.keys()) #[‘a’, ‘c’, ‘b’]
  8. 迭代器 iterator 的 next()函数被 Python3 废弃,统一使用 next(iterator)
  9. raw_input 函数被 Python3 废弃,统一使用 input 函数
  10. 字典变量的 has_key 函数被 Python 废弃,统一使用 in 关键词
  11. file 函数被 Python3 废弃,统一使用 open 来处理文件,可以通过 io.IOBase 检查文件类型
  12. apply 函数被 Python3 废弃
  13. 异常 StandardError 被 Python3 废弃,统一使用 Exception

三 、修改类差异

  1. 浮点数除法操作符“/”和“//”的区别
    “ / ”:
    Python2:若为两个整形数进行运算,结果为整形,但若两个数中有一个为浮点数,则结果为
    浮点数;
    Python3:为真除法,运算结果不再根据参加运算的数的类型。
    “//”:
    Python2:返回小于除法运算结果的最大整数;从类型上讲,与"/"运算符返回类型逻辑一致。
    Python3:和 Python2 运算结果一样。

  2. 异常抛出和捕捉机制区别
    Python2
    raise IOError, “file error” #抛出异常
    except NameError, err: #捕捉异常
    Python3
    raise IOError(“file error”) #抛出异常
    except NameError as err: #捕捉异常

  3. for 循环中变量值区别
    Python2,for 循环会修改外部相同名称变量的值

    1. i = 1
      print ('comprehension: ', [i for i in range(5)])
      print (‘after: i =’, i ) #i=4
      Python3,for 循环不会修改外部相同名称变量的值
    2. i = 1
    3. print ('comprehension: ', [i for i in range(5)])
    4. print (‘after: i =’, i ) #i=1
  4. round 函数返回值区别
    Python2,round 函数返回 float 类型值
    isinstance(round(15.5),int) #True
    Python3,round 函数返回 int 类型值
    isinstance(round(15.5),float) #True

  5. 比较操作符区别
    Python2 中任意两个对象都可以比较

    1. 11 < ‘test’ #True
      Python3 中只有同一数据类型的对象可以比较
    2. 11 < ‘test’ # TypeError: unorderable types: int() < str()

四、第三方工具包差异

我们在 pip 官方下载源 pypi 搜索 Python2.7 和 Python3.5 的第三方工具包数可以发现,Python2.7版本对应的第三方工具类目数量是 28523,Python3.5 版本的数量是 12457,这两个版本在第三方工具包支持数量差距相当大。

五、工具安装问题

windows 环境
  1. Python2 无法安装 mysqlclient。Python3 无法安装 MySQL-python、 flup、functools32、Gooey、Pywin32、 webencodings。
  2. matplotlib 在 python3 环境中安装报错:The following required packages can not be built:freetype, png。需要手动下载安装源码包安装解决。
  3. scipy 在 Python3 环境中安装报错,numpy.distutils.system_info.NotFoundError,需要自己手工下载对应的安装包,依赖 numpy,pandas 必须严格根据 python 版本、操作系统、64 位与否。运行
  4. matplotlib 后发现基础包 numpy+mkl 安装失败,需要自己下载,国内暂无下载源
centos 环境下
  1. Python2 无法安装 mysql-python 和 mysqlclient 包,报错:EnvironmentError:
    mysql_config not found,解决方案是安装 mysql-devel 包解决。
  2. 使用 matplotlib 报错:no module named _tkinter安装 Tkinter、tk-devel、tc-devel 解决。
  3. pywin32 也无法在 centos 环境下安装。

4.标识符和关键字

4.1 标识符

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

4.1.1. 合法标识符的命名规则:
  1. 只能由数字,字母和下划线组成
  2. 不可以是除了下划线之外的其他特殊字符
  3. 开头不能是数字或者空格
  4. 不能是Python的关键字,也不能使用系统的函数名【int,str,list。。。。】
  5. 严格区分大小写 age Age
4.2.2. 标识符的命名规范:
  • 尽量做到见名知意【具有描述性】
  • 遵守一定的命名规范
    1. Python官方推荐的命名方式:变量名,函数名和文件名全小写,使用下划线连接,如:stu_name check_qq
    2. 驼峰命名法:不同的单词之间使用首字母大写的方式进行分隔,又分为大驼峰和小驼峰,比如:stuName就是小驼峰,StuName就是大驼峰,小驼峰常用于变量或者函数的命名,大驼峰常用于类的命名

4.2 关键字

概念: 一些具有特殊功能的标识符
注意:关键字已经被python官方使用了,所以不允许开发者自己定义和关键字重名的标识符

False None True and as assert break class continue def del elif else except finally for from global if import in is lambda nonlocal not or pass raise return try while with yield …

5.赋值

    i,j = 10 ,20
    i,i = 30, 55
      
    print(i)  # 55

6.变量的存储与引用

定义变量时,变量名与变量值都是需要存储的,分别对应内存中的两块区域:堆区与栈区

变量名与值内存地址的关联关系存放于栈区,变量值存放于堆区,内存管理回收的则是堆区的内容
定义了两个变量x = 10、y = 20, 当我们执行x=y时,内存中的栈区与堆区变化, 直接引用指的是从栈区出发直接引用到的内存地址。
间接引用指的是从栈区出发引用到堆区后,再通过进一步引用才能到达的内存地址

7.Python的垃圾回收机制

垃圾回收机制(简称GC:garbage collection)是Python解释器自带一种机制,专门用来回收不可用的变量值所占用的内存空间.Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾。在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的循环引用的问题,并且通过“分代回收”(generation collection)以空间换取时间的方式来进一步提高垃圾回收的效率

一, 引用计数

  1. 引用计数的实现

    引用计数就是:变量值被变量名关联的次数

    如:age=18

    变量值18被关联了一个变量名age,称之为引用计数为1

    引用计数增加:

    age=18 (此时,变量值18的引用计数为1)

    m=age (把age的内存地址给了m,此时,m,age都关联了18,所以变量值18的引用计数为2)

    引用计数减少:

    age=10(名字age先与值18解除关联,再与3建立了关联,变量值18的引用计数为1)

    del m(del的意思是解除变量名x与变量值18的关联关系,此时,变量18的引用计数为0)

    值18的引用计数一旦变为0,其占用的内存地址就应该被解释器的垃圾回收机制回收

  2. 引用计数的问题与解决方案

    1.循环引用问题

    引用计数机制存在着一个致命的弱点,即循环引用(也称交叉引用)如下我们定义了两个列表,简称列表1与 列表2,变量名l1指向列表1,变量名l2指向列表2

    循环引用会导致:值不再被任何名字关联,但是值的引用计数并不会为0,应该被回收但不能被回收,什么意 思呢?试想一下,请看如下操作

    但此时两个列表的引用计数均不为0,但两个列表不再被任何其他对象关联,没有任何人可以再引用到它们,所以它俩占用内存空间应该被回收,但由于相互引用的存在,每一个对象的引用计数都不为0,因此这些对象所占用的内存永远不会被释放,所以循环引用是致命的,这与手动进行内存管理所产生的内存泄露毫无区别。 所以Python引入了“标记-清除” 与“分代回收”来分别解决引用计数的循环引用与效率低的问题

    2.效率问题

    基于引用计数的回收机制,每次回收内存,都需要把所有对象的引用计数都遍历一遍,这是非常消耗时间的,于是引入了分代回收来提高回收效率,分代回收采用的是用“空间换时间”的策略

二, 标记-清除(用于解决循环引用)

容器对象(比如:list,set,dict,class,instance)都可以包含对其他对象的引用,所以都可能产生循环引用。而“标记-清除”计数就是为了解决循环引用的问题。标记/清除算法的做法是当应用程序可用的内存空间被耗尽的时,就会停止整个程序,然后进行两项工作,第一项则是标记,第二项则是清除

  1. 标记

    通俗地讲就是: 栈区相当于“根”,凡是从根出发可以访达(直接或间接引用)的,都称之为“有根之人”,有根之人当活,无根之人当死。

    具体地:标记的过程其实就是,遍历所有的GC Roots对象(栈区中的所有内容或者线程都可以作为GC Roots对象),然后将所有GC Roots的对象可以直接或间接访问到的对象标记为存活的对象,其余的均为非存活对象,应该被清除。

  2. 清除

    清除的过程将遍历堆中所有的对象,将没有标记的对象全部清除掉。

    基于上例的循环引用,当我们同时删除l1与l2时,会清理到栈区中l1与l2的内容以及直接引用关系

    这样在启用标记清除算法时,从栈区出发,没有任何一条直接或间接引用可以访达l1与l2,即l1与l2成了“无根之人”,于是l1与l2都没有被标记为存活,二者会被清理掉,这样就解决了循环引用带来的内存泄漏问题

三,分代回收 (用于解决效率问题)

分代回收的核心思想是:在历经多次扫描的情况下,都没有被回收的变量,gc机制就会认为,该变量是常用变量,gc对其扫描的频率会降低,具体实现原理如下:

  1. 分代:
    根据变量的生成时间进行分代

  2. 回收:

    回收依然是使用引用计数作为回收的依据

    虽然分代回收可以起到提升效率的效果,但也存在一定的缺点:

    例如一个变量刚刚从新生代移入青春代,该变量的绑定关系就解除了,该变量应该被回收,但青春代的扫描频率低于新生代,这就到导致了应该被回收的垃圾没有得到及时地清理。

    没有十全十美的方案:

    毫无疑问,如果没有分代回收,即引用计数机制一直不停地对所有变量进行全体扫描,可以更及时地清理掉垃圾占用的内存,但这种一直不停地对所有变量进行全体扫描的方式效率极低,所以我们只能将二者中和。

四,总结

垃圾回收机制是在清理垃圾&释放内存的大背景下,允许分代回收以极小部分垃圾不会被及时释放为代价,以此换取引用计数整体扫描频率的降低,从而提升其性能,这是一种以空间换时间的解决方案目录

8. 进制转换

int(“0b1120”,base=( 16 )) # 16

9.逻辑运算符

    print(3 or 5)  #3
    print(0 or 5)   # 5
    print(1 and 0)  # 0
    print(False and 5) # 5
    
1. a and b 
	如果 a=Ture,则输出b
    如果 a=False , 则输出a

2. a or b 
    如果 a=Ture,则输出a
    如果 a=False, 则输出b

10.两个变量交换值的四种方法

	a = 10
    b = 22
    
    # 方法一: 定义第三个变量
    num1 = 23
    num2 = 10
    temp = num1
    num1 = num2
    num2 = temp
    
    # 方法二: 类似交换
    a, b = b, a
    
    # 方法三: +-运算
    a =  a + b
    b = a - b
    a = a - b
    
    # 方法四:  异或^
    num1 = 23
    num2 = 10
    num1 = num1 ^ num2    # num1 = 23 ^ 10
    num2 = num1 ^ num2    # num2 = 23 ^ 10 ^ 10 = 23
    num1 = num1 ^ num2    # num1 = 23 ^ 10 ^ 23 = 10
    print(num1,num2)

11.is 和 == 的区别

is :用于判断id是否相同

== :用于判断值是否相同

12.break和continue

12.1 概念区别

1.break主要应用于循环中,用来结束当前循环【就近原则】【直接跳出循环,继续执行后面循环外部的代码】
2. continue :结束本次循环,进入下一次循环

12.2.break如何跳出外层循环

    # break 通过设置状态变量,来跳出外层变量:
    
    a = 0
    flag = 0
    while a < 3:
        b = 0
        while b < 5:
            if b == 4:
                flag = 1
                break
            print(f'{a}={b}')
            b += 1
        if flag:
            break
        a += 1

13.列表操作append()和extend()的比较

相同点:

1.都是向列表追加元素
2.追加的位置都是在原列表的末尾

不同点:

1.append()可以追加任意类型的元素;extend()只能追加可迭代对象
2.append()追加可迭代对象时,是把可迭代对象作为元素整体追加; extend()是将可迭代对象的元素一一追加到原列表中,也就是’打碎加入’

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

"""
相同点:
    a.二者都是有序的
    b.二者都可以存储重复元素
    c.二者都可以存储不同类型的数据
    d.二者的遍历方式完全相同
    e.二者都可以进行切片
不同点:
    a.表示方式,列表:[],元组:()
    b.可变性,列表是可变的,元组是不可变的
    c.使用场景,在多线程的使用场景中,为了避免多个线程访问同一个数据造成数据混乱,则可以使用元组
                如果涉及到元素的添加或者删除或者修改,则使用列表
    d.内存角度,元组在创建时间和空间上都优于列表
"""

15.不同的方式定义字典

  # 方式一           
    d1 = {"name":"张三","age":18}
    print(d1)
    
    # 方式二
    d2 = {}
    d2['name'] = "lisi"
    d2["score"] = 88
    print(d2)
    
    # 方式三
    # dict(key1=value1,key2=value2....),但是,此处的key只能是字符串
    d3 = dict(name='abc',hobby='play')
    print(d3)
    # d3 = dict(10='abc',20='play')
    # print(d3)
    d3 = {10:'abc',20:'play'}
    print(d3)
    
    # 方式四
    # dict([(key1,value1),(key2,value2)......])
    d4 = dict([("a",10),('b',20),('c',30)])
    print(d4)
    
    # 方式五
    # dict(zip([所有的key],[所有的value]))
    d5 = dict(zip(["a",'b','c'],[24,5,99]))
    print(d5)

16.分别简述字符串,列表,元组,字典和集合的特点

列表:一种有序的,可以存储重复元素的,可以存储不同类型数据的,可变的集合

元组:一种有序的,可以存储重复元素的,可以存储不同类型数据的,不可变的集合

字典:一种无序的,key不能重复但value可以重复的,key只能是不可变的数据类型,value没有要求,可变的集合

集合:一种无序的,不允许存储重复元素,可以存储不同类型数据的,可变的集合

字符串:一种有序的,可以存储重复元素的,不可变的集合

17.简述字典和集合之间和联系

相同点:

a.都使用{}表示

b.都是容器,其中都可以存储数据

不同点:

a.{}为空,默认表示字典

b.字典中存储的键值对,集合中存储的是一组没有重复的数据

联系:

集合中的元素相当于字典中的key,无序且唯一

18.函数的优点

a.简化代码结构,提高应用的模块性

b.提高了代码的复用性

c.提高了代码维护性

d.提高了代码的可读性

19.简述传参时值传递和引用传递

值传递:实参是不可变的数据类型,在函数内部修改形参,对实参没有影响

引用传递:实参是可变的数据类型,在函数内部修改容器中的元素,实参会随着被修改

20.*xx 打包

定义变量的时候,*xx则表示打包,结果是一个列表,注意和函数形参列表中的*xx进行区分

#  *lst,*dic表示将lst或dic中的元素,拆包分别传参

    def show(a, b, c):
        print(a, b, c)
    lst = [10, 20, 30]
    show(*lst)

21.匿名函数 lambda

lambda 形参列表:函数体

  1. lambda只是一个表达式,用一行代码实现一个简单的逻辑,可以达到对函数的简化【优点】
  2. lambda主体是一个表达式,而不是一个代码块,只能封装有限的逻辑【缺点】
  3. lambda拥有自己的命名空间,不能访问自有列表之外或者全局命名空间里的参数
  4. 返回值直接书写,不需要结束于return
  5. 匿名函数本质仍然是一个函数,所以默认参数,关键字参数和不定长参数同样使用

22.阅读代码:高阶函数

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

23.阅读代码:局部变量

    num  = 10
    def test():
        num += 20     
        print(num)   # UnboundLocalError: local variable 'num' referenced before assignment
    test()
    print(num)    # 函数内部调用,需定义变量或使用golbal声明

24.global与nonlocal

global: 当全局变量和局部变量重名时,在局部变量未定义之前修改全局变量,则可以使用global声明变量来自于全局变量

 num = 10
    def func():
        num = 5
    func()
    print(num)   # 10
    
    num = 10
    def func():
        global num
        num = 5
    func()
    print(num)    # 5

nonlocal
只能使用在闭包中,当函数作用域内的变量和局部作用域的变量重名时,在局部作用域中修改函数作用域内的变量,则可以使用nonlocal声明变量来自于函数作用域

    def outter():
        num = 10
        def inner():
            num = 5
        print(num)      # 10
        return inner
    outter()()
    
    def outter():
        num = 10
        def inner():
            nonlocal num 
            num = 5
        print(num)      # 5
        return inner
    outter()()

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

区别:

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

迭代器:Iterator,可以通过next()获取下一个元素的对象,如:生成器

联系:

如果一个对象是迭代器,那它肯定是一个可迭代对象;如果一个对象是可迭代对象,那它不一定是迭代器

可以通过系统功能iter()将一个不是迭代器的可迭代对象转换为迭代器
  	from collections import  Iterable,Iterator
    # 1.可迭代对象
    print(isinstance({"a":10},Iterable))
    print(isinstance((i for i in range(5)),Iterable))
    
    # 2.迭代器
    print(isinstance({"a":10},Iterator))
    print(isinstance((i for i in range(5)),Iterator))
    # 3.将可迭代对象强转为迭代器
    print(isinstance(iter([2, 4, 5]), Iterator))
    print(isinstance(iter((2, 4, 5)), Iterator))
    print(isinstance(iter("abc"), Iterator))
    print(isinstance(iter({4, 6, 67}), Iterator))
    print(isinstance(iter({"a": 10}), Iterator))

26.装饰器:统计多个函数的执行时间

	import time
	def running_time(func):
	   def run(*args, **kwargs):
	       start = time.time()
	       func(*args, **kwargs)
	       stop = time.time()
	       return round(stop - start, 3)
	   return run
	@running_time
	def show():
	   for i in range(10000000):
	       pass
	r = show()
	print(r)

27.装饰器:校验格式是否为图片

    def isimage(func):
        def check(path):
            if path.endswith('.png') or path.endswith('.jpg'):
                func(path)
            else:
                print('不是图片,无法完成上传')
        return check
    @isimage
    def up_img(path):
        print(f'图片的路径是{path}')
        print('上传成功')
    up_img('av.png')
    up_img('av.txt')

28.有参的装饰器

@xxx(value)
a. 调用装饰器的外部函数,将value传递给外部函数的形参
b. 调用装饰器的内部函数,将被装饰的原函数传递给内部函数的形参
c. 原函数的函数名指向内部函数的返回值

   dic = {}
    def outter2(a):                # a表示装饰器参数
        print('外部函数调用了')
        def inner2(b):              # b表示原函数
            print('内部函数调用了')      # 增加新功能
            dic[a] = b
            b()                     # 调用原函数
            return 333
        print('over')
        return inner2                # 必须返回内部函数的引用,否则无法调用内部函数
    @outter2('aaa')
    def show():
        print('show原函数调用了')
    print(dic)
    print(show)
    
    '''
    外部函数调用了
    over
    内部函数调用了
    show原函数调用了
    {'aaa': <function show at 0x0000024FEF161D30>}
    333
    '''

29.多个装饰器装饰同一个函数

   # 作用:给同一个函数增加多个不同的新功能
    # a
    def wrapper1(func1):
        print("wrapper~~~~~1111")
        def inner1(*args,**kwargs):
            print("新功能~~~~1111")
            func1(*args,**kwargs)
        return inner1
    def wrapper2(func2):
        print("wrapper~~~~22222")
        def inner2(*args,**kwargs):
            print("新功能~~~~222")
            func2(*args,**kwargs)
        return inner2
    def wrapper3(func3):
        print("wrapper~~~~33333")
        def inner3(*args,**kwargs):
            print("新功能~~~~3333")
            func3(*args,**kwargs)
        return inner3
    @wrapper1     # inner2---->func1    返回inner1
    @wrapper2     # inner3--->func2    返回inner2
    @wrapper3     # show原---》func3   返回inner3
    def show():
        print("show原函数")
    show()
    
    print("*" * 30)

30.变量的作用域

全局作用域:global
函数作用域:enclosing
局部作用域:local
内置作用域:built-in

全局变量和局部变量的区别:
全局变量:直接定义在py文件中的变量,可以在整个程序中被访问
局部变量:定义在函数中或者类中的变量,只能在当前函数或者当前类中被直接访问

“”"

31.栈和队列

  1. 栈(Stack)是限定只能在表的一端进行插入和删除操作的线性表,先进后出,后进先出
  2. 队列(Queue)是限定只能在表的一端进行插入和在另一端进行删除操作的线性表,先进先出,后进后出
  3. 线性表:线性表是一种线性结构,它是一个含有n≥0个结点的有限序列,同一个线性表中的数据元素数据类型相同并且满足“一对一”的逻辑关系

栈与队列的相同点:

  1. 都是线性结构。
  2. 插入操作都是限定在表尾进行。
  3. 都可以通过顺序结构和链式结构实现。
  4. 插入与删除的时间复杂度都是O(1),在空间复杂度上两者也一样。
  5. 多链栈和多链队列的管理模式可以相同

栈与队列的不同点

  1. 删除数据元素的位置不同,栈的删除操作在表尾进行,队列的删除操作在表头进行。
  2. 应用场景不同;常见栈的应用场景包括括号问题的求解,表达式的转换和求值,函数调用和递归实现,深度优先搜索遍历等;常见的队列的应用场景包括计算机系统中各种资源的管理,消息缓冲器的管理和广度优先搜索遍历等。

32.面向过程和面向对象的区别

面向过程

在生活案例中:一种看待问题的思维方式,在思考问题的时候,着眼于问题是怎样一步一步解决的,然后亲力亲为的去解决问题 ,在决定做某件事的时候,事情的处理流程已经确定

在程序中:

  1. 代码从上而下顺序执行
  2. 各模块之间的关系尽可能简单,在功能上相对独立
  3. 每一模块内部均是由顺序、选择和循环三种基本结构组成
  4. 其模块化实现的具体方法是使用子程序
  5. 程序流程在写程序时就已决定

面向对象

在生活案例中:
1.也是一种看待问题的思维方式,着眼于找到一个具有特殊功能的具体个体,然后委托这个个体去做某件事情,我们把这个个体就叫做对象,一切皆对象
2.是一种更符合人类思考习惯的思想【懒人思想】,可以将复杂的事情简单化,将程序员从执行者转换成了指挥者

在程序中:

  1. 把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象
  2. 对同类对象抽象出其共性,形成类
  3. 类中的大多数数据,只能用本类的方法进行处理
  4. 类通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信
  5. 程序流程由用户在使用中决定
  6. 使用面向对象进行开发,先要去找具有所需功能的对象,如果该对象不存在,那么创建一个具有该功能的对象

注意:面向对象只是一种思想,并不是一门编程语言,也不会绑定编程语言

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个一次调用就可以了

面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为

33.面向过程和面向对象的优缺点

面向过程:

优点: 性能比面向对象高,开销比较大,比较消耗资源,比如单片机、嵌入式开发等一般采用面向过程开发,因为性能是最重要的因素

缺点: 没有面向对象易维护,易复用,易扩展

面向对象:

优点:易维护,易复用,易扩展,由于面向对象有封装,继承,多态的特性,可以设计出低耦合的系统,使得系统更加灵活,更加易于维护

缺点: 性能比面向过程低

Python

Python是一门面向对象的语言,面向对象语言的特点:封装,继承和多态

34.Python中的封装

  1. 广义的封装:函数的定义和类的提取,都是封装的体现
  2. 狭义的封装: 在面向对象编程中,一个类的某些属性,在使用的过程中,如果不希望被外界【直接】访问,就可以将该属性封装【将不希望被外界直接访问的属性私有化private,该属性只能被当前类持有,此时可以给外界暴露一个访问的函数即可】
  3. 封装的本质:就是属性私有化的过程
  4. 封装的好处:提高了数据的安全性,提高了数据的复用性

35.Python中的继承

一.概念

  1. 如果两个或者两个以上的类具有相同的属性和方法,我们可以抽取一个类出来,在抽取出来的类中声明各个类公共的部分
  2. 被抽取出来的类——父类【father class】 超类【super class】 基类【base class】
  3. 两个或两个以上的类——子类 派生类
  4. 他们之间的关系——子类继承自父类 或者 父类派生了子类
  5. 子类对象可以直接访问父类中未被私有化的属性和函数
  6. 子类不会继承父类中的slots
  7. 父类对象不能访问子类中特有的属性和函数

二.优点:

  1. 可以简化代码,减少冗余
  2. 提高代码的可维护性
  3. 是多态的前提

三.缺点:

  1. 在继承关系中,类与类之间的耦合性相对较高【如果修改父类,所有的子类都可能会发生改变】

四.菱形冲突【继承树】

  1. 在多继承中,如果在中间某层有向上解析的迹象,会按照父类列表中的排列顺序进行依次解析,当所有的父类全部解析完毕,才会继续向上解析,将这种解析称为广度优先解析

36.代码阅读: 类的继承

    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

37.实例方法,类方法和静态方法之间的区别

 '''
   1. 是否有装饰器修饰: 类函数需要用@classmethod装饰,静态方法用@staticmethod修饰, 实例函数没有装饰器修饰

   2. 形参列表不同:实例函数的形参列表中必须有self, self表示当前对象,类函数的形参列表必须有cls,cls表示当前类,静态方法没有形参

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

   4. 使用场景不同:

           a. 如果需要定义一个工具类, 则该工具类中的函数建议定义为类函数或静态函数

           b. 如果在函数内部需要访问对象的属性,则函数定义为实例函数

           c. 如果在函数内部需要创建当前类的对象,则将函数定义为类函数【cls】
 '''

38.需求:从控制台输入一段文本,统计每个字符出现的次数


data = input("请输入:")
#方式一 : 遍历后添加到字典
dict1 = {}
for ch in data:
    if ch not in dict1:
        dict1[ch] = 1
    else:
        dict1[ch] += 1
print(dict1)

#方式二 : 遍历每一个元素 + count()
dict1 = {}
for ch in data:
    dict1[ch] = data.count(ch)
print(dict1)

#方式三: 创建一个计数器
c = collections.Counter()
for ch in data:
    c[ch] += 1
print(c)

39.序列化与反序列化

  1. 对象的序列化:将一个对象持久化到磁盘上,相当将一个对象写入到指定文件中
  2. 对象的反序列化:将磁盘上的对象获取出来,相当于将磁盘上的对象读取出来
  3. 在Python中,可以实现对象的序列化和反序列化的模块 有pickle和json

40.写成至少五种常见的异常类型:

1.ValueError:进行数值转换的时候,不符合转换规则

2.IndexError:如果列表,元组或者字符串的索引越界

3.UnboundLocalError:不同作用域下的变量重名时,当局部变量内的变量还未被定义就使用

4.NameError:使用了一个未被定义的变量

5.KeyError:当访问了字典中不存在的key时

6.ModuleNotFoundError:导入了不存在的模块或者模块的路径书写错误		

7.FileNotFoundError:打开了不存在的文件,主要体现在读取的过程中

8.LookupError:使用了错误的编码格式

9.AttributeError:当访问了一个对象不存在的属性或者方法

10.SyntaxError:基本的语法错误

11.IndentationError:代码块缩进错误

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值