1. 解释型和编译型语言的区别
编译型语言:把做好的源程序全部编译成二进制的可运行程序。然后,可直接运行这个程序。如:C,C++ ;
解释型语言:把做好的源程序翻译一句,然后执行一句,直至结束!如:Python。
2. 简述下 Python 中的字符串、列表、元组和字典
字符串(str):字符串是用引号括起来的任意文本,是编程语言中最常用的数据类型。
列表(list):列表是有序的集合,可以向其中添加或删除元素。
元组(tuple):元组也是有序集合,元组中的数无法修改。即元组是不可变的。
字典(dict):字典是无序的集合,是由键值对(key-value)组成的。
集合(set):是一组 key 的集合,每个元素都是唯一,不重复且无序的。
3. 简述上述数据类型的常用方法
字符串:
切片:'luobodazahui'[1:3]
format:"welcome to luobodazahui, dear {name}"format(name="baby")
join:可以用来连接字符串,将字符串、元组、列表中的元素以指定的字符(分隔符)连接生成一个新的字符串。'-'.join(['luo', 'bo', 'da', 'za', 'hui'])
String.replace(old,new,count):将字符串中的 old字符替换为 New字符,count为替换的个数 'luobodazahui-haha'.replace('haha', 'good')
split:切割字符串,得到一个列表
列表:
切片,同字符串
append和 extend向列表中添加元素
删除元素 del:
根据下标进行删除pop:删除最后一个元素
remove:根据元素的值进行删除
元素排序 sort:是将list按特定顺序重新排列,默认为由小到大,参数 reverse=True可改为倒序,由大到小。
reverse:是将list逆置。
字典:
清空字典 dict.clear()
指定删除:使用 pop方法来指定删除字典中的某一项(随机的)。
遍历字典
fromkeys用于创建一个新字典,以序列中元素做字典的键,value为字典所有键对应的初始值。
4. 简述 Python 中的字符串编码
计算机在最初的设计中,采用了8个比特(bit)作为一个字节(byte)的方式。一个字节能表示的最大的整数就是255,如果要表示更大的整数,就必须用更多的字节。最早,计算机只有 ASCII 编码,即只包含大小写英文字母、数字和一些符号,这些对于其他语言,如中文,日文显然是不够用的。后来又发明了Unicode,Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。UTF-8 是隶属于 Unicode 的可变长的编码方式。
在 Python 中,以 Unicode 方式编码的字符串,可以使用 encode() 方法来编码成指定的 bytes,也可以通过 decode()方法来把 bytes编码成字符串。
5. 一行代码实现数值交换
>>> a, b = 1, 2
>>> a, b = b, a
>>> print(a, b)
6. is 和 == 的区别
==是比较操作符,只是判断对象的值(value)是否一致,而 is 则判断的是对象之间的身份(内存地址)是否一致。对象的身份,可以通过 id() 方法来查看。
只有 id一致时,is比较才会返回 True,而当 value一致时,== 比较就会返回 True。
7. Python 函数中的参数类型
位置参数,默认参数,可变参数,关键字参数。
默认参数:定义函数时,为形参提供默认值,默认参数必须在最右端。 调用函数的时候如果没有传入实参,则取默认参数。如果传入实参,则取实参。
位置参数:调用函数时传入实际参数的数量和位置都必须和定义函数时保持一致
关键字参数:调用函数的时候使用的是键值对的方式,key=values。混合传参时关键字参数必须在位置参数之后。
8. *arg 和 **kwarg 作用
允许我们在调用函数的时候传入多个实参
*arg 会把位置参数转化为 tuple,**kwarg 会把关键字参数转化为 dict。
9. 获取当前时间
>>> import time
>>> import datetime
>>> print(datetime.datetime.now())
2022-09-12 19:51:24.314335
>>> print(time.strftime('%Y-%m-%d %H:%M:%S'))
2022-09-12 19:51:24
10. PEP8 规范
简单列举10条:
尽量以免单独使用小写字母’l’,大写字母’O’,以及大写字母’I’等容易混淆的字母。
函数命名使用全部小写的方式,可以使用下划线。
常量命名使用全部大写的方式,可以使用下划线。
使用 has或 is前缀命名布尔元素,如: is_connect = True; has_member = False。
不要在行尾加分号,也不要用分号将两条命令放在同一行。
不要使用反斜杠连接行。
方法定义之间空1行,顶级定义之间空两行。
如果一个类不继承自其它类,就显式的从object继承。
内部使用的类、方法或变量前,需加前缀_表明此为内部使用的。
要用断言来实现静态类型检测。
11. Python 的深浅拷贝
浅拷贝
>>> import copy
>>> list1 = [1, 2, 3, [1, 2]]
>>> list2 = copy.copy(list1)
>>> list2.append('a')
>>> list2[3].append('a')
>>> list1
[1, 2, 3, [1, 2, 'a']]
>>> list2
[1, 2, 3, [1, 2, 'a'], 'a']
浅拷贝只成功”独立“拷贝了列表的外层,而列表的内层列表,还是共享的。(划重点!!!)
深拷贝
>>> import copy
>>> list1 = [1, 2, 3, [1, 2]]
>>> list3 = copy.deepcopy(list1)
>>> list3.append('a')
>>> list3[3].append('a')
>>> list1
[1, 2, 3, [1, 2]]
>>> list3
[1, 2, 3, [1, 2, 'a'], 'a']
深拷贝使得两个列表完全独立开来,每一个列表的操作,都不会影响到另一个。
12. 打印九九乘法表
>>> for i in range(1, 10):
... for j in range(1, i + 1):
... print(f"{i}*{j}={i * j}", end=" ")
... print()
...
1*1=1
2*1=2 2*2=4
3*1=3 3*2=6 3*3=9
4*1=4 4*2=8 4*3=12 4*4=16
5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
13. filter、map、reduce 的作用
filter 函数用于过滤序列,它接收一个函数和一个序列,把函数作用在序列的每个元素上,然后根据返回值是True还是False决定保留还是丢弃该元素。
>>> mylist = list(range(10))
>>> list(filter(lambda x: x % 2 == 1, mylist))
[1, 3, 5, 7, 9]
map函数传入一个函数和一个序列,并把函数作用到序列的每个元素上,返回一个可迭代对象。
>>> list(map(lambda x: x % 2, mylist))
[0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
>>> list(map(lambda x: x * 2, mylist))
[2, 4, 6, 8, 10, 12, 14, 16, 18]
reduce函数用于递归计算,同样需要传入一个函数和一个序列,并把函数和序列元素的计算结果与下一个元素进行计算。
>>> from functools import reduce
>>> reduce(lambda x, y: x + y, range(101))
5050
reduce()的应用:
一行代码搞定计算所有元素的积:
reduce(lambda x, y: x * y, [1, 2, 3, 4])
计算列表中所有元素的最大值:
reduce(lambda x, y: x if x > y else y, [1, 2, 3, 4])
有一个列表:[3, 5, 8, 1]对应的是3581的每一个数字,要从这个列表计算出原来的数,可以这样做:
reduce(lambda x, y: x * 10 + y, [3, 5, 8, 1])
14. 为什么不建议函数的默认参数传入可变对象
>>> def test(L=[]):
... L.append('test')
... print(L)
...
>>> test()
['test']
>>> test()
['test', 'test']
默认参数是一个列表,是可变对象[],Python在函数定义的时候,默认参数 L 的值就被计算出来了,是[],每次调用函数,如果 L 的值变了,那么下次调用时,默认参数的值就已经不再是[]了。
15. 面向对象中__new__ 和 __init__ 区别
__new__是在实例创建之前被调用的,因为它的任务就是创建实例然后返回该实例对象,是个静态方法。
__init__是当实例对象创建完成后被调用的,然后设置对象属性的一些初始值,通常用在初始化一个类实例的时候,是一个实例方法。
__new__至少要有一个参数cls,代表当前类,此参数在实例化时由 Python 解释器自动识别。
__new__必须要有返回值,返回实例化出来的实例,这点在自己实现__new__时要特别注意,可以 return 父类(通过 super(当前类名, cls))__new__出来的实例,或者直接是 object的__new__出来的实例。
__init__有一个参数 self,就是这个__new__返回的实例,__init__在__new__的基础上可以完成一些其它初始化的动作,__init__不需要返回值。
如果__new__创建的是当前类的实例,会自动调用__init__函数,通过 return 语句里面调用的__new__函数的第一个参数是 **cls**** 来保证是当前类实例**,如果是其他类的类名,那么实际创建返回的就是其他类的实例,其实就不会调用当前类的__init__函数,也不会调用其他类的__init__函数。
16. 三元运算规则
如果 a>b 成立 就输出 a-b 否则a+b。
>>> >>> a, b = 1, 2
>>> h = a - b if a > b else a + b
>>> h
3
17. 生成随机数
>>> import random
>>> random.random()
0.7571910055209727
>>> random.randint(1, 100)
23
>>> random.uniform(1, 5)
3.0640732831151687
用np.random也可以!
18. zip 函数用法
zip() 函数将可迭代的对象作为参数,将对象中对应的元素打包成一个元组,然后返回由这些元组组成的列表。
>>> list1 = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
>>> list2 = [0, 3, 2, 4]
>>> list(zip(list1, list2))
[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]
19. range和xrange的区别
只有Python2中才有xrange()和range(),Python3中的range()其实就是Python2中xrange()。
range([start,] stop[, step]),根据start与stop指定的范围以及step设定的步长,生成一个序列;
xrange() 生成一个生成器,可以很大的节约内存。
20. with方法打开文件的作用
打开文件在进行读写的时候可能会出现一些异常状况,如果按照常规的f.open()写法,我们需要 try,except,finally,做异常判断,并且文件最终不管遇到什么情况,都要执行f.close() 关闭文件,with方法帮我们实现了finally 中 f.close()。
with open("hello.txt", "a") as f:
f.write("hello world!")