Python基础
一、文件操作
1、有一个jsonline格式的文件file.txt 大小约10k
def get_lines():
with open('file.txt', 'rb') as f:
return f.readlines()
if __name__ == '__main__':
for e in get_lines():
process(e) # 处理每一行的数据
现在要处理一个大小为10G的文件,但是内存只有4G,如果在只修改get_lines
函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有哪些?
def get_lines():
with open('file.txt', 'rb') as f:
for i in f:
yield i
要考虑的问题有:内存只有4G无法一次性读入10G文件,需要分批读入数据要记录每次读入数据的位置,分批每次读取数据的大小,太小会在读取操作上花费过多的时间。
2、补充缺失的代码
def print_directory_contents(sPath):
"""
这个函数接收文件夹的名称作为输入参数
返回该文件夹中文件的路径
以及其包含文件夹中文件的路径
"""
import os
for s_child in os.listdir(s_path):
s_child_path = os.path.join(s_path, s_child)
if os.path.isdir(s_child_path):
print_directory_contents(s_child_path)
else:
print(s_child_path)
二、模块与包
3、输入日期,判断这一天是这一年的第几天?
import datetime
def dayofyear():
year = input("请输入年份: ")
month = input("请输入月份: ")
day = input("请输入天: ")
date1 = datetime.date(year=int(year),month=int(month),day=int(day))
date2 = datetime.date(year=int(year),month=1,day=1)
return (date1-date2).days+1
4、打乱一个排序号的list对象alist?
import random
alist = [1,2,3,4,5]
random.shuffle(alist)
print(alist)
三、数据类型
5、现有字典 d = {‘a’: 24, ‘g’: 52, ‘i’: 12, ‘k’: 33}, 请按value值进行排序?
sorted(d.items(),key=lambda x:x[1])
## x[0]代表用key进行排序;x[1]代表用value进行排序。
6、字典推导式
d = {key:value for (key,value) in iterable}
7、请反转字符串 “aStr”?
print("aStr"[::-1])
8、将字符串 “k:1 |k1:2|k2:3|k3:4”,处理成字典 {k:1,k1:2,…}
str1 = "k:1|k1:2|k2:3|k3:4"
def str2dict(str1):
dict1 = {}
for iterms in str1.split('|'):
key,value = iterms.split(':')
dict1[key] = value
return dict1
#字典推导式
d = {k:int(v) for t in str1.split("|") for k, v in (t.split(":"), )}
9、请按alist中元素的age由大到小排序
alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}]
def sort_by_age(list1):
return sorted(alist,key=lambda x:x['age'],reverse=True)
10、下面代码的输出结果将是什么?
list = ['a','b','c','d','e']
print(list[10:])
代码将输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致Bug很难被追踪到。
11、写一个列表生成式,产生一个公差为11的等差数列
print([x*11 for x in range(10)])
12、给定两个列表,怎么找出他们相同的元素和不同的元素?
list1 = [1,2,3]
list2 = [3,4,5]
set1 = set(list1)
set2 = set(list2)
print(set1 & set2)
print(set1 ^ set2)
13、请写出一段python代码实现删除list里面的重复元素?
l1 = ['b','c','d','c','a','a']
l2 = list(set(l1))
print(l2)
用list类的sort方法:
l1 = ['b','c','d','c','a','a']
l2 = sorted(set(l1),key=l1.index)
print(l2)
l1 = ['b','c','d','c','a','a']
l2 = []
for i in l1:
if not i in l2:
l2.append(i)
print(l2)
14、给定两个list A,B ,请用找出A,B中相同与不同的元素
A,B 中相同元素: print(set(A)&set(B))
A,B 中不同元素: print(set(A)^set(B))
企业面试题
15、python新式类和经典类的区别
- a. 在python里凡是继承了object的类,都是新式类
- python3里只有新式类
- python2里面继承object的是新式类,没有写父类的是经典类
- 经典类目前在python里基本没有什么应用
- 保持class与type的统一对新式类的实例执行a._ _ class _ _ 与type(a)的结果是一致的,对于旧式类来说就不一样了。
- 对于多重继承的属性搜索顺序不一样,新式类采用C3算法广度优先搜索,旧类采用深度优先搜索。
16、python中内置的数据结构有几种?
- a、整型 int、长整型 long、浮点型 float、复数 complex
- b、字符串 str、列表list、元组 tuple
- c、字典 dict、集合 set
- d、python3 中没有long,只有无限精度的 int
17、python如何实现单例模式?请写出两种实现方式?
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。
__new__()
在__init__()
之前被调用,用于生成实例对象。利用这个方法和类的属性的特点可以实现设计模式的单例模式。单例模式是指创建唯一对象,单例模式设计的类只能实例 这个绝对常考啊.绝对要记住1~2个方法,当时面试官是让手写的.
1 使用__new__()
方法
class Singleton(object):
def __new__(cls, *args, **kwargs):
if not hasattr(cls, '_instance'):
orig = super(Singleton, cls)
cls._instance = orig.__new__(cls, *args, **k wargs)
return cls._instance
class MyClass(Singleton):
a = 1
2 共享属性
创建实例时把所有实例的__dict__
指向同一个字典,这样它们具有相同的属性和方法.
class Borg(object):
_state = {}
def __new__(cls, *args, **kw):
ob = super(Borg, cls).__new__(cls, *args, **kw)
ob.__dict__ = cls._state
return ob
class MyClass2(Borg):
a = 1
3 装饰器
def singleton(cls):
instances = {}
def wrapper(*args, **kwargs):
if cls not in instances:
instances[cls] = cls(*args, **kwargs)
return instances[cls]
return wrapper
@singleton
class Foo(object):
pass
foo1 = Foo()
foo2 = Foo()
print(foo1 is foo2) # True
18、反转一个整数,例如 -123 --> -321
class Solution(object):
def reverse(self, x):
if -10 < x < 10:
return x
str_x = str(x)
if str_x[0] != '-':
str_x = str_x[::-1]
x = int(str_x)
else:
str_x = str_x[1:][::-1]
x = int(str_x)
x = -x
return x if -2147483648<x<2147483647 else 0
if __name__ == '__main__':
s = Solution()
reverse_int = s.reverse(-120)
print(reverse_int)
19、设计实现遍历目录与子目录,抓取.pyc 文件
import os
def pick(obj):
if obj.endswith(".pyc"):
print(obj)
def scan_path(ph):
file_list = os.listdir(ph)
for obj in file_list:
if os.path.isfile(obj):
pick(obj)
elif os.path.isdir(obj):
scan_path(obj)
if __name__=='__main__':
path = input('输入目录')
scan_path(path)
20、一行代码实现1-100之和
count = sum(range(1, 101))
print(count)
21、Python-遍历列表时删除元素的正确做法
遍历在新在列表操作,删除时在原来的列表操作
a = [1,2,3,4,5,6,7,8]
print(id(a))
print(id(a[:]))
for i in a[:]:
if i>5:
pass
else:
a.remove(i)
print(a)
print('-----------')
print(id(a))
#filter
a=[1,2,3,4,5,6,7,8]
b = filter(lambda x: x>5,a)
print(list(b))
列表解析
a=[1,2,3,4,5,6,7,8]
b = [i for i in a if i>5]
print(b)
倒序删除 因为列表总是‘向前移’,所以可以倒序遍历,即使后面的元素被修改了,还没有被遍历的元素和其坐标还是保持不变的
a = [1, 2, 3, 4, 5, 6, 7, 8]
print(id(a))
for i in range(len(a) - 1, -1, -1):
if a[i] > 5:
pass
else:
a.remove(a[i])
print(id(a))
print('------------')
print(a)
22、字符串的操作题目
全字母短句 PANGRAM 是包含所有英文字母的句子,比如:A QUICK BROWN FOX JUMPS OVER THE LAZY DOG. 定义并实现一个方法 get_missing_letter, 传入一个字符串采纳数,返回参数字符串变成一个 PANGRAM 中所缺失的字符。应该忽略传入字符串参数中的大小写,返回应该都是小写字符并按字母顺序排序(请忽略所有非 ACSII 字符)
下面示例是用来解释,双引号不需要考虑:
(0)输入: “A quick brown for jumps over the lazy dog”
返回: “”
(1)输入: “A slow yellow fox crawls under the proactive dog”
返回: “bjkmqz”
(2)输入: “Lions, and tigers, and bears, oh my!”
返回: “cfjkpquvwxz”
(3)输入: “”
返回:“abcdefghijklmnopqrstuvwxyz”
方法一
def get_missing_letter(a):
s1 = set('abcdefghijklmnopqrstuvwxyz')
s2 = set(a.lower())
ret = ''.join(sorted(s2 - s1))
return res
print(get_missing_letter("python"))
方法二
import string
class Solution(object):
def __init__(self):
self.all_ele = set(string.ascii_lowercase)
def get_missing_letter(self, str_input: str) -> str:
# global all_ele
diff_str = set(str_input.lower())
res = self.all_ele - diff_str #if ' ' not in diff_str else self.all_ele - diff_str - {' '}
return sorted(res)
S = Solution()
print(S.get_missing_letter(""))
23、可变类型和不可变类型
1、可变类型有list、dict, 不可变类型有string, number, tuple
2、当进行修改操作时,可变类型传递的是内存中的地址,也就是说,直接修改内存中的值,并没有开辟新的内存
3、不可变类型被改变时,平没有改变原内存中的地址,而是开辟一块新的内存,将原地址中的值复制过去,对这块新开辟的内存中的值进行操作。
24、 is 和 == 有什么区别?
is: 比较的是两个对象的id值是否相等,也就是比较两对象是否是同一个 实例对象,是否指向同一个内存地址
==:比较的是两个对象的内容/值是否相等,默认会调用对象的equ()方法
25、求列表所有奇数并构造新的列表
a= [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
res = [i for i in a if i % 2 != 0]
print(res)
26、用一行python代码写出1 + 2 + 3 + 10248
from functools import reduce
#1.使用sum内置求和函数
num = sum([1,2,3,10248])
print(num)
#2.reduce 函数
num1 = reduce(lambda x,y :x+y,[1,2,3,10248])
print(num1)
27、Python中的变量的作用域?(变量查找顺序)
函数作用域的LEGB顺序
1.什么是LEGB?
L: local 函数内部作用域
E: enclosing 函数内部与内嵌函数之间
G: global 全局作用域
B: build-in 内置作用
python在函数里面的查找分为4种,称之为LEGB,也正是按照这是顺序来查找的
28、字符串 "123"
转换为 123
, 不使用内置api, 例如:int()
方法一: 利用 str
函数
def atoi(s):
num = 0
for v in s:
for j in range(10):
if v == str(j):
num = num * 10 + j
return num
方法二: 利用 ord
函数
def atoi(s):
num = 0
for v in s:
num = num * 10 + ord(v) - ord('0')
return num
方法三: 利用 eval
函数
def atoi(s):
num = 0
for v in s:
t = "%s * 1" % v
n = eval(t)
num = num * 10 + n
return num
方法四: 结合方法二,使用 reduce,一行解决
from functools import reduce
def atoi(s):
return reduce(lambda num, v: num * 10 + ord(v) - ord('0'), s, 0)
29.Given an array of integers
给定一个整数数组和一个目标值,找出数组中和为目标值的两个数。你可以假设每个输入只对应一种答案,且同样的元素不能被重复利用。示例:给定nums = [2,7,11,15],target=9 因为 nums[0]+nums[1] = 2+7 =9,所以返回[0,1]
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
h = {}
for ind, num in enumerate(nums):
n = target - num
if n not in h:
h[num] = ind
else:
return [h[n], ind]
30、python代码实现删除一个list里面的元素
def distFunc1(a):
"""使用集合去重"""
a = list(set(a))
print(a)
def distFunc2(a):
"""将一个列表的数据取出放到另一个列表中,中间作判断"""、
list = []
for i in a:
if i not in list:
list.append(i)
list.sort()
return list
def distFunc3(a):
"""使用字典"""
b = {}
b = b.fromkeys(a)
c = list(b.keys())
print(c)
if __name__ == "__main__":
a = [1,2,4,2,4,5,7,10,5,5,7,8,9,0,3]
distFunc1(a)
distFunc2(a)
distFunc3(a)
31、统计一个文本中单词频次最高的10个单词?
import re
# 方法一
def test(filepath):
distone = {}
with open(filepath) as f:
for line in f:
line = re.sub("\W+", " ", line)
lineone = line.split()
for keyone in lineone:
if not distone.get(keyone):
distone[keyone] = 1
else:
distone[keyone] += 1
num_ten = sorted(distone.items(), key=lambda x:x[1], reverse=True)[:10]
num_ten =[x[0] for x in num_ten]
return num_ten
# 方法二
# 使用 built-in 的 Counter 里面的 most_common
import re
from collections import Counter
def test2(filepath):
with open(filepath) as f:
return list(map(lambda c: c[0], Counter(re.sub("\W+", " ", f.read()).split()).most_common(10)))
32、请写出一个函数满足一下条件
该函数的输入是一个仅包含数字的list,输出一个新的list,其中每一个元素要满足以下条件:
1、该元素是偶数
2、该元素在原list中是在偶数的位置(index是偶数)
def num_list(num):
return [i for i in num if i %2 ==0 and num.index(i)%2==0]
num = [0,1,2,3,4,5,6,7,8,9,10]
result = num_list(num)
print(result)
33、使用单一的列表生成式来产生一个新的列表
list_data = [1, 2, 5, 8, 10, 3, 18, 6, 20]
res = [x for x in list[::2] if x % 2 == 0]
print(res)
34、用一行代码生成[1,4,9,16,25,36,49,64,81,100]
[x ** 2 for x in range(1, 11)]
35、输入某年某月某日,判断这一天是这一年的第几天?
import datetime
y = int(input("请输入4位数字的年份:"))
m = int(input("请输入月份:"))
d = int(input("请输入是哪一天"))
targetDay = datetime.date(y,m,d)
dayCount = targetDay - datetime.date(targetDay.year -1,12,31)
print("%s是 %s年的第%s天。"%(targetDay,y,dayCount.days))
36、两个有序列表,L1、L2,对这两个列表进行合并,不可使用extend
class Solution(object):
def merge(self, list1, list2):
mege_list, j1, j2 = [], 0, 0
len_1, len_2 = len(list1), len(list2)
while j1 < len_1 or j2 < len_2:
if j2 >= len_2 or (j1 < len_1 and list1[j1] < list2[j2]) :
mege_list.append(list1[j1])
j1 += 1
else:
mege_list.append(list2[j2])
j2 += 1
return mege_list
S = Solution()
l1 = [1, 3, 5, 7, 9]
l2 = [2, 4, 6, 8, 9]
print(S.merge(l1, l2))
def loop_merge_sort(l1,l2):
tmp = []
while len(l1)>0 and len(l2)>0:
if l1[0] <l2[0]:
tmp.append(l1[0])
del l1[0]
else:
tmp.append(l2[0])
del l2[0]
while len(l1)>0:
tmp.append(l1[0])
del l1[0]
while len(l2)>0:
tmp.append(l2[0])
del l2[0]
return tmp
37、python:remove,pop和del方法的区别
这三种方法都是list的删除方法,其中remove是针对可变列表的元素进行搜索删除,而pop和del是针对可变列表的下标进行搜索删除。具体区别如下:
1. remove
remove(item)方法是直接对可变序中的元素进行检索删除,返回的是删除后的列表,不返回删除值(返回None)
>>>list1=[1,3,6,7,8]
>>>print list1.remove(3) #对列表元素进行搜索删除,而不是下表
>>>print list1
None
[1,6,7,8]123456
2. pop
pop(index)方法是对可变序列中元素下标进行检索删除,返回删除值
>>>list1=[1,3,6,7,8]
>>>print list1.pop(3),#对列表下表进行检索删除
>>>print list1
7
[1,3,6,8]
>>>dict1={'Abby':21,'Bob':22,'cindy':21}
>>>print dict1.pop(1)
>>>print dict1
123456789101112
3. del
del(list[index])方法是对可变序列中元素下边进行检索删除,不返回删除值
>>>list1=[1,3,6,7,8]
>>>del list[3]
>>>print list1
[1.3,6,8]
>>> a = [1, 3, 6, 7, 9]
>>> a.remove(3)
>>> a
[1, 6, 7, 9]
>>>
>>>
>>>
>>>
>>>
>>> A = [1, 3, 6, 7, 9]
>>> print(A.remove(3))
None
>>> A
[1, 6, 7, 9]
>>>
>>>
>>> A = [1, 3, 6, 7, 9]
>>> print(A.pop(1))
3
>>> A
[1, 6, 7, 9]
>>>
>>>
>>> A = [1, 3, 6, 7, 9]
>>> del A[1]
>>> A
[1, 6, 7, 9]
38、给定一个任意长度的数组,实现一个函数
让所有奇数都在偶数前面,而且奇数升序排列,偶数降序排序,如字符串’1982376455’,变成’1355798642’。
# 方法一
def func1(l):
if isinstance(l, str):
l = [int(i) for i in l]
l.sort(reverse=True)
for i in range(len(l)):
if l[i] % 2 > 0:
l.insert(0, l.pop(i))
print(''.join(str(e) for e in l))
# 方法二
def func2(l):
print("".join(sorted(l, key=lambda x: int(x) % 2 == 0 and 20 - int(x) or int(x))))
class Solution(object):
def list_sort(self, str_list: str)->str:
res1, res2 = [], []
for i in str_list:
temp = int(i)
if temp % 2 == 0:
res2.append(str(temp))
else: res1.append(str(temp))
res1.sort()
res2.sort(reverse=True)
res1 += res2
return "".join(res1)
A = Solution()
print(A.list_sort('1982376455'))
38、写一个函数找出一个整数数组中,第二大的数
class Solution(object):
def find_second_large_num_1(self, num_list):
tmp_list = sorted(num_list)
print("方法一\nSecond_large_num is :", tmp_list[-2])
def find_second_large_num_2(self, num_list):
one = num_list[0]
two = num_list[0]
for i in range(1, len(num_list)):
if num_list[i] > one:
two = one
one = num_list[i]
elif num_list[i] > two:
two = num_list[i]
print("方法二\nSecond_large_num is :", two)
def find_second_large_num_3(self, num_list):
from functools import reduce
num = reduce(lambda ot, x: ot[1] < x and (ot[1], x) or ot[0] < x and (x, ot[1]) or ot, num_list, (0, 0))[0]
print("方法三\nSecond_large_num is :", num)
if __name__ == '__main__':
A = Solution()
# assume the list has 2 distinct elements
num_list = [0, 0, 11]
try:
num_list = list(set(num_list))
A.find_second_large_num_1(num_list)
A.find_second_large_num_2(num_list)
A.find_second_large_num_3(num_list)
except IndexError:
print('Please enter at least 2 different elements')
except:
print('enter right list')
39、阅读一下代码他们的输出结果是什么?
def multi():
return [lambda x : i*x for i in range(4)]
print([m(3) for m in multi()])
正确答案是[9,9,9,9],而不是[0,3,6,9]产生的原因是Python的闭包的后期绑定导致的,这意味着在闭包中的变量是在内部函数被调用的时候被查找的,因为,最后函数被调用的时候,for循环已经完成, i 的值最后是3,因此每一个返回值的i都是3,所以最后的结果是[9,9,9,9]
40、统计一段字符串中字符出现的次数
# 方法一
def count_str(str_data):
"""定义一个字符出现次数的函数"""
dict_str = {}
for i in str_data:
dict_str[i] = dict_str.get(i, 0) + 1
return dict_str
dict_str = count_str("AAABBCCAC")
str_count_data = ""
for k, v in dict_str.items():
str_count_data += k + str(v)
print(str_count_data)
# 方法二
from collections import Counter
print("".join(map(lambda x: x[0] + str(x[1]), Counter("AAABBCCAC").most_common())))
41、super函数的具体用法和场景
https://python3-cookbook.readthedocs.io/zh_CN/latest/c08/p07_calling_method_on_parent_class.html