<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-generate-toc again -->
**Table of Contents**
* [Python语言特性](#python语言特性)
* [1 Python的函数参数传递](#1-python的函数参数传递)
* [2 Python中的元类(metaclass)](#2-python中的元类metaclass)
* [3 @staticmethod和@classmethod](#3-staticmethod和classmethod)
* [4 类变量和实例变量](#4-类变量和实例变量)
* [5 Python自省](#5-python自省)
* [6 字典推导式](#6-字典推导式)
* [7 Python中单下划线和双下划线](#7-python中单下划线和双下划线)
* [8 字符串格式化:\x和.format](#8-字符串格式化和format)
* [9 迭代器和生成器](#9-迭代器和生成器)
* [10 *args and <code>**kwargs</code>](#10-args-and-kwargs)
* [11 面向切面编程AOP和装饰器](#11-面向切面编程aop和装饰器)
* [12 鸭子类型](#12-鸭子类型)
* [13 Python中重载](#13-python中重载)
* [14 新式类和旧式类](#14-新式类和旧式类)
* [15 __new__和<code>__init__</code>的区别](#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)
* [<a href="http://lib.csdn.net/base/mysql">MySQL</a>的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-动态规划问题)
<!-- markdown-toc end -->
# Python语言特性
## 1 Python的函数参数传递
看两个例子:
```python
a = 1
def fun(a):
a = 2
fun(a)
print a # 1
```
```python
a = []
def fun(a):
a.append(1)
fun(a)
print a # [1]
```
所有的变量都可以理解是内存中一个对象的“引用”,或者,也可以看似c中void*的感觉。
通过`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 等则是可以修改的对象。(这就是这个问题的重点)
当一个引用传递给函数的时候,函数自动复制一份引用,这个函数里的引用和外边的引用没有半毛关系了.所以第一个例子里函数把引用指向了一个不可变对象,当函数返回的时候,外面的引用没半毛感觉.而第二个例子就不一样了,函数内的引用指向的是可变对象,对它的操作就和定位了指针地址一样,在内存里进行修改.
如果还不明白的话,这里有更好的解释: http://stackoverflow.com/questio