从今天开始,陆续分享一些 Python 相关的面试题,在学习的路上,与君共勉!java
各位 Python 大佬请绕过啊!!固然若是能给些指点,那就再好不过了!python
基础篇(一)面试
Python 语言简单易懂,上手容易,随着 AI 风潮,愈来愈火。正则表达式
编译型语言:把作好的源程序所有编译成二进制的可运行程序。而后,可直接运行这个程序。如:C,C++算法
解释型语言:把作好的源程序翻译一句,而后执行一句,直至结束!如:Python, (Java 有些特殊,java程序也须要编译,可是没有直接编译称为机器语言,而是编译称为字节码,而后用解释方式执行字节码。)编程
字符串(str):字符串是用引号括起来的任意文本,是编程语言中最经常使用的数据类型。json
列表(list):列表是有序的集合,能够向其中添加或删除元素。bash
元组(tuple):元组也是有序集合,可是是没法修改的。即元组是不可变的。微信
字典(dict):字典是无序的集合,是由 key-value 组成的。app
集合(set):是一组 key 的集合,每一个元素都是惟一,不重复且无序的。
mystr='luobodazahui'
mystr[1:3]
复制代码
output
'uo'
复制代码
mystr2 = "welcome to luobodazahui, dear {name}"
mystr2.format(name="baby")
复制代码
output
'welcome to luobodazahui, dear baby'
复制代码
能够用来链接字符串,将字符串、元组、列表中的元素以指定的字符(分隔符)链接生成一个新的字符串。
mylist = ['luo', 'bo', 'da', 'za', 'hui']
mystr3 = '-'.join(mylist)
print(mystr3)
复制代码
outout
'luo-bo-da-za-hui'
复制代码
String.replace(old,new,count) 将字符串中的 old 字符替换为 New 字符,count 为替换的个数
mystr4 = 'luobodazahui-haha'
print(mystr4.replace('haha', 'good'))
复制代码
output
luobodazahui-good
复制代码
切割字符串,获得一个列表。
mystr5 = 'luobo,dazahui good'
# 以空格分割
print(mystr5.split())
# 以h分割
print(mystr5.split('h'))
# 以逗号分割
print(mystr5.split(','))
复制代码
output
['luobo,dazahui', 'good']
['luobo,daza', 'ui good']
['luobo', 'dazahui good']
复制代码
同字符串
向列表中国添加元素
mylist1 = [1, 2]
mylist2 = [3, 4]
mylist3 = [1, 2]
mylist1.append(mylist2)
print(mylist1)
mylist3.extend(mylist2)
print(mylist3)
复制代码
outout
[1, 2, [3, 4]]
[1, 2, 3, 4]
复制代码
del:根据下标进行删除
pop:删除最后一个元素
remove:根据元素的值进行删除
mylist4 = ['a', 'b', 'c', 'd']
del mylist4[0]
print(mylist4)
mylist4.pop()
print(mylist4)
mylist4.remove('c')
print(mylist4)
复制代码
output
['b', 'c', 'd']
['b', 'c']
['b']
复制代码
sort:是将list按特定顺序从新排列,默认为由小到大,参数 reverse=True 可改成倒序,由大到小。
reverse:是将list逆置。
mylist5 = [1, 5, 2, 3, 4]
mylist5.sort()
print(mylist5)
mylist5.reverse()
print(mylist5)
复制代码
output
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
复制代码
dict.clear()
dict1 = {'key1':1, 'key2':2}
dict1.clear()
print(dict1)
复制代码
output
{}
复制代码
使用 pop 方法来指定删除字典中的某一项
dict1 = {'key1':1, 'key2':2}
d1 = dict1.pop('key1')
print(d1)
print(dict1)
复制代码
output
1
{'key2': 2}
复制代码
dict2 = {'key1':1, 'key2':2}
mykey = [key for key in dict2]
print(mykey)
myvalue = [value for value in dict2.values()]
print(myvalue)
key_value = [(k, v) for k, v in dict2.items() ]
print(key_value)
复制代码
output
['key1', 'key2']
[1, 2]
[('key1', 1), ('key2', 2)]
复制代码
用于建立一个新字典,以序列中元素作字典的键,value 为字典全部键对应的初始值
keys = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
dict.fromkeys(keys, 0)
复制代码
output
{'zhangfei': 0, 'guanyu': 0, 'liubei': 0, 'zhaoyun': 0}
复制代码
计算机在最初的设计中,采用了8个比特(bit)做为一个字节(byte)的方式。一个字节能表示的最大的整数就是255(二进制11111111=十进制255),若是要表示更大的整数,就必须用更多的字节。 最先,计算机只有 ASCII 编码,即只包含大小写英文字母、数字和一些符号,这些对于其余语言,如中文,日文显然是不够用的。后来又发明了Unicode,Unicode把全部语言都统一到一套编码里,这样就不会再有乱码问题了。当须要保存到硬盘或者须要传输的时候,就转换为UTF-8编码。UTF-8 是隶属于 Unicode 的可变长的编码方式。 在 Python 中,以 Unicode 方式编码的字符串,可使用 encode() 方法来编码成指定的 bytes,也能够经过 decode() 方法来把 bytes 编码成字符串。
encode
"中文".encode('utf-8')
复制代码
output
b'\xe4\xb8\xad\xe6\x96\x87'
复制代码
decode
b'\xe4\xb8\xad\xe6\x96\x87'.decode('utf-8')
复制代码
output
'中文'
复制代码
a = 1
b = 2
a, b = b, a
print(a, b)
复制代码
output
2 1
复制代码
先来看个例子
c = d = [1,2]
e = [1,2]
print(c is d)
print(c == d)
print(c is e)
print(c == e)
复制代码
output
True
True
False
True
复制代码
== 是比较操做符,只是判断对象的值(value)是否一致,而 is 则判断的是对象之间的身份(内存地址)是否一致。对象的身份,能够经过 id() 方法来查看。
id(c)
id(d)
id(e)
复制代码
output
188748080
288748080
388558288
复制代码
能够看出,只有 id 一致时,is 比较才会返回 True,而当 value 一致时,== 比较就会返回 True
位置参数,默认参数,可变参数,关键字参数
容许咱们在调用函数的时候传入多个实参
def test(*arg, **kwarg):
if arg:
print("arg:", arg)
if kwarg:
print("kearg:", kwarg)
test('ni', 'hao', key='world')
复制代码
output
arg: ('ni', 'hao')
kearg: {'key': 'world'}
复制代码
能够看出, *arg会把位置参数转化为tuple **kwarg会把关键字参数转化为dict
sum(range(1, 101))
复制代码
import time
import datetime
print(datetime.datetime.now())
print(time.strftime('%Y-%m-%d %H:%M:%S'))
复制代码
output
12019-06-07 18:12:11.165330
22019-06-07 18:12:11
复制代码
简单列举10条:
尽可能以避免单独使用小写字母'l',大写字母'O',以及大写字母'I'等容易混淆的字母。
函数命名使用所有小写的方式,可使用下划线。
常量命名使用所有大写的方式,可使用下划线。
使用 has 或 is 前缀命名布尔元素,如: is_connect = True; has_member = False
不要在行尾加分号, 也不要用分号将两条命令放在同一行。
不要使用反斜杠链接行。
顶级定义之间空2行, 方法定义之间空1行,顶级定义之间空两行。
若是一个类不继承自其它类, 就显式的从 object 继承。
内部使用的类、方法或变量前,需加前缀'_'代表此为内部使用的。
要用断言来实现静态类型检测。
import copy
list1 = [1, 2, 3, [1, 2]]
list2 = copy.copy(list1)
list2.append('a')
list2[3].append('a')
print(list1, list2)
复制代码
output
[1, 2, 3, [1, 2, 'a']] [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')
print(list1, list3)
复制代码
output
[1, 2, 3, [1, 2]] [1, 2, 3, [1, 2, 'a'], 'a']
复制代码
深拷贝使得两个列表彻底独立开来,每个列表的操做,都不会影响到另外一个。
def num():
return [lambda x:i*x for i in range(4)]
print([m(1) for m in num()])
复制代码
output
[3, 3, 3, 3]
复制代码
经过运行结果,能够看出 i 的取值为3,很神奇
可变数据类型:list、dict、set
不可变数据类型:int/float、str、tuple
for i in range(1, 10):
for j in range(1, i+1):
print("%s*%s=%s " %(i, j, i*j), end="")
print()
复制代码
output
11*1=1
22*1=2 2*2=4
33*1=3 3*2=6 3*3=9
44*1=4 4*2=8 4*3=12 4*4=16
55*1=5 5*2=10 5*3=15 5*4=20 5*5=25
66*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
77*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
88*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
99*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
复制代码
print 函数,默认是会换行的,其有一个默认参数 end,若是像例子中,咱们把 end 参数显示的置为"",那么 print 函数执行完后,就不会换行了,这样就达到了九九乘法表的效果了。
filter 函数用于过滤序列,它接收一个函数和一个序列,把函数做用在序列的每一个元素上,而后根据返回值是True仍是False决定保留仍是丢弃该元素。
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(filter(lambda x: x%2 == 1, mylist))
复制代码
output
[1, 3, 5, 7, 9]
复制代码
保留奇数列表
map 函数传入一个函数和一个序列,并把函数做用到序列的每一个元素上,返回一个可迭代对象
mylist = [1, 2, 3, 4, 5, 6, 7, 8, 9]
list(map(lambda x: x*2, mylist))
复制代码
output
[2, 4, 6, 8, 10, 12, 14, 16, 18]
复制代码
reduce 函数用于递归计算,一样须要传入一个函数和一个序列,并把函数和序列元素的计算结果与下一个元素进行计算。
from functools import reduce
reduce(lambda x, y: x+y, range(101))
复制代码
output
15050
复制代码
能够看出,上面的三个函数与匿名函数相结合使用,能够写出强大简洁的代码。
match()函数只检测要匹配的字符是否是在 string 的开始位置匹配,search()会扫描整个 string 查找匹配
__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__函数。
a, b = 1, 2
# 若果 a>b 成立 就输出 a-b 不然 a+b
h = a-b if a>b else a+b
复制代码
output
13
复制代码
print(random.random())
print(random.randint(1, 100))
print(random.uniform(1,5))
复制代码
output
10.03765019937131564
218
31.8458555362279228
复制代码
zip() 函数将可迭代的对象做为参数,将对象中对应的元素打包成一个个元组,而后返回由这些元组组成的列表
list1 = ['zhangfei', 'guanyu', 'liubei', 'zhaoyun']
list2 = [0, 3, 2, 4]
list(zip(list1, list2))
复制代码
output
[('zhangfei', 0), ('guanyu', 3), ('liubei', 2), ('zhaoyun', 4)]
复制代码
range([start,] stop[, step]),根据 start 与 stop 指定的范围以及 step 设定的步长,生成一个序列。 而 xrange 生成一个生成器,能够很大的节约内存。
开文件在进行读写的时候可能会出现一些异常情况,若是按照常规的 f.open 写法,咱们须要 try,except,finally,作异常判断,而且文件最终无论遇到什么状况,都要执行 finally f.close() 关闭文件,with 方法帮咱们实现了 finally 中 f.close。
Python 中默认是贪婪匹配模式。
贪婪模式:正则表达式通常趋向于最大长度匹配。
非贪婪模式:在整个表达式匹配成功的前提下,尽量少的匹配。
例如:
def test(L=[]):
L.append('test')
print(L)
复制代码
output
test() # ['test']
test() # ['test', 'test']
复制代码
默认参数是一个列表,是可变对象[],Python 在函数定义的时候,默认参数 L 的值就被计算出来了,是[],每次调用函数,若是 L 的值变了,那么下次调用时,默认参数的值就已经再也不是[]了。
mystr = '1,2,3'
mystr.split(',')
复制代码
output
['1', '2', '3']
复制代码
mylist = ['1', '2', '3']
list(map(lambda x: int(x), mylist))
复制代码
output
[1, 2, 3]
复制代码
mylist = [1, 2, 3, 4, 5, 5]
list(set(mylist))
复制代码
from collections import Counter
mystr = 'sdfsfsfsdfsd,were,hrhrgege.sdfwe!sfsdfs'
Counter(mystr)
复制代码
output
Counter({'s': 9,
'd': 5,
'f': 7,
',': 2,
'w': 2,
'e': 5,
'r': 3,
'h': 2,
'g': 2,
'.': 1,
'!': 1})
复制代码
[x for x in range(10) if x%2 == 1]
复制代码
output
[1, 3, 5, 7, 9]
复制代码
list1 = [[1,2],[3,4],[5,6]]
[j for i in list1 for j in i]
复制代码
output
[1, 2, 3, 4, 5, 6]
复制代码
二分查找算法也称折半查找,基本思想就是折半,对比大小后再折半查找,必须是有序序列才可使用二分查找。 递归算法
def binary_search(data, item):
# 递归
n = len(data)
if n > 0:
mid = n // 2
if data[mid] == item:
return True
elif data[mid] > item:
return binary_search(data[:mid], item)
else:
return binary_search(data[mid+1:], item)
return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 999)
复制代码
非递归算法
def binary_search(data, item):
# 非递归
n = len(data)
first = 0
last = n - 1
while first <= last:
mid = (first + last)//2
if data[mid] == item:
return True
elif data[mid] > item:
last = mid - 1
else:
first = mid + 1
return False
list1 = [1,4,5,66,78,99,100,101,233,250,444,890]
binary_search(list1, 99)
复制代码
字典转 json
import json
dict1 = {'zhangfei':1, "liubei":2, "guanyu": 4, "zhaoyun":3}
myjson = json.dumps(dict1)
myjson
复制代码
output
'{"zhangfei": 1, "liubei": 2, "guanyu": 4, "zhaoyun": 3}'
复制代码
json 转字典
mydict = json.loads(myjson)
mydict
复制代码
output
{'zhangfei': 1, 'liubei': 2, 'guanyu': 4, 'zhaoyun': 3}
复制代码
import random
td_list=[i for i in range(10)]
print("列表推导式", td_list, type(td_list))
ge_list = (i for i in range(10))
print("生成器", ge_list)
dic = {k:random.randint(4, 9)for k in ["a", "b", "c", "d"]}
print("字典推导式",dic,type(dic))
复制代码
output
列表推导式 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] <class 'list'>
生成器 <generator object <genexpr> at 0x0139F070>
字典推导式 {'a': 6, 'b': 5, 'c': 8, 'd': 9} <class 'dict'>
复制代码
read 读取整个文件
readline 读取下一行,使用生成器方法
readlines 读取整个文件到一个迭代器以供咱们遍历
list2 = [1, 2, 3, 4, 5, 6]
random.shuffle(list2)
print(list2)
复制代码
output
[4, 6, 5, 1, 2, 3]
复制代码
str1 = 'luobodazahui'
str1[::-1]
复制代码
output
'iuhazadoboul'
复制代码
__foo__
:一种约定,Python 内部的名字,用来区别其余用户自定义的命名,以防冲突,就是例如__init__()和__del__()及__call__()这些特殊方法。
_foo
:一种约定,用来指定变量私有。不能用 from module import * 导入,其余方面和公有变量同样访问。
__foo
:这个有真正的意义:解析器用_classname__foo 来代替这个名字,以区别和其余类相同的命名,它没法直接像公有成员同样随便访问,经过对象名._类名__xxx 这样的方式能够访问。
a. 在 python 里凡是继承了 object 的类,都是新式类
b. Python3 里只有新式类
c. Python2 里面继承 object 的是新式类,没有写父类的是经典类
d. 经典类目前在 Python 里基本没有应用
a. 同时支持单继承与多继承,当只有一个父类时为单继承,当存在多个父类时为多继承。
b. 子类会继承父类全部的属性和方法,子类也能够覆盖父类同名的变量和方法。
c. 在继承中基类的构造(__init__()
)方法不会被自动调用,它须要在其派生类的构造中专门调用。
d. 在调用基类的方法时,须要加上基类的类名前缀,且须要带上 self 参数变量。区别于在类中调用普通函数时并不须要带上 self 参数。
super() 函数是用于调用父类(超类)的一个方法。
class A():
def funcA(self):
print("this is func A")
class B(A):
def funcA_in_B(self):
super(B, self).funcA()
def funcC(self):
print("this is func C")
ins = B()
ins.funcA_in_B()
ins.funcC()
复制代码
output
this is func A
this is func C
复制代码
主要分为实例方法、类方法和静态方法
实例方法:
定义:第一个参数必须是实例对象,该参数名通常约定为“self”,经过它来传递实例的属性和方法(也能够传类的属性和方法);
调用:只能由实例对象调用。
类方法:
定义:使用装饰器@classmethod。第一个参数必须是当前类对象,该参数名通常约定为“cls”,经过它来传递类的属性和方法(不能传实例的属性和方法);
调用:实例对象和类对象均可以调用。
静态方法:
定义:使用装饰器@staticmethod。参数随意,没有“self”和“cls”参数,可是方法体中不能使用类或实例的任何属性和方法;
调用:实例对象和类对象均可以调用。
静态方法是类中的函数,不须要实例。静态方法主要是用来存放逻辑性的代码,主要是一些逻辑属于类,可是和类自己没有交互。即在静态方法中,不会涉及到类中的方法和属性的操做。能够理解为将静态方法存在此类的名称空间中。 类方法是将类自己做为对象进行操做的方法。他和静态方法的区别在于:无论这个方式是从实例调用仍是从类调用,它都用第一个参数把类传递过来。
与类和实例无绑定关系的 function 都属于函数(function) 与类和实例有绑定关系的 function 都属于方法(method)
普通函数:
def func1():
pass
print(func1)
复制代码
output
<function func1 at 0x01379348>
复制代码
类中的函数:
class People(object):
def func2(self):
pass
@staticmethod
def func3():
pass
@classmethod
def func4(cls):
pass
people = People()
print(people.func2)
print(people.func3)
print(people.func4)
复制代码
output
<bound method People.func2 of <__main__.People object at 0x013B8C90>>
<function People.func3 at 0x01379390>
<bound method People.func4 of <class '__main__.People'>>
复制代码
isinstance() 函数来判断一个对象是不是一个已知的类型,相似 type()。
区别:
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
class A(object):
pass
class B(A):
pass
a = A()
b = B()
print(isinstance(a, A))
print(isinstance(b, A))
print(type(a) == A)
print(type(b) == A)
复制代码
output
True
True
True
False
复制代码
单例模式:主要目的是确保某一个类只有一个实例存在。
工厂模式:包涵一个超类,这个超类提供一个抽象化的接口来建立一个特定类型的对象,而不是决定哪一个对象能够被建立。
import os
print(os.listdir('.'))
复制代码
# 1到5组成的互不重复的三位数
k = 0
for i in range(1, 6):
for j in range(1, 6):
for z in range(1, 6):
if (i != j) and (i != z) and (j != z):
k += 1
if k%6:
print("%s%s%s" %(i, j, z), end="|")
else:
print("%s%s%s" %(i, j, z))
复制代码
output
1123|124|125|132|134|135
2142|143|145|152|153|154
3213|214|215|231|234|235
4241|243|245|251|253|254
5312|314|315|321|324|325
6341|342|345|351|352|354
7412|413|415|421|423|425
8431|432|435|451|452|453
9512|513|514|521|523|524
10531|532|534|541|542|543
复制代码
str1 = " hello nihao "
str1.strip()
复制代码
output
'hello nihao'
复制代码
str2 = "hello you are good"
print(str2.replace(" ", ""))
"".join(str2.split(" "))
复制代码
output
helloyouaregood
'helloyouaregood'
复制代码
面试题系列第一部分就到这里了,咱们下次见!
欢迎关注个人微信公众号--萝卜大杂烩,或者扫描下方的二维码,你们一块儿交流,学习和进步!