**kwargs
](#10-args-and-kwargs)
+ * [11 面向切面编程AOP和装饰器](#11-面向切面编程aop和装饰器)
+ * [12 鸭子类型](#12-鸭子类型)
+ * [13 Python中重载](#13-python中重载)
+ * [14 新式类和旧式类](#14-新式类和旧式类)
+ * [15 __new__和__init__
的区别](#15-__new__和__init__的区别)
+ * [16 单例模式](#16-单例模式)
+ * [1 使用__new__方法](#1-使用__new__方法)
+ * [2 共享属性](#2-共享属性)
+ * [3 装饰器版本](#3-装饰器版本)
+ * [4 import方法](#4-import方法)
+ * [17 Python中的作用域](#17-python中的作用域)
+ * [18 GIL线程全局锁](#18-gil线程全局锁)
+ * [19 协程](#19-协程)
+ * [20 闭包](#20-闭包)
+ * [21 lambda函数](#21-lambda函数)
+ * [22 Python函数式编程](#22-python函数式编程)
+ * [23 Python里的拷贝](#23-python里的拷贝)
+ * [24 Python垃圾回收机制](#24-python垃圾回收机制)
+ * [1 引用计数](#1-引用计数)
+ * [2 标记-清除机制](#2-标记-清除机制)
+ * [3 分代技术](#3-分代技术)
+ * [25 Python的List](#25-python的list)
+ * [26 Python的is](#26-python的is)
+ * [27 read,readline和readlines](#27-readreadline和readlines)
+ * [28 Python2和3的区别](#28-python2和3的区别)
+ * [29 super init](#29-super-init)
+ * [30 range and xrange](#30-range-and-xrange)
+ * [操作系统](#操作系统)
+ * [1 select,poll和epoll](#1-selectpoll和epoll)
+ * [2 调度算法](#2-调度算法)
+ * [3 死锁](#3-死锁)
+ * [4 程序编译与链接](#4-程序编译与链接)
+ * [1 预处理](#1-预处理)
+ * [2 编译](#2-编译)
+ * [3 汇编](#3-汇编)
+ * [4 链接](#4-链接)
+ * [5 静态链接和动态链接](#5-静态链接和动态链接)
+ * [6 虚拟内存技术](#6-虚拟内存技术)
+ * [7 分页和分段](#7-分页和分段)
+ * [分页与分段的主要区别](#分页与分段的主要区别)
+ * [8 页面置换算法](#8-页面置换算法)
+ * [9 边沿触发和水平触发](#9-边沿触发和水平触发)
+ * [数据库](#数据库)
+ * [1 事务](#1-事务)
+ * [2 数据库索引](#2-数据库索引)
+ * [3 Redis原理](#3-redis原理)
+ * [Redis是什么?](#redis是什么)
+ * [Redis数据库](#redis数据库)
+ * [Redis缺点](#redis缺点)
+ * [4 乐观锁和悲观锁](#4-乐观锁和悲观锁)
+ * [5 MVCC](#5-mvcc)
+ * [MySQL的innodb引擎是如何实现MVCC的](#mysql的innodb引擎是如何实现mvcc的)
+ * [6 MyISAM和InnoDB](#6-myisam和innodb)
+ * [网络](#网络)
+ * [1 三次握手](#1-三次握手)
+ * [2 四次挥手](#2-四次挥手)
+ * [3 ARP协议](#3-arp协议)
+ * [4 urllib和urllib2的区别](#4-urllib和urllib2的区别)
+ * [5 Post和Get](#5-post和get)
+ * [6 Cookie和Session](#6-cookie和session)
+ * [7 apache和nginx的区别](#7-apache和nginx的区别)
+ * [8 网站用户密码保存](#8-网站用户密码保存)
+ * [9 HTTP和HTTPS](#9-http和https)
+ * [10 XSRF和XSS](#10-xsrf和xss)
+ * [11 幂等 Idempotence](#11-幂等-idempotence)
+ * [12 RESTful架构(SOAP,RPC)](#12-restful架构soaprpc)
+ * [13 SOAP](#13-soap)
+ * [14 RPC](#14-rpc)
+ * [15 CGI和WSGI](#15-cgi和wsgi)
+ * [16 中间人攻击](#16-中间人攻击)
+ * [17 c10k问题](#17-c10k问题)
+ * [18 socket](#18-socket)
+ * [19 浏览器缓存](#19-浏览器缓存)
+ * [20 HTTP1.0和HTTP1.1](#20-http10和http11)
+ * [21 Ajax](#21-ajax)
+ * [*NIX](#nix)
+ * [unix进程间通信方式(IPC)](#unix进程间通信方式ipc)
+ * [数据结构](#数据结构)
+ * [1 红黑树](#1-红黑树)
+ * [编程题](#编程题)
+ * [1 台阶问题/斐波那契](#1-台阶问题斐波那契)
+ * [2 变态台阶问题](#2-变态台阶问题)
+ * [3 矩形覆盖](#3-矩形覆盖)
+ * [4 杨氏矩阵查找](#4-杨氏矩阵查找)
+ * [5 去除列表中的重复元素](#5-去除列表中的重复元素)
+ * [6 链表成对调换](#6-链表成对调换)
+ * [7 创建字典的方法](#7-创建字典的方法)
+ * [1 直接创建](#1-直接创建)
+ * [2 工厂方法](#2-工厂方法)
+ * [3 fromkeys()方法](#3-fromkeys方法)
+ * [8 合并两个有序列表](#8-合并两个有序列表)
+ * [9 交叉链表求交点](#9-交叉链表求交点)
+ * [10 二分查找](#10-二分查找)
+ * [11 快排](#11-快排)
+ * [12 找零问题](#12-找零问题)
+ * [13 广度遍历和深度遍历二叉树](#13-广度遍历和深度遍历二叉树)
+ * [17 前中后序遍历](#17-前中后序遍历)
+ * [18 求最大树深](#18-求最大树深)
+ * [19 求两棵树是否相同](#19-求两棵树是否相同)
+ * [20 前序中序求后序](#20-前序中序求后序)
+ * [21 单链表逆置](#21-单链表逆置)
+ * [22 两个字符串是否是变位词](#22-两个字符串是否是变位词)
+ * [23 动态规划问题](#23-动态规划问题)
@@ -122,19 +129,50 @@
a = 1
def fun(a):
a = 2
-print a # 1
+fun(a)
+print(a) # 1
```
```python
a = []
def fun(a):
a.append(1)
-print a # [1]
+fun(a)
+print(a) # [1]
```
所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
-这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而list,dict等则是可以修改的对象。(这就是这个问题的重点)
+通过`id`来看引用`a`的内存地址可以比较理解:
+
+```python
+a = 1
+def fun(a):
+ print("func_in",id(a)) # func_in 41322472
+ a = 2
+ print("re-point",id(a), id(2)) # re-point 41322448 41322448
+print("func_out",id(a), id(1)) # func_out 41322472 41322472
+fun(a)
+print(a) # 1
+```
+
+注:具体的值在不同电脑上运行时可能不同。
+
+可以看到,在执行完`a = 2`之后,`a`引用中保存的值,即内存地址发生变化,由原来`1`对象的所在的地址变成了`2`这个实体对象的内存地址。
+
+而第2个例子`a`引用保存的内存值就不会发生变化:
+
+```python
+a = []
+def fun(a):
+ print ("func_in",id(a)) # func_in 53629256
+ a.append(1)
+print("func_out",id(a)) # func_out 53629256
+fun(a)
+print(a) # [1]
+```
+
+这里记住的是类型是属于对象的,而不是变量。而对象有两种,“可更改”(mutable)与“不可更改”(immutable)对象。在python中,strings, tuples, 和numbers是不可更改的对象,而 list, dict, set 等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
@@ -150,19 +188,19 @@ Python其实有3个方法,即静态方法(staticmethod),类方法(classmethod)
```python
def foo(x):
- print "executing foo(%s)"%(x)
+ print("executing foo(%s)"%(x))
class A(object):
def foo(self,x):
- print "executing foo(%s,%s)"%(self,x)
+ print("executing foo(%s,%s)"%(self,x))
@classmethod
def class_foo(cls,x):
- print "executing class_foo(%s,%s)"%(cls,x)
+ print("executing class_foo(%s,%s)"%(cls,x))
@staticmethod
def static_foo(x):
- print "executing static_foo(%s)"%x
+ print("executing static_foo(%s)"%x)
a=A()
@@ -172,15 +210,42 @@ a=A()
对于静态方法其实和普通的方法一样,不需要对谁进行绑定,唯一的区别是调用的时候需要使用`a.static_foo(x)`或者`A.static_foo(x)`来调用.
-|\\|实例方法|类方法|静态方法|
-|:--|:--|:--|:--|
-|a = A()|a.foo(x)|a.class_foo(x)|a.static_foo(x)|
-|A|不可用|A.class_foo(x)|A.static_foo(x)|
-
-更多关于这个问题:http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
+| \\ | 实例方法 | 类方法 | 静态方法 |
+| :------ | :------- | :------------- | :-------------- |
+| a = A() | a.foo(x) | a.class_foo(x) | a.static_foo(x) |
+| A | 不可用 | A.class_foo(x) | A.static_foo(x) |
+更多关于这个问题:
+1. http://stackoverflow.com/questions/136097/what-is-the-difference-between-staticmethod-and-classmethod-in-python
+2. https://realpython.com/blog/python/instance-class-and-static-methods-demystified/
## 4 类变量和实例变量
+**类变量:**
+
+> 是可在类的所有实例之间共享的值(也就是说,它们不是单独分配给每个实例的)。例如下例中,num_of_instance 就是类变量,用于跟踪存在着多少个Test 的实例。
+
+**实例变量:**
+
+> 实例化之后,每个实例单独拥有的变量。
+
+```python
+class Test(object):
+ num_of_instance = 0
+ def __init__(self, name):
+ self.name = name
+ Test.num_of_instance += 1
+
+if __name__ == '__main__':
+ print(Test.num_of_instance) # 0
+ t1 = Test('jack')
+ print(Test.num_of_instance) # 1
+ t2 = Test('lucy')
+ print(t1.name , t1.num_of_instance) # jack 2
+ print(t2.name , t2.num_of_instance) # lucy 2
+```
+
+> 补充的例子
+
```python
class Person:
name="aaa"
@@ -188,13 +253,11 @@ class Person:
p1=Person()
p2=Person()
p1.name="bbb"
-print p1.name # bbb
-print p2.name # aaa
-print Person.name # aaa
+print(p1.name) # bbb
+print(p2.name) # aaa
+print(Person.name) # aaa
```
-类变量就是供类使用的变量,实例变量就是供实例使用的.
-
这里`p1.name="bbb"`是实例调用了类变量,这其实和上面第一个问题一样,就是函数传参的问题,`p1.name`一开始是指向的类变量`name="aaa"`,但是在实例的作用域里把类变量的引用改变了,就变成了一个实例变量,self.name不再引用Person的类变量name了.
可以看看下面的例子:
@@ -206,12 +269,14 @@ class Person:
p1=Person()
p2=Person()
p1.name.append(1)
-print p1.name # [1]
-print p2.name # [1]
-print Person.name # [1]
+print(p1.name) # [1]
+print(p2.name) # [1]
+print(Person.name) # [1]
```
-参考:http://stackoverflow.com/questions/6470428/catch-multiple-exceptions-in-one-line-except-block
+当类变量值为可变对象(列表、字典等)时,共享类变量可能会造成意外的结果。
+
+为了避免变量混淆,推荐使用 self 来定义实例变量,使用类名或 cls 来定义类变量。对于可变对象的类变量,可以在类定义时使用深复制来避免共享。
## 5 Python自省
@@ -219,12 +284,20 @@ print Person.name # [1]
自省就是面向对象的语言所写的程序在运行时,所能知道对象的类型.简单一句就是运行时能够获得对象的类型.比如type(),dir(),getattr(),hasattr(),isinstance().
+```python
+a = [1,2,3]
+b = {'a':1,'b':2,'c':3}
+c = True
+print(type(a),type(b),type(c)) # Hello world github/linguist#1 cool, and #1!
'" +gh_toc_md2html() { + local gh_file_md=$1 + URL=https://api.github.com/markdown/raw + TOKEN="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/token.txt" + if [ -f "$TOKEN" ]; then + URL="$URL?access_token=$(cat $TOKEN)" + fi + curl -s --user-agent "$gh_user_agent" \ + --data-binary @"$gh_file_md" -H "Content-Type:text/plain" \ + $URL +} + +# +# Is passed string url +# +gh_is_url() { + case $1 in + https* | http*) + echo "yes";; + *) + echo "no";; + esac +} + +# +# TOC generator +# +gh_toc(){ + local gh_src=$1 + local gh_src_copy=$1 + local gh_ttl_docs=$2 + + if [ "$gh_src" = "" ]; then + echo "Please, enter URL or local path for a README.md" + exit 1 + fi + + + # Show "TOC" string only if working with one document + if [ "$gh_ttl_docs" = "1" ]; then + + echo "Table of Contents" + echo "=================" + echo "" + gh_src_copy="" + + fi + + if [ "$(gh_is_url "$gh_src")" == "yes" ]; then + gh_toc_load "$gh_src" | gh_toc_grab "$gh_src_copy" + else + gh_toc_md2html "$gh_src" | gh_toc_grab "$gh_src_copy" + fi +} + +# +# Grabber of the TOC from rendered html +# +# $1 — a source url of document. +# It's need if TOC is generated for multiple documents. +# +gh_toc_grab() { + # if closedfoo1
+ #
+ # became: The command foo1
+ sed -e ':a' -e 'N' -e '$!ba' -e 's/\n<\/h/<\/h/g' |
+ # find strings that corresponds to template
+ grep -E -o '//' | sed 's/<\/code>//' |
+ # now all rows are like:
+ # ... .*<\/h/)+2, RLENGTH-5)"](" gh_url substr($0, match($0, "href=\"[^\"]+?\" ")+6, RLENGTH-8) ")"}' | sed 'y/+/ /; s/%/\\x/g')"
+}
+
+#
+# Returns filename only from full path or url
+#
+gh_toc_get_filename() {
+ echo "${1##*/}"
+}
+
+#
+# Options hendlers
+#
+gh_toc_app() {
+ local app_name="gh-md-toc"
+
+ if [ "$1" = '--help' ] || [ $# -eq 0 ] ; then
+ echo "GitHub TOC generator ($app_name): $gh_toc_version"
+ echo ""
+ echo "Usage:"
+ echo " $app_name src [src] Create TOC for a README file (url or local path)"
+ echo " $app_name - Create TOC for markdown from STDIN"
+ echo " $app_name --help Show help"
+ echo " $app_name --version Show version"
+ return
+ fi
+
+ if [ "$1" = '--version' ]; then
+ echo "$gh_toc_version"
+ return
+ fi
+
+ if [ "$1" = "-" ]; then
+ if [ -z "$TMPDIR" ]; then
+ TMPDIR="/tmp"
+ elif [ -n "$TMPDIR" -a ! -d "$TMPDIR" ]; then
+ mkdir -p "$TMPDIR"
+ fi
+ local gh_tmp_md
+ gh_tmp_md=$(mktemp $TMPDIR/tmp.XXXXXX)
+ while read input; do
+ echo "$input" >> "$gh_tmp_md"
+ done
+ gh_toc_md2html "$gh_tmp_md" | gh_toc_grab ""
+ return
+ fi
+
+ for md in "$@"
+ do
+ echo ""
+ gh_toc "$md" "$#"
+ done
+
+ echo ""
+ echo "Created by [gh-md-toc](https://github.com/ekalinin/github-markdown-toc)"
+}
+
+#
+# Entry point
+#
+gh_toc_app "$@"