**kwargs
](#10-args-and-kwargs)
16 | * [11 面向切面编程AOP和装饰器](#11-面向切面编程aop和装饰器)
17 | * [12 鸭子类型](#12-鸭子类型)
18 | * [13 Python中重载](#13-python中重载)
19 | * [14 新式类和旧式类](#14-新式类和旧式类)
20 | * [15 __new__和__init__
的区别](#15-__new__和__init__的区别)
21 | * [16 单例模式](#16-单例模式)
22 | * [1 使用__new__方法](#1-使用__new__方法)
23 | * [2 共享属性](#2-共享属性)
24 | * [3 装饰器版本](#3-装饰器版本)
25 | * [4 import方法](#4-import方法)
26 | * [17 Python中的作用域](#17-python中的作用域)
27 | * [18 GIL线程全局锁](#18-gil线程全局锁)
28 | * [19 协程](#19-协程)
29 | * [20 闭包](#20-闭包)
30 | * [21 lambda函数](#21-lambda函数)
31 | * [22 Python函数式编程](#22-python函数式编程)
32 | * [23 Python里的拷贝](#23-python里的拷贝)
33 | * [24 Python垃圾回收机制](#24-python垃圾回收机制)
34 | * [1 引用计数](#1-引用计数)
35 | * [2 标记-清除机制](#2-标记-清除机制)
36 | * [3 分代技术](#3-分代技术)
37 | * [25 Python的List](#25-python的list)
38 | * [26 Python的is](#26-python的is)
39 | * [27 read,readline和readlines](#27-readreadline和readlines)
40 | * [28 Python2和3的区别](#28-python2和3的区别)
41 | * [29 super init](#29-super-init)
42 | * [30 range and xrange](#30-range-and-xrange)
43 | * [操作系统](#操作系统)
44 | * [1 select,poll和epoll](#1-selectpoll和epoll)
45 | * [2 调度算法](#2-调度算法)
46 | * [3 死锁](#3-死锁)
47 | * [4 程序编译与链接](#4-程序编译与链接)
48 | * [1 预处理](#1-预处理)
49 | * [2 编译](#2-编译)
50 | * [3 汇编](#3-汇编)
51 | * [4 链接](#4-链接)
52 | * [5 静态链接和动态链接](#5-静态链接和动态链接)
53 | * [6 虚拟内存技术](#6-虚拟内存技术)
54 | * [7 分页和分段](#7-分页和分段)
55 | * [分页与分段的主要区别](#分页与分段的主要区别)
56 | * [8 页面置换算法](#8-页面置换算法)
57 | * [9 边沿触发和水平触发](#9-边沿触发和水平触发)
58 | * [数据库](#数据库)
59 | * [1 事务](#1-事务)
60 | * [2 数据库索引](#2-数据库索引)
61 | * [3 Redis原理](#3-redis原理)
62 | * [Redis是什么?](#redis是什么)
63 | * [Redis数据库](#redis数据库)
64 | * [Redis缺点](#redis缺点)
65 | * [4 乐观锁和悲观锁](#4-乐观锁和悲观锁)
66 | * [5 MVCC](#5-mvcc)
67 | * [MySQL的innodb引擎是如何实现MVCC的](#mysql的innodb引擎是如何实现mvcc的)
68 | * [6 MyISAM和InnoDB](#6-myisam和innodb)
69 | * [网络](#网络)
70 | * [1 三次握手](#1-三次握手)
71 | * [2 四次挥手](#2-四次挥手)
72 | * [3 ARP协议](#3-arp协议)
73 | * [4 urllib和urllib2的区别](#4-urllib和urllib2的区别)
74 | * [5 Post和Get](#5-post和get)
75 | * [6 Cookie和Session](#6-cookie和session)
76 | * [7 apache和nginx的区别](#7-apache和nginx的区别)
77 | * [8 网站用户密码保存](#8-网站用户密码保存)
78 | * [9 HTTP和HTTPS](#9-http和https)
79 | * [10 XSRF和XSS](#10-xsrf和xss)
80 | * [11 幂等 Idempotence](#11-幂等-idempotence)
81 | * [12 RESTful架构(SOAP,RPC)](#12-restful架构soaprpc)
82 | * [13 SOAP](#13-soap)
83 | * [14 RPC](#14-rpc)
84 | * [15 CGI和WSGI](#15-cgi和wsgi)
85 | * [16 中间人攻击](#16-中间人攻击)
86 | * [17 c10k问题](#17-c10k问题)
87 | * [18 socket](#18-socket)
88 | * [19 浏览器缓存](#19-浏览器缓存)
89 | * [20 HTTP1.0和HTTP1.1](#20-http10和http11)
90 | * [21 Ajax](#21-ajax)
91 | * [*NIX](#nix)
92 | * [unix进程间通信方式(IPC)](#unix进程间通信方式ipc)
93 | * [数据结构](#数据结构)
94 | * [1 红黑树](#1-红黑树)
95 | * [编程题](#编程题)
96 | * [1 台阶问题/斐波那契](#1-台阶问题斐波那契)
97 | * [2 变态台阶问题](#2-变态台阶问题)
98 | * [3 矩形覆盖](#3-矩形覆盖)
99 | * [4 杨氏矩阵查找](#4-杨氏矩阵查找)
100 | * [5 去除列表中的重复元素](#5-去除列表中的重复元素)
101 | * [6 链表成对调换](#6-链表成对调换)
102 | * [7 创建字典的方法](#7-创建字典的方法)
103 | * [1 直接创建](#1-直接创建)
104 | * [2 工厂方法](#2-工厂方法)
105 | * [3 fromkeys()方法](#3-fromkeys方法)
106 | * [8 合并两个有序列表](#8-合并两个有序列表)
107 | * [9 交叉链表求交点](#9-交叉链表求交点)
108 | * [10 二分查找](#10-二分查找)
109 | * [11 快排](#11-快排)
110 | * [12 找零问题](#12-找零问题)
111 | * [13 广度遍历和深度遍历二叉树](#13-广度遍历和深度遍历二叉树)
112 | * [17 前中后序遍历](#17-前中后序遍历)
113 | * [18 求最大树深](#18-求最大树深)
114 | * [19 求两棵树是否相同](#19-求两棵树是否相同)
115 | * [20 前序中序求后序](#20-前序中序求后序)
116 | * [21 单链表逆置](#21-单链表逆置)
117 | * [22 两个字符串是否是变位词](#22-两个字符串是否是变位词)
118 | * [23 动态规划问题](#23-动态规划问题)
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | # Python语言特性
127 |
128 | ## 1 Python的函数参数传递
129 |
130 | 看两个例子:
131 |
132 | ```python
133 | a = 1
134 | def fun(a):
135 | a = 2
136 | fun(a)
137 | print a # 1
138 | ```
139 |
140 | ```python
141 | a = []
142 | def fun(a):
143 | a.append(1)
144 | fun(a)
145 | print a # [1]
146 | ```
147 |
148 | 所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
149 |
150 | 通过`id`来看引用`a`的内存地址可以比较理解:
151 |
152 | ```python
153 | a = 1
154 | def fun(a):
155 | print "func_in",id(a) # func_in 41322472
156 | a = 2
157 | print "re-point",id(a), id(2) # re-point 41322448 41322448
158 | print "func_out",id(a), id(1) # func_out 41322472 41322472
159 | fun(a)
160 | print a # 1
161 | ```
162 |
163 | 注:具体的值在不同电脑上运行时可能不同。
164 |
165 | 可以看到,在执行完`a = 2`之后,`a`引用中保存的值,即内存地址发生变化,由原来`1`对象的所在的地址变成了`2`这个实体对象的内存地址。
166 |
167 | 而第2个例子`a`引用保存的内存值就不会发生变化:
168 |
169 | ```python
170 | a = []
171 | def fun(a):
172 | print "func_in",id(a) # func_in 53629256
173 | a.append(1)
174 | print "func_out",id(a) # func_out 53629256
175 | fun(a)
176 | print a # [1]
177 | ```
178 |
179 | 这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点)
180 |
181 | 当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
182 |
183 | 如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference
184 |
185 | ## 2 Python中的元类(metaclass)
186 |
187 | 这个非常的不常用,但是像ORM这种复杂的结构还是会需要的,详情请看:http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python
188 |
189 | ## 3 @staticmethod和@classmethod
190 |
191 | Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)和实例方法,如下:
192 |
193 | ```python
194 | def foo(x):
195 | print "executing foo(%s)"%(x)
196 |
197 | class A(object):
198 | def foo(self,x):
199 | print "executing foo(%s,%s)"%(self,x)
200 |
201 | @classmethod
202 | def class_foo(cls,x):
203 | print "executing class_foo(%s,%s)"%(cls,x)
204 |
205 | @staticmethod
206 | def static_foo(x):
207 | print "executing static_foo(%s)"%x
208 |
209 | a=A()
210 |
211 | ```
212 |
213 | 这里先理解下函数参数里面的self和cls.这个self和cls是对类或者实例的绑定,对于一般的函数来说我们可以这么调用`foo(x)`,这个函数就是最常用的,它的工作跟任何东西(类,实例)无关.对于实例方法,我们知道在类里每次定义方法的时候都需要绑定这个实例,就是`foo(self, x)`,为什么要这么做呢?因为实例方法的调用离不开实例,我们需要把实例自己传给函数,调用的时候是这样的`a.foo(x)`(其实是`foo(a, x)`).类方法一样,只不过它传递的是类而不是实例,`A.class_foo(x)`.注意这里的self和cls可以替换别的参数,但是python的约定是这俩,还是不要改的好.
214 |
215 | 对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用`a.static_foo(x)`或者`A.static_foo(x)`来调用.
216 |
217 | | \\ | 实例方法 | 类方法 | 静态方法 |
218 | | :------ | :------- | :------------- | :-------------- |
219 | | a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
220 | | A | 不可用 | A.class_foo(x) | A.static_foo(x) |
221 |
222 | 更多关于这个问题:
223 | 1. http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
224 | 2. https://realpython.com/blog/python/instance-class-and-static-methods-demystified/
225 | ## 4 类变量和实例变量
226 |
227 | **类变量:**
228 |
229 | > 是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance 就是类变量,用于跟踪存在着多少个Test 的实例。
230 |
231 | **实例变量:**
232 |
233 | > 实例化之后,每个实例单独拥有的变量。
234 |
235 | ```python
236 | class Test(object):
237 | num_of_instance = 0
238 | def __init__(self, name):
239 | self.name = name
240 | Test.num_of_instance += 1
241 |
242 | if __name__ == '__main__':
243 | print Test.num_of_instance # 0
244 | t1 = Test('jack')
245 | print Test.num_of_instance # 1
246 | t2 = Test('lucy')
247 | print t1.name , t1.num_of_instance # jack 2
248 | print t2.name , t2.num_of_instance # lucy 2
249 | ```
250 |
251 | > 补充的例子
252 |
253 | ```python
254 | class Person:
255 | name="aaa"
256 |
257 | p1=Person()
258 | p2=Person()
259 | p1.name="bbb"
260 | print p1.name # bbb
261 | print p2.name # aaa
262 | print Person.name # aaa
263 | ```
264 |
265 | 这里`p1.name="bbb"`是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,`p1.name`一开始是指向的类变量`name="aaa"`,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
266 |
267 | 可以看看下面的例子:
268 |
269 | ```python
270 | class Person:
271 | name=[]
272 |
273 | p1=Person()
274 | p2=Person()
275 | p1.name.append(1)
276 | print p1.name # [1]
277 | print p2.name # [1]
278 | print Person.name # [1]
279 | ```
280 |
281 | 参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block
282 |
283 | ## 5 Python自省
284 |
285 | 这个也是python彪悍的特性.
286 |
287 | 自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
288 |
289 | ```python
290 | a = [1,2,3]
291 | b = {'a':1,'b':2,'c':3}
292 | c = True
293 | print type(a),type(b),type(c) # Hello world github/linguist#1 cool, and #1!
'" 52 | gh_toc_md2html() { 53 | local gh_file_md=$1 54 | URL=https://api.github.com/markdown/raw 55 | TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" 56 | if [ -f "$TOKEN" ]; then 57 | URL="$URL?access_token=$(cat $TOKEN)" 58 | fi 59 | curl -s --user-agent "$gh_user_agent" \ 60 | --data-binary @"$gh_file_md" -H "Content-Type:text/plain" \ 61 | $URL 62 | } 63 | 64 | # 65 | # Is passed string url 66 | # 67 | gh_is_url() { 68 | case $1 in 69 | https* | http*) 70 | echo "yes";; 71 | *) 72 | echo "no";; 73 | esac 74 | } 75 | 76 | # 77 | # TOC generator 78 | # 79 | gh_toc(){ 80 | local gh_src=$1 81 | local gh_src_copy=$1 82 | local gh_ttl_docs=$2 83 | 84 | if [ "$gh_src" = "" ]; then 85 | echo "Please, enter URL or local path for a README.md" 86 | exit 1 87 | fi 88 | 89 | 90 | # Show "TOC" string only if working with one document 91 | if [ "$gh_ttl_docs" = "1" ]; then 92 | 93 | echo "Table of Contents" 94 | echo "=================" 95 | echo "" 96 | gh_src_copy="" 97 | 98 | fi 99 | 100 | if [ "$(gh_is_url "$gh_src")" == "yes" ]; then 101 | gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy" 102 | else 103 | gh_toc_md2html "$gh_src" | gh_toc_grab "$gh_src_copy" 104 | fi 105 | } 106 | 107 | # 108 | # Grabber of the TOC from rendered html 109 | # 110 | # $1 — a source url of document. 111 | # It's need if TOC is generated for multiple documents. 112 | # 113 | gh_toc_grab() { 114 | # if closedfoo1
117 | #
118 | # became: The command foo1
119 | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n<\/h/<\/h/g' |
120 | # find strings that corresponds to template
121 | grep -E -o '//' | sed 's/<\/code>//' |
124 | # now all rows are like:
125 | # ... .*<\/h/)+2, RLENGTH-5)"](" gh_url substr($0, match($0, "href=\"[^\"]+?\" ")+6, RLENGTH-8) ")"}' | sed 'y/+/ /; s/%/\\x/g')"
130 | }
131 |
132 | #
133 | # Returns filename only from full path or url
134 | #
135 | gh_toc_get_filename() {
136 | echo "${1##*/}"
137 | }
138 |
139 | #
140 | # Options hendlers
141 | #
142 | gh_toc_app() {
143 | local app_name="gh-md-toc"
144 |
145 | if [ "$1" = '--help' ] || [ $# -eq 0 ] ; then
146 | echo "GitHub TOC generator ($app_name): $gh_toc_version"
147 | echo ""
148 | echo "Usage:"
149 | echo " $app_name src [src] Create TOC for a README file (url or local path)"
150 | echo " $app_name - Create TOC for markdown from STDIN"
151 | echo " $app_name --help Show help"
152 | echo " $app_name --version Show version"
153 | return
154 | fi
155 |
156 | if [ "$1" = '--version' ]; then
157 | echo "$gh_toc_version"
158 | return
159 | fi
160 |
161 | if [ "$1" = "-" ]; then
162 | if [ -z "$TMPDIR" ]; then
163 | TMPDIR="/tmp"
164 | elif [ -n "$TMPDIR" -a ! -d "$TMPDIR" ]; then
165 | mkdir -p "$TMPDIR"
166 | fi
167 | local gh_tmp_md
168 | gh_tmp_md=$(mktemp $TMPDIR/tmp.XXXXXX)
169 | while read input; do
170 | echo "$input" >> "$gh_tmp_md"
171 | done
172 | gh_toc_md2html "$gh_tmp_md" | gh_toc_grab ""
173 | return
174 | fi
175 |
176 | for md in "$@"
177 | do
178 | echo ""
179 | gh_toc "$md" "$#"
180 | done
181 |
182 | echo ""
183 | echo "Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)"
184 | }
185 |
186 | #
187 | # Entry point
188 | #
189 | gh_toc_app "$@"
190 |
--------------------------------------------------------------------------------
/img/builder.graffle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackfrued/interview_python/ca47c8f9d8800dec97566bcc2009aae5e492f6f3/img/builder.graffle
--------------------------------------------------------------------------------
/img/builder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jackfrued/interview_python/ca47c8f9d8800dec97566bcc2009aae5e492f6f3/img/builder.png
--------------------------------------------------------------------------------
/pattern.md:
--------------------------------------------------------------------------------
1 | # Python设计模式
2 |
3 | 代码直戳: https://github.com/faif/python-patterns
4 |
5 | # 创建型模式
6 |
7 | ## 工厂方法
8 |
9 |
10 | 实例 -> 类 -> 类工厂
11 |
12 | ## 抽象工厂
13 |
14 | 简单来说就是把一些具有相同方法的类再进行封装,抽象共同的方法以供调用.是工厂方法的进阶版本.
15 |
16 | 实例 -> 类 -> 类工厂 -> 抽象工厂
17 |
18 | ## 惰性初始化 Lazy evaluation
19 |
20 | 这个Python里可以使用@property实现,就是当调用的时候才生成.
21 |
22 | ## 生成器 Builder
23 |
24 | 
25 |
26 | Builder模式主要用于构建一个复杂的对象,但这个对象构建的算法是稳定的,对象中的各个部分经常变化。Builder模式主要在于应对复杂对象各个部分的频繁需求变动。但是难以应对算法的需求变动。这点一定要注意,如果用错了,会带来很多不必要的麻烦。
27 |
28 | 重点是将复杂对象的建造过程抽象出来(抽象类别),使这个抽象过程的不同实现方法可以构造出不同表现(属性)的对象。
29 |
30 | 简单的说:子对象变化较频繁,对算法相对稳定。
31 |
32 | ## 单例模式 Singleton
33 |
34 | 一个类只有一个实例
35 |
36 | ## 原型模式
37 |
38 | 特点是通过复制一个已经存在的实例来返回新的实例,而不是新建实例.
39 |
40 | 多用于创建复杂的或者耗时的实例,因为这种情况下,复制一个已经存在的实例使程序运行更高效;或者创建值相等,只是命名不一样的同类数据.
41 |
42 | ## 对象池 Object pool
43 |
44 | 一个对象池是一组已经初始化过且可以使用的对象,而可以不用在有需求时创建和销毁对象。池的用户可以从池子中取得对象,对其进行操作处理,并在不需要时归还给池子而非销毁 而不是销毁它.
45 |
46 | 在Python内部实现了对象池技术.例如像小整型这样的数据引用非常多,创建销毁都会消耗时间,所以保存在对象池里,减少开销.
47 |
48 | # 结构型模式
49 |
50 | ## 修饰模型 Decorator
51 |
52 | Python里就是装饰器.
53 |
54 | ## 代理模式 Proxy
55 |
56 | 例如Python里的引用计数.
57 |
58 | # 行为型模式
59 |
60 | ## 迭代器
61 |
62 | 迭代容器里所有的元素.
63 |
64 |
65 |
--------------------------------------------------------------------------------