• Day 23:Python 中的一些高频面试题及解答小记


    #!/usr/bin/env python
    # coding: utf-8
    
    # 1)
    # 一行代码生成 [1, 3, 5, 7, 9, 11, 13, 15, 17, 19]
    # 找规律
    lst = [2*_ -1 for _ in range(1,11)]
    lst
      
    # 2) # 生成等差数列 # 用range步长就可以 lst = list(range(10,100,5)) lst
    # 3) # 一行代码求 1 到 10000 内整数和 # sum ret = sum(range(10000)) ret # 4) 累积和 from functools import reduce ret = reduce(lambda x,y: x+y,range(10000)) ret
    # 5) # 打乱一个列表 # random.shuffle() import random a = list(range(10)) print(type(a)) random.shuffle(a) print(a) # 6) # 字典按 value 排序并返回新字典 or 按 key 排序 # python 有内置sorted函数,支持选择排序指标 d= {'a':12,'b':50,'c':1,'d':20} d = dict(sorted(d.items(),key=lambda item:item[1])) d = dict(sorted(d.items(),key=lambda item:item[0])) d
    # 7) # 如何删除 list 里重复元素,并保证元素顺序不变 a = [3,2,2,2,1,3] # 既然都用python了,怎么高效怎么来 def del_duplicated(lst): ret = [] for _ in lst: if _ not in ret: ret.append(_) return ret del_duplicated(a) # 8) # 找出两个列表的相同元素和不同元素? # 那就是取交集,和交集的补集 # 用集合的intersection求交方法和difference求差方法很快啊union并集方法 a = [3,2,2,2,1,3] b = [1,4,3,4,5] def ans(lst_1, lst_2): set_1,set_2 = set(lst_1),set(lst_2) intersection = set_1.intersection(set_2) complement = set_1.difference(set_2).union(set_2.difference(set_1)) return intersection, complement c,d = ans(a,b) print(a,b,c,d) # 9) # 字符串处理成字典 输入串 "k0:10|k1:2|k2:11|k3:5",输出字典 {k0:10,k1:2,...} # 涉及字符串的分割 split方法 # 先分| 再按 : 分 m = map(lambda x:x.split(':'),'k0:10|k1:2|k2:11|k3:5'.split('|')) ans = {mi[0]:int(mi[1]) for mi in m } ans # 10) # 输入日期,判断这一天是这一年的第几天 # 需要用到time 或是 datetime中的方法 from datetime import datetime def i_day_of_years(y,m,d): return datetime(y,m,d).date().timetuple().tm_yday ret = i_day_of_years(2021,7,11) ret # 11) # 单机 4G 内存,处理 10G 文件的方法? # ans:按行读取,使用生成器函数yield方法以节省内存 也可以一次IO读取多行 Pandas的方法可以实现 def python_read(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line if __name__ == '__main__': g = python_read('写入filename') for c in g: print(c) # process c # 一次IO读入多行 众多参数,更加灵活,参考pd.read_csv() 的各种方法 def pandas_read(filename,sep=',',chunksize=5): reader = pd.read_csv(filename,sep=sep,chunksize=chunksize) while True: try: yield reader.get_chunk() except StopIteration: print('---Done---') break if __name__ == '__main__': g = pandas_read('写入filename',sep="::") for c in g: print(c) # process c # 12) # 统计一个文本中单词频次最高的 10 个单词 # 首先要按行解耦读入文本,然后得到单词,需要分隔字符串,用正则替换掉没用的字符串,保存并做统计,取最高rank的10个单词 from collections import Counter, defaultdict import re def python_read(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line d = defaultdict(int) # 默认生成的字典 def process(line): for word in re.sub('W+'," ",line).split(): # 先匹配任意字母/数字/下划线以外的字符替换成空格,再默认按空格分割 d[word] += 1 for line in python_read('写入filename'): process(line) most_active_word_10 = Counter(d).most_common(10) print(most10) # 13) # 反转一个整数,例如 -12345 --> -54321 # 转成字符逆序再转成int再乘以符号 如果是负的,除去“-”符号再逆序 def reverse_int(x:int): if -10 < x < 10: return x x_str = str(x) def reverse_str(str): return str[::-1] if x_str[0] == "-": temp_str = reverse_str(x_str[1::]) ret = int(temp_str) return -ret return int(reverse_str(x_str)) reverse_int(-531546654) # 14) # 内嵌函数调用 def f(): i = 0 def foo(x): return i*x #foo 使用的两个变量 i 和 x,其中 x 为其形参,i 为 enclosing 域内定义的变量 rtn = [] while i < 3: rtn.append(foo) i += 1 return rtn # 调用函数 f for fs in f(): print(fs(10)) # rtn 添加三个函数 foo,但是并未发生调用。 # 直到执行 fs(10) 时,内嵌函数 foo 才被调用,但是此时的 enclosing 变量 i 取值为 3 # 15) # 函数的正确调用 def foo(filename,a=0,b=1,c=2): print('filename: %s c: %d'%(filename,c)) ''' A foo('.', 10)错误 a被赋值为10 B foo('.', 0,1,10)对 C foo('.',0,1,c=10)对 D foo('.',a=0,1,10)错 关键字参数要在位置参数后面 E foo(filename='.', c=10)对 F foo('.', c=10)对 ''' # 16) # lambda 函数的形参和返回值 def longer(*s): return max(*s, key=lambda x: len(x)) longer({1,3,5,7},{1,5,7},{2,4,6,7,8}) # lambda 函数的形参:s 解包后的元素值,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 三种。 # lambda 函数的返回值为:元素的长度,可能取值为:{1,3,5,7}、{1,5,7}、{2,4,6,7,8} 的长度 4,3,5。 # 17) # 正则匹配负整数 # 小知识 匹配所有负整数,不包括 0。正则表达式:^-[1-9]d*$ """ ^- 表示字符串以 - 开头 [1-9] 表示数字 1 到 9,注意不要写成 d,因为负整数没有以 -0 开头的 d* 表示数字 0 到 9 出现 0 次、1 次或多次 $ 表示字符串以数字结尾 """ import re s = ['-1','-15756','9','-01','10','-'] pat = r'^-[1-9]d*$' rec = re.compile(pat) rs = [i for i in s if rec.match(i)] print(rs) # 结果 # ['-1', '-15756'] # 18) # 正则匹配负浮点数 # 小知识 匹配所有负的浮点数,正则表达式: ^-[1-9]d*.d*|-0.d*[1-9]d*$ # 实例 -0.12 的正则表达式:^-0.d*[1-9]d*$ # 实例 -111.234 的正则表达式:^-[1-9]d*.d*$ # 使用 |,综合两种情况 import re s = ['-1','-1.5756','-0.00','-000.1','-1000.10'] pat = r'^-[1-9]d*.d*|-0.d*[1-9]d*$' rec = re.compile(pat) rs = [i for i in s if rec.match(i)] print(rs) # 结果 # ['-1.5756', '-1000.10'] # 19) # 求出列表中大于 10 的元素 过滤器 # 使用fliter函数,lambda函数 """ def filter_self(function, iterable): return iter([ item for item in iterable if function(item)]) """ # 过滤掉不满足函数 function 的元素,重新返回一个新的迭代器。 a = [15,2,7,20,400,10,9,-15,107] al = list(filter(lambda x: x > 10, a)) al # 20) # map映射函数 # map 函数当含有多个列表时,返回长度为最短列表的长度 m = map(lambda x,y: min(x,y), [5, 1, 3, 4], [3,4,3,2,1]) list(m) # 21) # reduce 函数的输出结果 # reduce实现 规约。 # function函数的参数必须为2,是可迭代对象 iterable 内的连续两项 # 计算过程,从左侧到右侧,依次归约,直到最终为单个值并返回。 from functools import reduce reduce(lambda x,y: x*y+1,[1,2,3,4,5]) # 22) # x = (i for i in range(5)),x 是什么类型 # x 是生成器类型,与for in相结合使用于迭代 x = (i for i in range(5)) for i in x: print(i) # 23) # 可变类型和不可变类型分别列举 3 个 # 可变类型:mutable type,常见的有:list、dict、set、deque队列 等 # 不可变类型:immutable type,常见的有:int、float、str、tuple、frozenset 等 # 小知识:只有不可变类型才能作为字典等的键。 # frozenset冻结集合,一旦创建不允许增删元素 # 24) # is 和 == 有什么区别? # is 标识号 用来判断两个对象的标识号是否相等; # == 对象的值或者内容 用于判断值或内容是否相等,默认是基于两个对象的标识号比较。 #p.s. 也就是说,如果 a is b 为 True 且如果按照默认行为,意味着 a==b 也为 True # 25) # 写一个学生类 Student # 添加一个属性 id,并实现若 id 相等,则认为是同一位同学的功能。 # 重写 __eq__ 方法,若 id 相等,返回 True。 class Student: def __init__(self,id,name): self.id = id self.name = name def __eq__(self,student): return self.id == student.id s1 = Student(10,'xiaoming') s2 = Student(20,'xiaohong') s3 = Student(10,'xiaoming2') s1 == s2 s1 == s3 # 26) # 有什么方法获取类的所有属性和方法? 答:dir(对象) dir(Student) a = [1,2,3] dir(a) # 27) # Python 中如何动态获取和设置对象的属性? 主要问题是 动态 就是说要先判断原来没有的,需要立刻马上增加一个 class Student: def __init__(self,id,name): self.id = id self.name = name def __eq__(self,student): return self.id == student.id # 使用 hasattr 方法,判断实例是否有属性 x: s1 = Student(10,'xiaoming') print(hasattr(s1,'id')) print(hasattr(s1,'age')) # 使用 setattr 动态添加对象的属性,函数原型:<function setattr(obj, name, value, /)> if not hasattr(Student, 'age'): setattr(Student,'age','beijing') print(hasattr(s1,'age')) # 28) # 实现一个按照 2*i+1 自增的迭代器 # 肯定要重写__next__方法或者__iter__ from collections.abc import Iterator class AutoIncreass(Iterator): def __init__(self,init,n): self.init = init self.n = n self.__cal = 0 def __iter__(self): return self def __next__(self): if self.__cal == 0: self.__cal += 1 return self.init while self.__cal < self.n: self.init *= 2 self.init += 1 self.__cal += 1 return self.init raise StopIteration # 返回的是一个迭代器对象,用for in 打印 iter = AutoIncreass(1,10) for i in iter: print(i) # 29) # 实现文件按行读取和操作数据分离功能 # 首先是文件按行读取 ,节省内存,yield函数 # 然后是对读取的这一行数据进行操作 def read_line(filename): with open(filename,'r',encoding='utf-8') as f: for line in f: yield line def process_line(line:str): pass for line in read_line("文件名"): process_line(line) # 30) # 使用 Python 锁避免脏数据出现的例子 # 会出现同时修改一个全局变量的情况,叫做 暴露问题,创建一把锁 locka: # 通过 locka.acquire() 获得锁,通过 locka.release() 释放锁。 # 多线程的代码,由于避免脏数据的出现,基本退化为单线程代码,执行效率被拖累。 import threading import time locka = threading.Lock() a = 0 def add1(): global a try: locka.acquire() # 获得锁 tmp = a + 1 time.sleep(0.2) # 模拟 IO 操作 a = tmp finally: locka.release() # 释放锁 print('%s adds a to 1: %d'%(threading.current_thread().getName(),a)) threads = [threading.Thread(name='t%d'%(i,),target=add1) for i in range(10)] [t.start() for t in threads] # 31) # 说说死锁、GIL 锁、协程 比如,线程 A 等待着线程 B 释放锁 b,同时,线程 B 等待着线程 A 释放锁 a。在这种局面下,线程 A 和线程 B 都相互等待着,无法执行下去,这就是死锁。 为了避免死锁发生,Python 使用 GIL 锁,确保同一时刻只有一个线程在执行,所以其实是伪多线程。 Python 里常常使用协程技术来代替多线程。多进程、多线程的切换是由系统决定,而协程由我们自己决定。协程无需使用锁,也就不会发生死锁。同时,利用协程的协作特点,高效的完成了原编程模型只能通过多个线程才能完成的任务。 看多线程和协程部分笔记:https://www.cnblogs.com/PiaYie/p/14995055.html#_label3
  • 相关阅读:
    项目实战从0到1之hive(34)大数据项目之电商数仓(用户行为数据采集)(二)
    项目实战从0到1之hive(33)大数据项目之电商数仓(用户行为数据采集)(一)
    项目实战从0到1之spark(32)大数据项目之电商数仓(总结)(二):系统业务数据仓库
    项目实战从0到1之spark(31)大数据项目之电商数仓(总结)(一):系统业务数据仓库
    LeetCode435. 无重叠区间
    LeetCode392. 判断子序列
    LeetCode455. 分发饼干
    LeetCode128. 最长连续序列
    LeetCode376. 摆动序列
    LeetCode1143. 最长公共子序列
  • 原文地址:https://www.cnblogs.com/PiaYie/p/15020300.html
Copyright © 2020-2023  润新知