diff --git a/README.md b/README.md index 7394730..bc86071 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ * 3.8、给定两个列表,怎么找出他们相同的元素和不同的元素? * 3.9、请写出一段Python代码实现删除一个list里面的重复元素? * 3.10、给定两个list A ,B,请用找出 A ,B中相同与不同的元素 -* 4、企业面试题 +* [4、企业面试题](#企业面试题) * 4.1、Python新式类和经典类的区别? * 4.2、python中内置的数据结构有几种? * 4.3、Python如何实现单例模式?请写出两种实现方法 @@ -45,7 +45,7 @@ * 4.24、阅读一下代码他们的输出结果是什么? * 4.25、统计一段字符串中字符出现的次数 * 4.26、super函数的具体用法和场景 -* 二、Python高级 +* [二、Python高级](#Pythong高级) * 1、元类 * 1.1、Python中类方法、类实例方法、静态方法有何区别? * 1.2、super函数的具体用法和场景? @@ -87,7 +87,7 @@ * 3.25、递归函数停止的条件? * 3.26、下面这段代码的输出结果将是什么?请解释。 * 3.27、什么是lambda函数?它有什么好处?写一个匿名函数求两个数的 - * 4、设计模式 + * [4、设计模式](#4设计模式) * 4.1、对设计模式的理解,简述你了解的设计模式? * 4.2、请手写一个单例 * 4.3、单例模式的应用场景有哪些? @@ -118,7 +118,7 @@ * 6.10、简述Python里面search和match的区别 * 6.11、请写出匹配ip的Python正则表达式 * 6.12、Python里match与search的区别? - * 7、系统编程 + * [7、系统编程](#7系统编程) * 7.1、进程总结 * 7.2、谈谈你对多进程,多线程,以及协程的理解,项目是否用? * 7.3、Python异步使用场景有那些? @@ -275,33 +275,31 @@ * 1.4、判断数据是否在大量数据中 -# 文件操作 +# Python基础 ## 1.1 有一个jsonline格式的文件爱file.txt 大小约为10K -``` - def get_lines(): - l = [] - with open('file.txt','rb) as f: - for eachline in f: - l.append(eachline) - return l +```python +def get_lines(): + with open('file.txt', 'rb') as f: + return list(f) - if __name__ == '__main__': - for e in get_lines(): - process(e) #处理每一行数据 +if __name__ == '__main__': + for e in get_lines(): + process(e) # 处理每一行数据 ``` 现在要处理一个大小为10G的文件,但是内存只有4G,如果在只修改get_lines 函数而其他代码保持不变的情况下,应该如何实现?需要考虑的问题都有那些? -``` - def get_lines(): - l = [] - with open('file.txt','rb') as f: - data = f.readlines(60000) - l.append(data) - yield l +```python +def get_lines(line_number=10000): + f = open('file.txt','rb') + while True: + lines = f.readlines(line_number) + if not lines: + return + yield lines ``` 要考虑的问题有:内存只有4G无法一次性读入10G文件,需要分批读入分批读入数据要记录每次读入数据的位置。分批每次读取数据的大小,太小会在读取操作花费过多时间。 ## 1.2 补充缺失的代码 -``` - def print_directory_contents(sPath): +```python +def print_directory_contents(sPath): """ 这个函数接收文件夹的名称作为输入参数 返回该文件夹中文件的路径 @@ -315,237 +313,752 @@ else: print(sChildPath) ``` -# 模块与包 -## 2.1 输入日期, 判断这一天是这一年的第几天? +更简单的做法:`os.walk`. +```python +def print_directory_contents(sPath): + """ + 这个函数接收文件夹的名称作为输入参数 + 返回该文件夹中文件的路径 + 以及其包含文件夹中文件的路径 + """ + import os + for root, dirs, files in os.walk(sPath): + for dir_name in dirs: + print(os.path.join(root, dir_name)) + for fname in files: + print(os.path.join(root, fname)) ``` + +# 模块与包 +## 2.1 输入日期,判断这一天是这一年的第几天? +```python import datetime def dayofyear(): year = input("请输入年份: ") month = input("请输入月份: ") day = input("请输入天: ") - date1 = datetime.data(year=int(year),month=int(month),day=int(day)) - date2 = datatime.date(year=int(year),month=1,day=1) - return (date2-date1 +1).days + date1 = datetime.data(year=int(year), month=int(month), ay=int(day)) + date2 = datatime.date(year=int(year), month=1, day=1) + return (date2 - date1 +1).days ``` ## 2.2 打乱一个排好序的list对象alist? -``` - import random - alist = [1,2,3,4,5] - random.shuffle(alist) - print(alist) +```python +import random +alist = [1, 2, 3, 4, 5] +random.shuffle(alist) +print(alist) ``` # 数据类型 -## 3.1 现有字典 d= {'a':24,'g':52,'i':12,'k':33}请按value值进行排序? -``` - sorted(d.items(),key=lambda x:x[1]) +## 3.1 现有字典 d = {'a': 24, 'g': 52, 'i': 12, 'k': 33},请按value值进行排序? +```python +from operator import itemgetter + +sorted(d.items(),key=itemgetter(1)) ``` ## 3.2 字典推导式 -``` - d = {key:value for (key,value) in iterable} +```python +d = {key:value for (key, value) in iterable} ``` ## 3.3 请反转字符串 "aStr"? +```python +print("aStr"[::-1]) ``` - print("aStr"[::-1]) -``` -## 3.4 将字符串 "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 +## 3.4 将字符串 "k:1|k1:2|k2:3|k3:4",处理成字典 {k:1,k1:2,...} +```python +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 ``` ## 3.5 请按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) +```python +alist = [{'name':'a','age':20},{'name':'b','age':30},{'name':'c','age':25}] + +def sort_by_age(list1): + from operator import itemgetter + return sorted(alist, key=itemgetter('age'), reverse=True) ``` ## 3.6 下面代码的输出结果将是什么? +```python +list = ['a','b','c','d','e'] +print(list[10:]) ``` - list = ['a','b','c','d','e'] - print(list[10:]) -``` -代码将输出[],不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致Bug很难被追踪到。 +代码将输出`[]`,不会产生IndexError错误,就像所期望的那样,尝试用超出成员的个数的index来获取某个列表的成员。例如,尝试获取list[10]和之后的成员,会导致IndexError。然而,尝试获取列表的切片,开始的index超过了成员个数不会产生IndexError,而是仅仅返回一个空列表。这成为特别让人恶心的疑难杂症,因为运行的时候没有错误产生,导致Bug很难被追踪到。 ## 3.7 写一个列表生成式,产生一个公差为11的等差数列 -``` - print([x*11 for x in range(10)]) +```python +print([x * 11 for x in range(10)]) ``` ## 3.8 给定两个列表,怎么找出他们相同的元素和不同的元素? -``` - list1 = [1,2,3] - list2 = [3,4,5] - set1 = set(list1) - set2 = set(list2) - print(set1 & set2) - print(set1 ^ set2) +```python +list1 = [1,2,3] +list2 = [3,4,5] +set1 = set(list1) +set2 = set(list2) +print(set1 & set2) +print(set1 ^ set2) ``` ## 3.9 请写出一段python代码实现删除list里面的重复元素? -``` - l1 = ['b','c','d','c','a','a'] - l2 = list(set(l1)) - print(l2) +```python +l1 = ['b','c','d','c','a','a'] +l2 = list(set(l1)) +print(l2) ``` 用list类的sort方法: -``` - l1 = ['b','c','d','c','a','a'] - l2 = list(set(l1)) - l2.sort(key=l1.index) - print(l2) -``` -也可以这样写: -``` - l1 = ['b','c','d','c','a','a'] - l2 = sorted(set(l1),key=l1.index) - print(l2) +```python +l1 = ['b','c','d','c','a','a'] +l2 = list(set(l1)) +l2.sort(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) +```python +l1 = ['b','c','d','c','a','a'] +l2 = [] +for i in l1: + if not i in l2: + l2.append(i) +print(l2) ``` ## 3.10 给定两个list A,B ,请用找出A,B中相同与不同的元素 -``` - A,B 中相同元素: print(set(A)&set(B)) - A,B 中不同元素: print(set(A)^set(B)) +```python +A,B 中相同元素: print(set(A)&set(B)) +A,B 中不同元素: print(set(A)^set(B)) ``` # 企业面试题 ## 4.1 python新式类和经典类的区别? -a. 在python里凡是继承了object的类,都是新式类 -b. Python3里只有新式类 -c. Python2里面继承object的是新式类,没有写父类的是经典类 -d. 经典类目前在Python里基本没有应用 +根本区别:MRO 不同。 +a. 在 Python 里凡是继承了 `object` 的类,都是新式类 +b. Python 3 里只有新式类 +c. Python 2 里面继承 `object` 的是新式类,没有写父类的是经典类 +d. 经典类目前在 Python 里基本没有应用 ## 4.2 python中内置的数据结构有几种? -a. 整型 int、 长整型 long、浮点型 float、 复数 complex -b. 字符串 str、 列表list、 元祖tuple -c. 字典 dict 、 集合 set +a. 整型 int、长整型 long、浮点型 float、复数 complex +b. 字符串 str、列表list、元组tuple +c. 字典 dict、集合 set +d. None ## 4.3 python如何实现单例模式?请写出两种实现方式? 第一种方法:使用装饰器 -``` - 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 +```python +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() +assert foo1 is foo2 ``` 第二种方法:使用基类 -New 是真正创建实例对象的方法,所以重写基类的new 方法,以此保证创建对象的时候只生成一个实例 -``` - class Singleton(object): - def __new__(cls,*args,**kwargs): - if not hasattr(cls,'_instance'): - cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs) - return cls._instance - - class Foo(Singleton): - pass +`__new__` 是真正创建实例对象的方法,所以重写基类的 `__new__` 魔术方法,以此保证创建对象的时候只生成一个实例 +```python +class Singleton(object): + def __new__(cls,*args,**kwargs): + if not hasattr(cls,'_instance'): + cls._instance = super(Singleton,cls).__new__(cls,*args,**kwargs) + return cls._instance - foo1 = Foo() - foo2 = Foo() +class Foo(Singleton): + pass + +foo1 = Foo() +foo2 = Foo() - print foo1 is foo2 #True +assert foo1 is foo2 ``` -第三种方法:元类,元类是用于创建类对象的类,类对象创建实例对象时一定要调用call方法,因此在调用call时候保证始终只创建一个实例即可,type是python的元类 +第三种方法:元类,元类是用于创建类对象的类,类对象创建实例对象时一定要调用 `__call__` 魔术方法,因此在调用 `__call__` 的时候保证始终只创建一个实例即可,`type` 是 Python 类的类型(type) +```python +class Singleton(type): + def __call__(cls,*args,**kwargs): + if not hasattr(cls,'_instance'): + cls._instance = super(Singleton,cls).__call__(*args,**kwargs) + return cls._instance + +class Foo(object, metaclass=Singleton): + pass + +foo1 = Foo() +foo2 = Foo() +assert foo1 is foo2 ``` - class Singleton(type): - def __call__(cls,*args,**kwargs): - if not hasattr(cls,'_instance'): - cls._instance = super(Singleton,cls).__call__(*args,**kwargs) - return cls._instance + +第四种方法:直接使用 Python 内置的模块。模块不会重新导入,所以模块内定义的变量均为单例。 +## 4.4 反转一个整数,例如 -123 -> -321 +```python +class Solution(object): + def reverse(self,x): + str_x = str(x) + if str_x[0].isdigit(): + return int(str_x[::-1]) + else: + return int(str_x[0] + str_x[-1:0:-1]) + +if __name__ == '__main__': + s = Solution() + reverse_int = s.reverse(-120) + print(reverse_int) ``` +## 4.5 设计实现遍历目录与子目录,抓取 .pyc 文件 +第一种方法: +```python +import os + +def getFiles(dir, suffix): + res = [] + for root, dirs, files in os.walk(dir): + for filename in files: + name,suf = os.path.splitext(filename) + if suf == suffix: + res.append(os.path.join(root,filename)) + + return res + +getFiles("./",'.pyc') ``` - class Foo(object): - __metaclass__ = Singleton +第二种方法: +```python + import os + +def pick(obj): + try: + if obj[-4:] == ".pyc": + print(obj) + except: + return None - foo1 = Foo() - foo2 = Foo() - print foo1 is foo2 #True +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) +``` +## 4.6 一行代码实现 1-100 之和 +```python +sum(range(101)) +``` + +## 4.7 Python 遍历列表时删除元素的正确做法 +**不要删**。 + +Python 在遍历列表时,会根据 `index` 来遍历。如果在迭代过程中删除了某些元素,可能会跳过下一个迭代的元素。 +更好的做法是在遍历过程中记下所有需要删除的下标,迭代结束后一并删除。 + +## 4.9 可变类型和不可变类型 +`list` 是可变类型,在构建后可以对它进行原地修改;而 `tuple` 是不可变类型,对它进行操作(如 `+=`)将会产生一个新的 `tuple` 对象。 +## 4.10 `is` 和 `==` 有什么区别? +`is` 是比较两个对象的 ID;`==` 会查看两边的对象是否实现了 `__eq__` 函数, +若实现则调用,若都未实现,`==` 才会比较两个对象的 ID. + +## 4.11 求出列表所有奇数并构造新列表 +```python +[ + a for a in a_list + if a % 2 +] ``` -## 4.4 反转一个整数,例如-123 --> -321 + +## 4.12 用一行 Python 代码写出 1+2+3+10248 +```python +sum(range(1, 10249)) ``` - class Solution(object): - def reverse(self,x): - if -10