参考:http://python.jobbole.com/82294/
https://www.jianshu.com/p/aed6067eeac9
1. 操作系统基础题
1 will = ["Will", 28, ["Python", "C#", "JavaScript"]] 2 wilber = will 3 print id(will) 4 print will 5 print [id(ele) for ele in will] 6 print id(wilber) 7 print wilber 8 print [id(ele) for ele in wilber] 9 10 will[0] = "Wilber" 11 will[2].append("CSS") 12 print id(will) 13 print will 14 print [id(ele) for ele in will] 15 print id(wilber) 16 print wilber 17 print [id(ele) for ele in wilber]
这里需要注意的一点是,str是不可变类型,所以当修改的时候会替换旧的对象,产生一个新的地址39758496
浅拷贝:
1 import copy 2 3 will = ["Will", 28, ["Python", "C#", "JavaScript"]] 4 wilber = copy.copy(will) 5 6 print id(will) 7 print will 8 print [id(ele) for ele in will] 9 print id(wilber) 10 print wilber 11 print [id(ele) for ele in wilber] 12 13 will[0] = "Wilber" 14 will[2].append("CSS") 15 print id(will) 16 print will 17 print [id(ele) for ele in will] 18 print id(wilber) 19 print wilber 20 print [id(ele) for ele in wilber]
浅拷贝会创建一个新的对象,这个例子中”wilber is not will”
但是,对于对象中的元素,浅拷贝就只会使用原始元素的引用(内存地址),也就是说”wilber[i] is will[i]”
由于list的第一个元素是不可变类型,所以will对应的list的第一个元素会使用一个新的对象39758496
但是list的第三个元素是一个可变类型,修改操作不会产生新的对象,所以will的修改结果会相应的反应到wilber上
总结一下,当我们使用下面的操作的时候,会产生浅拷贝的效果:
- 使用切片[:]操作
- 使用工厂函数(如list/dir/set)
- 使用copy模块中的copy()函数
1 import copy 2 3 will = ["Will", 28, ["Python", "C#", "JavaScript"]] 4 wilber = copy.deepcopy(will) 5 6 print id(will) 7 print will 8 print [id(ele) for ele in will] 9 print id(wilber) 10 print wilber 11 print [id(ele) for ele in wilber] 12 13 will[0] = "Wilber" 14 will[2].append("CSS") 15 print id(will) 16 print will 17 print [id(ele) for ele in will] 18 print id(wilber) 19 print wilber
但是,对于对象中的元素,深拷贝都会重新生成一份(有特殊情况,下面会说明),而不是简单的使用原始元素的引用(内存地址)
例子中will的第三个元素指向39737304,而wilber的第三个元素是一个全新的对象39773088,也就是说,”wilber[2] is not will[2]”
- 当对will进行修改的时候
由于list的第一个元素是不可变类型,所以will对应的list的第一个元素会使用一个新的对象39758496
但是list的第三个元素是一个可不类型,修改操作不会产生新的对象,但是由于”wilber[2] is not will[2]”,所以will的修改不会影响wilber
其实,对于拷贝有一些特殊情况:
- 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有拷贝这一说
也就是说,对于这些类型,”obj is copy.copy(obj)” 、”obj is copy.deepcopy(obj)”
- 如果元祖变量只包含原子类型对象,则不能深拷贝,看下面的例子
总结
本文介绍了对象的赋值和拷贝,以及它们之间的差异:
- Python中对象的赋值都是进行对象引用(内存地址)传递
- 使用copy.copy(),可以进行对象的浅拷贝,它复制了对象,但对于对象中的元素,依然使用原始的引用.
- 如果需要复制一个容器对象,以及它里面的所有元素(包含元素的子元素),可以使用copy.deepcopy()进行深拷贝
- 对于非容器类型(如数字、字符串、和其他’原子’类型的对象)没有被拷贝一说
- 如果元祖变量只包含原子类型对象,则不能深拷贝。
3. 数据结构&算法基础题(3选1)
1)请实现一个双向列表的数据结构。并实现插入。
1 #双向链表 2 '节点类' 3 class Node(object): 4 def __init__(self,data = None): 5 self.data = data 6 self.pre = None 7 self.next = None 8 9 10 class Linklist(object): 11 def __init__(self): 12 self.head = None 13 14 def is_Empty(self): 15 return self.head==None 16 17 def length(self): 18 cur = self.head 19 count = 0 20 while cur != None: 21 count += 1 22 cur = cur.next 23 return count 24 #前面插节点 25 def add(self,item): 26 node = Node(item) 27 if self.is_Empty(): 28 self.head = node 29 30 else: 31 node.next = self.head 32 self.head.pre = node 33 self.head = node 34 #后面插节点 35 def append(self,item): 36 node = Node(item) 37 if self.is_Empty(): 38 self.head = node 39 40 else: 41 cur = self.head 42 while cur.next != None: 43 cur = cur.next 44 cur.next = node 45 node.pre = cur 46 #查找 47 def search(self,item): 48 node = Node(item) 49 50 cur = self.head 51 while cur!= None: 52 if cur.data == item: 53 return True 54 cur = cur.next 55 return False 56 57 def insert(self,pos,item): 58 """在指定位置添加节点""" 59 if pos <= 0: 60 self.add(item) 61 elif pos > (self.length()-1): 62 self.append(item) 63 else: 64 node = Node(item) 65 cur = self.head 66 count = 0 67 while count < (pos-1) : 68 count += 1 69 cur = cur.next 70 node.pre = cur 71 node.next = cur.next 72 cur.next.pre = node 73 cur.next = node 74 #移除某个元素 75 def remove(self,item): 76 77 if self.is_Empty(): 78 return 79 else: 80 cur = self.head 81 if cur.item == item: #第一个就是要找的 82 if cur.next == None: #只有一个头结点 83 self.head = None 84 else: 85 cur.next.pre = None 86 self.head = cur.next 87 return 88 while cur != None: 89 if cur.item == item: 90 cur.pre.next = cur.next 91 cur.next.pre = cur.pre 92 break 93 94 cur = cur.next
2.对于阻塞调用来说,则当前线程就会被挂起等待当前函数返回;
5. 编程应用题
现有1份用户访问日志,文件名为access.log,每行记录包含3列数据(' '分割):IP地址(点分格式的字符串)、URL(用户访问的URL链接)、时间戳(Unix Timestamp格式)。请实现如下数据处理需求。
备注:尽量写出可直接运行的源码,Java/C/Python均可。
1)统计该日志中所有URL的热度,并按热度降序输出TOP 5
2)统计今天凌晨3点至凌晨5点30分期间内,用户访问最频繁的5个URL(假设那段时间内的用户访问记录包含在access.log中)
3)把点分格式字符串表示的IP地址转换成其整数表示
4)如果文件太大导致单机无法直接处理,有哪些解决思路?
答:
1.
2.
3.
1 ip2num = lambda x:sum([256**j*int(i) for j,i in enumerate(x.split('.')[::-1])]) 2 ip2num('192.168.0.1')
3232235521
4. 将文件分为若干个小文件
通过一个hash函数,将URL散列到不同的文件之中,字符串映射到整型数
通过哈希,根据余数将url分配到小文件中
统计每一个txt文件中的URL出现的频次,存入数组中
最后统计数组。