Python 学习笔记 (转载)
Python Notes Python 学习笔记
简介
从1990年到现在,Python 已经是一个非常成熟的语言了,并且他的流程度增长也很稳定。它是跨平台、开放源代码、动态类型、面向对象的解释型语言。它的应用范围非常广,包括web开发,科学计算,系统管理,桌面应用程序,游戏等等。
Python 的哲学强调干净和可读的代码,并且同时给开发者以最大的灵活性。
Python语言是少有的一种可以称得上即简单又功能强大的编程语言。你将惊喜地发现Python语言是多么地简单,它注重的是如何解决问题而不是编程语言的语法和结构。
Python的官方介绍是:
Python是一种简单易学,功能强大的编程语言,它有高效率的高层数据结构,简单而有效地实现面向对象编程。Python简洁的语法和对动态输入的支持,再加上解释性语言的本质,使得它在大多数平台上的许多领域都是一个理想的脚本语言,特别适用于快速的应用程序开发。
下载 Python
1) 首先下载 Python 的 Windows 版本,地址是:http://www.python.org/download/
2) 安装
3) 运行 Python GUI,如图:
图1 - 运行 Python GUI
4) Hello Python!
1. >>> print "Xwy2.com Say: Hello Python"
2. Xwy2.com Say: Hello Python
3. >>>
怎么样?让我们开始我们的 Python 之旅吧,本系列所有的代码示例均在交互式(Interactive)模式下完成。
先提醒你一下:
1) Python 函数没有明显的 begin 和 end, 没有花括号, 用于标函数的开始和结束。唯一的分隔符是一个冒号 (:), 接着代码本身是缩进的。
2) Python 使用硬回车来分割语句, 冒号和缩进来分割代码块。C++ 和 Java 使用分号来分割语句, 花括号来分割代码块。
本系列课程,大部分内容来自Q.yhenRuby 学习笔记系列http://www.rainsts.net/default.asp?cat=20,感谢Q.yhen让我的Python之路节省了不少时间~~
在学习 Python 之前,我们先学几个内置函数,这对于了解 Python 的一些原理是非常有用的。
内置函数
id()
如果我们能获取对象(变量、方法或类型实例)的 "内存地址" 对于我们了解引用机制还是非常不错的。
id() 返回一个对象的 "唯一序号",转换成 16 进制就是所谓的内存地址了,为了图方便后面直接使用 id(),不再转换成 16 进制。
1. >>> def Foo():
2. pass
3.
4. >>> Foo
5. <function Foo at 0x00DC6EB0>
6. >>> hex(id(Foo))
7. '0xdc6eb0'
8. >>>
dir()
方法 dir() 能帮我们了解对象包含哪些成员。
1. >>> dir(Foo)
2. ['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']['__call__', '__class__', '__delattr__', '__dict__', '__doc__', '__get__', '__getattribute__', '__hash__', '__init__', '__module__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
3. >>>
type()
type() 让我们知道变量的实际类型。
1. >>> type(Foo)
2. <type 'function'>
3. >>>
isinstance()
isinstance() 可以确认某个变量是否某种类型。
1. >>> s = "Xwy2.com"
2. >>> isinstance(s, str)
3. True
4. >>>
issubclass()
该函数可以判断继承关系。
1. >>> issubclass(int,object)
2. True
3. >>>
is
多数情况下,我们可以直接使用 "==" 来判断两个对象是否相等。但 Python 同样支持运算符重载,因此使用 is 来代替应该更安全一点(C# 中经典的 Equals 问题)。
1. >>> class MyClass:
2. def __ini__(Self):
3. self.x = 123
4. def __eq__(self, o):
5. return self.x == o.x
6.
7.
8. >>> a = MyClass()
9. >>> b = MyClass()
10.>>> print hex(id(a))
11.0xdcea80
12.>>> print hex(id(b))
13.0xdc4b98
14.>>> print a == b
15.true
16.>>> print a is b
17.false
LoongTsui按:Python里一切均是对象,Python 提供了很棒的自省能力,自省揭示了关于程序对象的有用信息。Python自带的Help指令就是有其自省能力实现的,下面补充一下对Help指令的介绍
Python帮助help指令
启动Help指令
引用
>>> help()
Welcome to Python 2.5! This is the online help utility.
..省略号
Enter the name of any module, keyword, or topic to get help on writing
Python programs and using Python modules. To quit this help utility and
return to the interpreter, just type "quit".
To get a list of available modules, keywords, or topics, type "modules",
"keywords", or "topics". Each module also comes with a one-line summary
of what it does; to list the modules whose summaries contain a given word
such as "spam", type "modules spam".
help>
输入help()会启动help指令,最后进入help>提示符,如果输入keywords,将列出Python的所有关键字:
引用
help> keywords
Here is a list of the Python keywords. Enter any keyword to get more help.
and elif if print
as else import raise
assert except in return
break exec is try
class finally lambda while
continue for not with
def from or yield
del global pass
输入modules将列出Python所有可用的模块:
引用
...省略号
PathBrowser binascii mailbox sys
Percolator binhex mailcap tabnanny
PyParse bisect markupbase tabpage
...省略号
可以输入上面列出的所有指令,查看其帮助信息
help指令还有使用方式,在 Python Shell 提示符>>>下,输入 help("modules") 这样。
上面介绍的内置函数和help实用程序是很方便很有用处的。
关于自省的更为详细的介绍,请参见:Python 自省指南
Python 中的每样东西都是对象,不同与其他面向对象语言的是:
第一,Python 中的所有数据值都被封装在相关对象类中。
第二,Python 程序中的所有东西都是可以从程序访问的对象,即使是您编写的代码也不例外。
Python 不包含像 int 这样的简单类型 —— 只有对象类型。如果 Python 中需要整数值,将整数赋值给相应变量(如 i = 100 )即可。在后台,Python 将创建一个整数对象,并将对新对象的引用赋值给变量。问题的关键是:Python 是一种动态类型化语言,所以无需声明变量类型。事实上在单个程序中,变量的类型是可以改变(多次)的。
可以将 PyObject 类之下的所有 Python 类划分为 Python 运行时解释器可以使用的四个主要类别:
1) 简单类型 —— 基本构建块,如 int 和 float。
2) 容器类型 —— 保存其他对象。
3) 代码类型 —— 封装 Python 程序的元素。
4) 内部类型 —— 程序执行期间使用的类型。
本次重点介绍简单类型。
Python 有五个内置的简单类型:bool、int、long、float 和 complex。这些类型是不可变的,就是说整数对象一旦创建,其值便不可更改。相反,系统将创建新的简单类型对象并将其赋值给变量。通过 Python id 函数,可以查看基本 PyObject 标识的变更方式:
整数 & 浮点数
整数有两种,分别是 int 和 long。其中 int 最大值是 2147483647 (sys.maxint),而 long 长度仅受内存大小限制。
1. >>> a = 123
2. >>> b = 123L
3. >>> type(a)
4. <type 'int'>
5. >>> type(b)
6. <type 'long'>
7. >>>
浮点数基本上也没有什么特别之处,不过要注意下面写法不同。
1. >>> a = 1
2. >>> b = 1.0
3. >>> type(a)
4. <type 'int'>
5. >>> type(b)
6. <type 'float'>
7. >>>
和数字有关的函数有:
1. abs(x) 取绝对值。
1. >>> abs(-123)
2. 123
3. >>>
2. coerce(x, y) 将两个数字转换成相同类型。
1. >>> a = 1.0
2. >>> b = 2
3. >>> s = coerce(a,b)
4. >>> type(s)
5. <type 'tuple'>
6. >>> s
7. (1.0, 2.0)(1.0, 2.0)
8. >>>
3. divmod(a, b) 获取商和余数。返回一个 tuple,如 (2, 1) 分别是商和余数。
1. >>> s = divmod(5,2)
2. >>> type(s)
3. <type 'tuple'>
4. >>> s
5. (2, 1)(2, 1)
6. >>>
4. pow(x, y) 取幂,和 ** 操作符意义相同。
1. >>> 2 ** 3
2. 8
3. >>> pow(2,3)
4. 8
5. >>>
5. round(x, [n]) 四舍五入
1. >>> round(3.1415926535897932,2)
2. 3.1400000000000001
3. >>> round(2.4567,2)
4. 2.46
6. min(x [, y, z...]) 返回最小的一个数。
1. >>> min(3, 6, 9, 4, 1)
2. 1
3. >>>
7. max(x [, y, z...]) 返回最大的一个数。
1. >>> max(3, 6, 9, 4, 1)
2. 9
3. >>>
8. cmp(x, y) 比较数字。x > y 返回 1, x == y 返回 0, x < y 返回 -1。
1. >>> cmp(2,1)
2. 1
3. >>> cmp(1,1)
4. 0
5. >>> cmp(1,2)
6. -1
7. >>>
字符串
Python 中没有字符(char)类型,而且和 C# 一样,字符串是不可以更改的。字符串可以使用单引号(')也可以使用双引号("),或者使用三引号使其跨越多行。
1. >>> s = '''xwy
2. 2
3. .
4. com'''
5. >>> s
6. 'xwy"n2"n."ncom'
7. >>>
字符串同样支持转义符。还记得 C# 字符串前面那个常用的 "@" 吗?Python 也有类似的东西,就是 "r"。
1. >>> s = r"c:"windows"notepade.exe"
2. >>> s
3. 'c:""windows""notepade.exe'
4. >>>
比较有意思的是,Python 中的字符串支持使用乘号来创建一个连续字符串。如:
1. >>> s = "abc" * 6
2. >>> s
3. 'abcabcabcabcabcabc'
4. >>>
尽管没有字符类型,但依然可以使用索引号来获取字符串中的字符。
1. >>> s = "abc"
2. >>> s[1]
3. 'b'
4. >>>
Python 拥有非常方便的切片处理能力,我们可以使用负索引号从字符串结尾进行索引。
1. >>> s = "abcdefg"
2. >>> s[2:-1]
3. 'cdef'
4. >>>
这里需要提一下,Python 比较古怪的多变量赋值方式。
1. >>> a,b,c=("xwy2",".","com")
2. >>> a
3. 'xwy2'
4. >>> b
5. '.'
6. >>> c
7. 'com'
8. >>> a,b,c="123"
9. >>> a
10.'1'
11.>>> b
12.'2'
13.c
14.>>> c
15.'3'
16.>>>
Python 同样支持格式化字符串,类似 C# 中的 String.Format。包括各种类型以及固定宽度输出。
1. >>> s = "str = [%-5s],int = [%05d],float = [%.2f]"%("a",5,3.1415)
2. >>> s
3. 'str = [a ],int = [00005],float = [3.14]'
4. >>>
],int = [00005],float = [3.14]'
Python 使用如下方式支持 Unicode。
1. >>> s = u"abc"
2. s
3. >>> s
4. u'abc'
5. >>> type(s)
6. <type 'unicode'>
7. >>> s += 'sss'
8. >>> s
9. u'abcsss'
10.>>>
和字符串相关的常用函数有:
1. lstrip() / rstrip() / strip() 好像多数语言都命名为 LTrim() / RTrim() / Trim()。
>>> " abc ".strip()
'abc'
2. expandtabs() 将 TAB 替换成指定数量的空格。
1. >>> "abc ".strip()
2. 'abc'
3. >>>
".strip()
3. lower() / upper() 大小写转换。
1. >>> "ABC".lower()
2. 'abc'
3. >>> "abc".upper()
4. 'ABC'
5. >>>
4. swapcase() / title() / capitalize() 分别将全部字符,每单词首字符,短语首字符转成大写。
1. >>> "Xwy2.com".swapcase()
2. 'xWY2.COM'
3. >>> "xwy2.com".title()
4. 'Xwy2.Com'
5. >>> "xwy2.com".capitalize()
6. 'Xwy2.com'
7. >>>
5. isxxxx 判断字符串... 没啥好说的。
1. >>> "xwy".isalpha()
2. True
3. >>> "xwy2".isalnum()
4. True
5. >>> "123".isdigit()
6. True
7. >>> " ".isspace()
8. True
9. >>> "AB".isupper()
10.True
11.>>>
".isspace()
6. find() 查找子串,类似的还有 index() / rindex() / rfind()。rxxx 表示找最后一个子串, index 在找不到时会触发异常。
1. >>> "abcdefg".find('d',1,-1)
2. 3
3. >>> "abcdefg".find('d',4, -1)
4. -1
5. >>> "aaa1111aaa".rfind('aaa')
6. 7
7. >>> "aa1111aaa".index('b')
8.
9. Traceback (most recent call last):
10. File "<pyshell#192>", line 1, in <module>
11. 'aa1111aaa'.index('b')
12.ValueError: substring not found
13.>>>
File "<pyshell#192>", line 1, in <module>
'aa1111aaa'.index('b')
7. count() 统计子串数量。
1. >>> "Loong Tsui".count("o")
2. 2
3. >>>
8. replace() 替换子串
1. >>> "abc".replace("b", "1")
2. 'a1c'
3. >>>
9. splite() 分解字符串。
1. >>> "a b c d".split(" ")
2. ['a', 'b', 'c', 'd']['a', 'b', 'c', 'd']
3. >>> "a b c".split(" ",2)
4. ['a', 'b', 'c']['a', 'b', 'c']
5. >>> "a b c d".split(" ",2)
6. ['a', 'b', 'c d']['a', 'b', 'c d']
7. >>> "a b c d e".split(" ", 2)
8. ['a', 'b', 'c d e']['a', 'b', 'c d e']
9. >>>
10. join() 连接字符串。
1. >>> "|".join(["a","b","c","d"])
2. 'a|b|c|d'
3. >>> "|".join(["首页","b","c","d"])
4. '"xca"xd7"xd2"xb3|b|c|d'
5. >>>
类型转换
转换函数和多数编程语言类似。
1. >>> int("123")
2. 123
3. >>> long("123")
4. 123L
5. >>> float("123.45")
6. 123.45
7. >>> float(123)
8. 123.0
9. >>> float(123L)
10.123.0
11.>>> ord("a")
12.97
13.>>> chr(97)
14.'a'
15.>>> hex(97)
16.'0x61'
17.>>> str(123)
18.'123'
- Python 学习笔记 - 4.if 表达式
方式1
1. >>> s = ""
2. >>> a = s or "not none"
3. >>> a
4. 'not none'
5.
6. >>> s = None
7. >>> a = s or "not none"
8. >>> a
9. 'not none'
10.
11.>>> s = "aa"
12.>>> a = s or "not none"
13.>>> a
14.'aa'
方式2
1. >>> s = None
2. >>> a = "not null" if s == None else s
3. >>> a
4. 'not null'
5.
6. >>> s = "aa"
7. >>> a = "not null" if s == None else s
8. >>> a
9. 'aa'
好像方式2 更接近 "? :" 这种三元表达式。
Python 学习笔记 - 5.对象驻留
我们知道 C# 中使用字符串驻留(string interning)机制来提高系统性能,可在 Python 中非但字符串有驻留机制,连整数等也拥有同样的待遇。
1. >>> i = 1
2. >>> i2 = 1
3. >>> id(i)
4. 11229288
5. >>> id(i2)
6. 11229288
7. >>>
甚至是类成员也同样如此。
1. >>> class MyClass:
2. def __init__(self):
3. self.x = 123
4.
5.
6. >>> a = MyClass()
7. >>> b = MyClass()
8. >>> id(a.x)
9. 11229808
10.>>> id(b.x)
11.11229808
12.>>>
继续一个复杂一点的。
1. >>> class MyClass1:
2. i = 123
3. def __init__(self):
4. self.x = 1234
5.
6.
7. >>> class MyClass2:
8. i = 123
9. def __init__(self):
10. self.x = 1234
11.
12.
13.>>> id(MyClass1.i)
14.11229808
15.>>> id(MyClass2.i)
16.11229808
17.>>> id(MyClass1().x)
18.12893924
19.>>> id(MyClass2().x)
20.13241836
21.>>>
即便在不同类型中,也只有实例成员的地址不同。
我们还可以使用如下方式查看引用计数的变化,这是否意味着 Python 将简单类型也分配到堆上?
1. >>> import sys
2. >>> a = 1
3. >>> sys.getrefcount(a)
4. 699
5. >>> b = a
6. >>> sys.getrefcount(a)
7. 700
8. >>> c = 1
9. >>> sys.getrefcount(c)
10.701
11.>>>
而在 C# 中,显然堆或栈上都不可能如此。
1. unsafe
2. {
3. int i = 1;
4. int i2 = 1;
5.
6. int* p1 = &i;
7. int* p2 = &i2;
8.
9. Console.WriteLine((int)p1);
10. Console.WriteLine((int)p2);
11.}
int i = 1;
int i2 = 1;
int* p1 = &i;
int* p2 = &i2;
Console.WriteLine((int)p1);
Console.WriteLine((int)p2);
输出结果自然不同。
Python 学习笔记 - 6.List和Tuple
List,Tuple
列表(List) : 类似于 .NET ArrayList / List。
元组(Tuple) : 列表的只读版。
1. 转换
我们可以使用 list() / tuple() 函数在列表和元组之间进行转换。
1. >>> a = ['a', 'b', 'c']
2. >>> a
3. ['a', 'b', 'c']['a', 'b', 'c']
4. >>> b = tuple(a)
5. >>> b
6. ('a', 'b', 'c')('a', 'b', 'c')
7. >>> c = list(b)
8. >>> c
9. ['a', 'b', 'c']['a', 'b', 'c']
10.>>>
这两个函数接受字符串参数时候比较有意思。
1. >>> list("xwy2.com")
2. ['x', 'w', 'y', '2', '.', 'c', 'o', 'm']['x', 'w', 'y', '2', '.', 'c', 'o', 'm']
3. >>> tuple("xwy2.com")
4. ('x', 'w', 'y', '2', '.', 'c', 'o', 'm')('x', 'w', 'y', '2', '.', 'c', 'o', 'm')
5. >>>
2. 运算符操作
列表支持运算符操作。
1. >>> [1, 2] * 2
2. [1, 2, 1, 2][1, 2, 1, 2]
3. >>> [1, 2] + [3, 4]
4. [1, 2, 3, 4][1, 2, 3, 4]
5. >>>
3. in / not in
可以使用 in / not in 来判断是否包含某个元素。
1. >>> a = [1, 2, 3]
2. >>> 1 in a
3. True
4. >>> 4 in a
5. False
6. >>> b = (1, 2, 3)
7. >>> 2 in b
8. True
9. >>>
4. range()
我们还可以使用 range() 函数获得一个整数列表,甚至进行运算和添加过滤条件。
1. >>> range(10)
2. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
3. >>> range(2, 10, 2)
4. [2, 4, 6, 8][2, 4, 6, 8]
5. >>> range(2, 7)
6. [2, 3, 4, 5, 6][2, 3, 4, 5, 6]
7. >>> [x*2 for x in range(10)]
8. [0, 2, 4, 6, 8, 10, 12, 14, 16, 18][0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
9. >>> [x for x in range(10) if x%2>0]
10.[1, 3, 5, 7, 9][1, 3, 5, 7, 9]
11.>>> [x + 1 for x in range(10) if x%2==0]
12.[1, 3, 5, 7, 9][1, 3, 5, 7, 9]
13.>>>
5. Slices
和字符串一样,我们可以通过序号或切片进行访问。
1. >>> b = (1,2,3)
2. >>> b[-1]
3. 3
4. >>> b[1:-1]
5. (2,)(2,)
6. >>> b=(1,2,3)
7. >>> b[1]
8. 2
9. >>> b[1:]
10.(2, 3)(2, 3)
11.>>> b[-1]
12.3
13.>>> b=[1,2,3]
14.>>> b[1] = 100
15.>>> b
16.[1, 100, 3][1, 100, 3]
17.>>>
6. 相关方法
基本方法:
1. >>> a = ['a','b','c']
2. >>> a.index('b')
3. 1
4. >>> a += ['d']
5. >>> a
6. ['a', 'b', 'c', 'd']['a', 'b', 'c', 'd']
7. >>> a += ['b']
8. >>> a
9. ['a', 'b', 'c', 'd', 'b']['a', 'b', 'c', 'd', 'b']
10.>>> a.count('b')
11.2
12.>>> a.insert(1, 's')
13.>>> a
14.['a', 's', 'b', 'c', 'd', 'b']['a', 's', 'b', 'c', 'd', 'b']
15.>>> a.remove('s')
16.>>> a
17.['a', 'b', 'c', 'd', 'b']['a', 'b', 'c', 'd', 'b']
18.>>> a.pop(2)
19.'c'
20.>>> a
21.['a', 'b', 'd', 'b']['a', 'b', 'd', 'b']
22.>>> a.reverse()
23.>>> a
24.['b', 'd', 'b', 'a']['b', 'd', 'b', 'a']
25.>>> a.sort()
26.>>> a
27.['a', 'b', 'b', 'd']['a', 'b', 'b', 'd']
28.>>> a.extend(['e','f'])
29.>>> a
30.['a', 'b', 'b', 'd', 'e', 'f']['a', 'b', 'b', 'd', 'e', 'f']
31.>>> a.append('m', 'n')
32.
33.Traceback (most recent call last):
34. File "<pyshell#72>", line 1, in <module>
35. a.append('m', 'n')
36.TypeError: append() takes exactly one argument (2 given)
37.>>> a.append(['m','n'])
38.>>> a
39.['a', 'b', 'b', 'd', 'e', 'f', ['m', 'n']]['a', 'b', 'b', 'd', 'e', 'f', ['m', 'n']]
40.>>>
File "<pyshell#72>", line 1, in <module>
a.append('m', 'n')
还可以使用 filter() 进行过滤。
1. >>> a = range(10)
2. >>> a
3. [0, 1, 2, 3, 4, 5, 6, 7, 8, 9][0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
4. >>> def divfilter(i):
5. return i%2 == 0
6.
7. >>> filter(divfilter, a)
8. [0, 2, 4, 6, 8][0, 2, 4, 6, 8]
9. >>>
上面的代码还可以简写为:
1. >>> filter(lambda i: i%2==0, range(10))
2. [0, 2, 4, 6, 8][0, 2, 4, 6, 8]
3. >>>
当 function 参数(第一个参数)为 None 时,可以用来过滤掉空值。
1. >>> b = ['a', '', [], [1,2]]
2. >>> filter(None,b)
3. ['a', [1, 2]]['a', [1, 2]]
4. >>>
map() 类似 .NET 中的 Array.Foreach()
1. >>> map(lambda i:i*2, range(10))
2. [0, 2, 4, 6, 8, 10, 12, 14, 16, 18][0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
3. >>>
另外,我们还可以使用 reduce() 对元素进行统计。
1. >>> import operator
2. >>> reduce(operator.add, range(10))
3. 45
4. >>> reduce(operator.sub, [100, 5, 7])
5. 88
6. >>>
zip() 方法可以对两个或多个列表/元组进行交叉合并。
1. >>> zip(range(2,10), ('a', 'b', 'c', 'd', 'e'))
2. [(2, 'a'), (3, 'b'), (4, 'c'), (5, 'd'), (6, 'e')][(2, 'a'), (3, 'b'), (4, 'c'), (5, 'd'), (6, 'e')]
3. >>>
- Python 学习笔记 - 7.Dictionary
Python 中的 Dictionary 和 .NET Hashtable / Dictionary 非常类似。
1. >>> a = {1:"a", 2:"b"}
2. >>> a[1]
3. 'a'
4. >>> b = {'a':100, 'b':200}
5. >>> b[2]
6.
7. Traceback (most recent call last):
8. File "<pyshell#93>", line 1, in <module>
9. b[2]
10.KeyError: 2
11.>>> b['b']
12.200
13.>>> a[1]='aaa'
14.>>> a
15.{1: 'aaa', 2: 'b'}
16.>>> del(a[1])
17.>>> a
18.{2: 'b'}
19.>>> a[1]='AAAA'
20.>>> a
21.{1: 'AAAA', 2: 'b'}
22.>>> a.has_key(1)
23.True
24.>>> a.keys()
25.[1, 2][1, 2]
26.>>> a.values()
27.['AAAA', 'b']['AAAA', 'b']
28.>>> a.items()
29.[(1, 'AAAA'), (2, 'b')][(1, 'AAAA'), (2, 'b')]
30.>>>
File "<pyshell#93>", line 1, in <module>
b[2]
Dictionary 的 key 是大小写敏感的。
1. >>> b = {"a":1, "A":2}
2. >>> b["A"]
3. 2
4. >>> b["a"]
5. 1
6. >>>
可以使用 Get() 方法避免触发 KeyError。
1. >>> b={'a':1,'A':2}
2. >>> b['c']
3.
4. Traceback (most recent call last):
5. File "<pyshell#112>", line 1, in <module>
6. b['c']
7. KeyError: 'c'
8. >>> b.get('c')
9. >>> b.get('c','default')
10.'default'
11.>>>
- Python 学习笔记 - 8.引用(Reference)
在 Python 中没有值类型、引用类型之类的区别。所有变量都只是指向对象内存地址的引用,而所有的对象都有一个唯一的序号,以及类型和值。对象类型并不能被修改,我们修改的不过是引用的内容而已。
1. >>> a = 1
2. >>> b = 1
3. >>> hash(a)
4. 1
5. >>> hash(b)
6. 1
7. >>> id(a)
8. 11228576
9. >>> id(b)
10.11228576
我们可以使用 sys.getrefcount() 查看对象引用计数。
1. >>> import sys
2. >>> class Class1:
3. pass
4.
5. >>> a = Class1()
6. >>> sys.getrefcount(a)
7. 2
8. >>> b = a
9. >>> sys.getrefcount(b)
10.3
11.>>>
我们可以进行 Shallow copy 或者 Deep Copy。
1. >>> class Data:
2. pass
3.
4. >>> class Class1:
5. def __init__(self):
6. self.Data = Data()
7.
8.
9. >>> a = Class1()
10.>>> import copy
11.>>> b = copy.copy(a)
12.>>> a is b
13.False
14.>>> a.Data is b.Data
15.True
16.>>> c = copy.deepcopy(a)
17.>>> c is a
18.False
19.>>> c.Data is a.Data
20.False
21.>>>
weak reference
弱引用使用的机会不是很多,一般用来进行 cache 编程。我们可以使用 weakref.ref() 来创建一个弱引用。
1. >>> import sys
2. >>> import weakref
3. >>> class Class1:
4. def Foo(self):
5. print "Foo..."
6.
7.
8. >>> o = Class1()
9. >>> sys.getrefcount(o)
10.2
11.>>> r = weakref.ref(o) # 创建一个弱引用
12.>>> sys.getrefcount(o) # 引用计数并没有改变
13.2
14.>>> r
15.<weakref at 01295840; to 'instance' at 00DC48A0>
16.>>> o2 = r() # 获取弱引用所指向的对象
17.>>> o2 is o
18.True
19.>>> sys.getrefcount(o)
20.3
21.>>> o = None
22.>>> o2 = None
23.>>> r # 当前对象引用计数为零时,弱引用失效
24.<weakref at 01295840; dead>
25.>>>
weakref 还提供了一个 proxy()。
1. >>> import sys
2. >>> import weakref
3. >>> class Class1:
4. def Foo(self):
5. print "Foo..."
6.
7.
8. >>> def callback(self):
9. print "callback..."
10.
11.
12.>>> o = Class1()
13.>>> p = weakref.proxy(o, callback)
14.>>> p.Foo()
15.Foo...
16.>>> o = None
17.callback...
18.>>>
Python 支持类似 Object Pascal 那样的全局函数,也就说我们可以用结构化方式写一些小程序。
1. >>> def Foo(s):
2. print s
3.
4.
5. >>> Foo("Hello Python!")
6. Hello Python!
7. >>>
Python 函数的参数也采取引用拷贝的方式,也就是说对参数变量赋值,并不会影响外部对象。
1. >>> def Fun(i):
2. print id(i)
3. i = 10
4.
5.
6. >>> a = 100
7. >>> id(a)
8. 11229556
9. >>> Fun(a)
10.11229556
11.>>> a
12.100
13.>>>
当然,函数参数和原变量同时指向同一对象,我们是可以改变该对象成员的。
1. >>> class Data:
2. def __init__(self):
3. self.i = 10
4.
5.
6. >>> def Fun(d):
7. d.i = 100
8.
9.
10.>>> d = Data()
11.>>> d.i
12.10
13.>>> Fun(d)
14.>>> d.i
15.100
16.>>>
我们可以使用 global 关键词来实现类似 C# ref/out 的功能。
1. >>> def Foo():
2. global i
3. i = 100
4.
5.
6. >>> i = 10
7. >>> Foo()
8. >>> i
9. 100
10.>>>
Python 不支持方法重载,但支持缺省参数和一些特殊的调用方式。
1. >>> def Foo(a, b= 1, c = 2):
2. print "a=%s, b=%s, c=%s"%(a, b ,c)
3.
4.
5. >>> Foo(0, 0 ,7)
6. a=0, b=0, c=7
7. >>> Foo(0, 0)
8. a=0, b=0, c=2
9. >>> Foo(7)
10.a=7, b=1, c=2
11.>>> Foo(c = 3, a = 4)
12.a=4, b=1, c=3
13.>>>
Python 还支持类似 C# params 那样的可变参数数组。
1. >>> def MyFun1(*i):
2. print type(i)
3. for n in i: print n
4.
5.
6. >>> MyFun1(1,2,3,4)
7. <type 'tuple'>
8. 1
9. 2
10.3
11.4
12.
13.>>> def MyFun2(**i):
14. print type(i)
15. for(m, n) in i.items():
16. print m, "=", n
17.
18.
19.>>> MyFun2(a=1, b=2, c=3)
20.<type 'dict'>
21.a = 1
22.c = 3
23.b = 2
24.>>>
Python 提供了一个内置函数 apply() 来简化函数调用。
1. >>> def Fun(a, b, c):
2. print a, b, c
3.
4.
5. >>> a = ("l", "M", "n")
6. >>> Fun(a[0], a[1], a[2])
7. l M n
8. >>> apply(Fun, a)
9. l M n
10.>>>
Lambda 是个非常实用的语法,可以写出更简练的代码。
1. >>> def Do(fun, nums):
2. for i in range(len(nums)):
3. nums[i] = fun(nums[i])
4. print nums
5.
6.
7. >>> def Fun(i):
8. return i*10
9.
10.>>> Do(Fun, [1, 2, 3])
11.[10, 20, 30][10, 20, 30]
12.>>> Do(lambda i: i*10, [1, 2, 3]) # 使用 lambda
13.[10, 20, 30][10, 20, 30]
14.>>>
还有一点比较有意思,由于 Python 函数无需定义返回值,因此我们可以很容易地返回多个结果。这种方式也可以从一定程度上替代 ref/out 的功能。
1. >>> def Fun():
2. return 1, 2, 3
3.
4. >>> a = Fun()
5. >>> type(a)
6. <type 'tuple'>
7. >>> a
8. (1, 2, 3)(1, 2, 3)
9. >>>
- Python 学习笔记 - 10.类(Class)
定义
Python 的 Class 比较特别,和我们习惯的静态语言类型定义有很大区别。
1. 使用一个名为 __init__ 的方法来完成初始化。
2. 使用一个名为 __del__ 的方法来完成类似析购操作。
3. 所有的实例方法都拥有一个 self 参数来传递当前实例,类似于 this。
4. 可以使用 __class__ 来访问类型成员。
1. >>> class MyClass:
2. def __init__(self):
3. print "initialize...."
4. def Foo(self):
5. print id(self)
6.
7.
8. >>> a = MyClass()
9. initialize....
10.>>> a.Foo()
11.14412576
12.>>> id(a)
13.14412576
Class 有一些特殊的属性,便于我们获得一些额外的信息。
1.
2. >>> class MyClass(object):
3. """This is MyClass's Docoment"""
4. def __init__(self):
5. self.i = 1234
6.
7.
8. >>> MyClass.__doc__ # 类型帮助信息
9. "This is MyClass's Docoment""This is MyClass's Docoment"
10.>>> MyClass.__name__ # 类型名称
11.'MyClass'
12.>>> MyClass.__module__ # 类型所在模块
13.'__main__'
14.>>> MyClass.__bases__ # 类型所继承的基类(Python 支持多继承)
15.(<type 'object'>,)
16.>>> MyClass.__dict__ # 类型字典,存储所有类型成员信息
17.<dictproxy object at 0x00DC1AD0>
18.>>> #以下是实例拥有的属性
19.>>> MyClass().__class__ # 实例的类型
20.<class '__main__.MyClass'>
21.>>> MyClass().__module__ # 实例类型所在模块
22.'__main__'
23.>>> MyClass().__dict__ # 对象字典,存储所有实例成员信息
24.{'i': 1234}
25.>>>
继承
Python 支持多继承,但有几点需要注意:
1. 基类 __init__ / __del__ 需显示调用。
2. 继承方法的调用和基类声明顺序有关。
1. >>> class Base1:
2. def __init__(self):
3. print "Base1"
4. def test(self):
5. print "Base1 test..."
6.
7.
8. >>> class Base2:
9. def __init__(self):
10. print "Base2"
11. def test(self):
12. print "Base2 test..."
13.
14.
15.>>> class MyClass(Base2,Base1):
16. def __init__(self):
17. Base1.__init__(self)
18. Base2.__init__(self)
19. print "MyClass"
20.
21.
22.>>> a = MyClass()
23.Base1
24.Base2
25.MyClass
26.>>> a.test()
27.Base2 test...
28.>>> # 下面把 Base1 放在前面
29.>>> class MyClass(Base1,Base2):
30. def __init__(self):
31. Base1.__init__(self)
32. Base2.__init__(self)
33. print "MyClass"
34.
35.
36.>>> a = MyClass()
37.Base1
38.Base2
39.MyClass
40.>>> a.test()
41.Base1 test...
42.>>>
成员
Python Class 同样包含类型和实例两种成员。
1. >>> class Class1:
2. i = 123 # 类成员
3. def __init__(self):
4. self.i = 100 # 实例成员
5.
6.
7. >>> print Class1.i
8. 123
9. >>> print Class1().i
10.100
11.>>>
有几个很 "特殊" 的 "规则" 需要注意。
(1) 我们可以通过实例引用访问类型成员。因此下面的例子中 self.i 实际指向 Class1.i,直到我们为实例新增了一个成员 i。
1. >>> class Class1:
2. i = 123
3. def __init__(self):
4. print self.i
5. print hex(id(self.i))
6.
7.
8. >>> hex(id(Class1.i)) # 显示 Class1.i 的地址
9. '0xab5860'
10.>>> a = Class1() # 创建 Class1 实例,我们会发现 self.i 实际指向 Class1.i
11.123
12.0xab5860
13.>>> Class1.__dict__ # 显示 Class1 成员
14.{'i': 123, '__module__': '__main__', '__doc__': None, '__init__': <function __init__ at 0x012911B0>}
15.>>> a.__dict__ # 显示实例成员
16.{}
17.>>> a.i = 100 # 为实例新增加一个成员i
18.>>> hex(id(a.i)) # 显示新成员i的地址
19.'0xab5974'
20.>>> a.__dict__ # 显示实例成员
21.{'i': 100}
22.>>>
(2) 调用类型内部方法,需要省略 self 参数。
1. >>> class Class1:
2. def __init__(self):
3. self.__test("Hello Python")
4. def __test(self, s):
5. print s
6.
7.
8. >>> Class1()
9. Hello Python
10.<__main__.Class1 instance at 0x00DC3800>
11.>>>
我们可以在成员名称前添加 "__" 使其成为私有成员。
1. >>> class Class1:
2. __i = 123
3. def __init__(self):
4. self.__x = 0
5. def __test(self):
6. print id(self)
7.
8.
9. >>> Class1.i
10.
11.Traceback (most recent call last):
12. File "<pyshell#203>", line 1, in <module>
13. Class1.i
14.AttributeError: class Class1 has no attribute 'i'
15.>>> Class1().__x
16.
17.Traceback (most recent call last):
18. File "<pyshell#204>", line 1, in <module>
19. Class1().__x
20.AttributeError: Class1 instance has no attribute '__x'
21.>>> Class1().__test()
22.
23.Traceback (most recent call last):
24. File "<pyshell#205>", line 1, in <module>
25. Class1().__test()
26.AttributeError: Class1 instance has no attribute '__test'
27.>>>
File "<pyshell#203>", line 1, in <module>
Class1.i
File "<pyshell#204>", line 1, in <module>
Class1().__x
File "<pyshell#205>", line 1, in <module>
Class1().__test()
事实上这只是一种规则,并不是编译器上的限制。我们依然可以用特殊的语法来访问私有成员。
1. >>> Class1._Class1__i
2. 123
3. >>> a = Class1()
4. >>> a._Class1__x
5. 0
6. >>> a._Class1__test()
7. 14432256
8. >>>
除了静态(类型)字段,我们还可以定义静态方法。
1. >>> class Class1:
2. @staticmethod
3. def test():
4. print "In Static method..."
5.
6.
7. >>> Class1.test()
8. In Static method...
9. >>>
从设计的角度,或许更希望用属性(property)来代替字段(field)。
1. >>> class Class1:
2. def __init__(self):
3. self.__i = 1234
4. def getI(self): return self.__i
5. def setI(self, value): self.__i = value
6. def delI(self): del self.__i
7. I = property(getI, setI, delI, "Property I")
8.
9.
10.>>> a = Class1()
11.>>> a.I
12.1234
13.>>> a.I = 1000
14.>>> a.I
15.1000
16.>>>
如果只是 readonly property,还可以用另外一种方式。
1. >>> class Class1:
2. def __init__(self):
3. self.__i = 1234
4. @property
5. def I(self):
6. return self.__i
7.
8.
9. >>> a = Class1()
10.>>> a.I
11.1234
12.>>>
用 __getitem__ 和 __setitem__ 可以实现 C# 索引器的功能。
1. >>> class Class1:
2. def __init__(self):
3. self.__x = ["a", "b", "c"]
4. def __getitem__(self, key):
5. return self.__x[key]
6. def __setitem__(self, key, value):
7. self.__x[key] = value
8.
9.
10.>>> a = Class1()
11.>>> a[1]
12.'b'
13.>>> a[1] = "xxx"
14.>>> a[1]
15.'xxx'
16.>>>
重载
Python 支持一些特殊方法和运算符重载。
1. >>> class Class1:
2. def __init__(self):
3. self.i = 0
4. def __str__(self):
5. return "id=%i"%(id(self))
6. def __add__(self, other):
7. return self.i + other.i
8.
9.
10.>>> a = Class1()
11.>>> a.i = 10
12.>>> str(a)
13.'id=19481664'
14.>>> b = Class1()
15.>>> b.i = 20
16.>>> a + b
17.30
18.>>>
通过重载 "__eq__",我们可以改变 "==" 运算符的行为。
1. >>> class Class1:
2. pass
3.
4. >>> a = Class1()
5. >>> b = Class1()
6. >>> a ==b
7. False
8. >>> # 实现操作符__eq__重载
9. >>> class Class1:
10. def __eq__(self, other):
11. return True
12.
13.
14.>>> a = Class1()
15.>>> b = Class1()
16.>>> a == b
17.True
18.>>>
Open Class
这是个有争议的话题。在 Python 中,我们随时可以给类型或对象添加新的成员。
1. 添加字段
1. >>> class Class1:
2. pass
3.
4. >>> a = Class1()
5. >>> a.x = 10
6. >>> a.x
7. 10
8. >>> dir(a)
9. ['__doc__', '__module__', 'x']['__doc__', '__module__', 'x']
10.>>> b = Class1()
11.>>> dir(b)
12.['__doc__', '__module__']['__doc__', '__module__']
13.>>> del a.x
14.>>> dir(a)
15.['__doc__', '__module__']['__doc__', '__module__']
16.>>> dir(Class1)
17.['__doc__', '__module__']['__doc__', '__module__']
18.>>> Class1.x = 100
19.>>> Class1.x
20.100
21.>>> dir(Class1)
22.['__doc__', '__module__', 'x']['__doc__', '__module__', 'x']
23.>>>
2. 添加方法
1. >>> class Class1:
2. pass
3.
4. >>> def test():
5. print "test..."
6.
7.
8. >>> def hello(self):
9. print "hello ",id(self)
10.
11.
12.>>> Class1.test = test
13.>>> a = Class1()
14.>>> dir(a)
15.['__doc__', '__module__', 'test']['__doc__', '__module__', 'test']
16.>>> b = Class1()
17.>>> a.hello = hello
18.>>> dir(a)
19.['__doc__', '__module__', 'hello', 'test']['__doc__', '__module__', 'hello', 'test']
20.>>> a.hello()
21.
22.Traceback (most recent call last):
23. File "<pyshell#340>", line 1, in <module>
24. a.hello()
25.TypeError: hello() takes exactly 1 argument (0 given)
26.>>> a.hello(a)
27.hello 19474632
28.>>> a.hello(b)
29.hello 19481584
30.>>> dir(b)
31.['__doc__', '__module__', 'test']['__doc__', '__module__', 'test']
32.>>> b.test()
33.
34.Traceback (most recent call last):
35. File "<pyshell#344>", line 1, in <module>
36. b.test()
37.TypeError: test() takes no arguments (1 given)
38.>>>
File "<pyshell#340>", line 1, in <module>
a.hello()
19474632
19481584
File "<pyshell#344>", line 1, in <module>
b.test()
3. 改变现有方法
1. >>> class Class1:
2. def test(self):
3. print "a"
4.
5.
6. >>> def test(self):
7. print "b"
8.
9.
10.>>> Class1.test = test
11.>>> Class1().test()
12.b
13.>>>
另外,有几个内建函数方便我们在运行期进行操作。
1. >>> hasattr(a, "x")
2. False
3. >>> a.x = 10
4. >>> getattr(a, "x")
5. 10
6. >>> setattr(a, "b", 1234)
7. >>> a.b
8. 1234
9. >>>
Python Open Class 是如何实现的呢?我们看一下下面的代码。
1. >>> class Class1:
2. pass
3.
4. >>> a = Class1()
5. >>> a.__dict__
6. {}
7. >>> a.x = 123
8. >>> a.__dict__
9. {'x': 123}
10.>>> a.test = lambda i: i*10
11.>>> a.test(1)
12.10
13.>>> a.__dict__
14.{'test': <function <lambda> at 0x012912F0>, 'x': 123}
15.>>>
原来,Python Class 对象或类型通过内置成员 __dict__ 来存储成员信息。
我们还可以通过重载 __getattr__ 和 __setattr__ 来拦截对成员的访问,需要注意的是 __getattr__ 只有在访问不存在的成员时才会被调用。
1. >>> class Class1:
2. def __getattr__(self, name):
3. print "__getattr__", name
4. return None
5. def __setattr__(self, name, value):
6. print "__setattr__", name, value
7. self.__dict__[name] = value
8.
9.
10.>>> a = Class1()
11.>>> a.x
12.__getattr__ x
13.>>> a.x = 123
14.__setattr__ x 123
15.>>> a.x
16.123
17.>>>
如果类型继承自 object,我们可以使用 __getattribute__ 来拦截所有(包括不存在的成员)的获取操作。
注意在 __getattribute__ 中不要使用 "return self.__dict__[name]" 来返回结果,因为在访问 "self.__dict__" 时同样会被 __getattribute__ 拦截,从而造成无限递归形成死循环。
1. >>> class Class1(object):
2. def __getattribute__(self, name):
3. print "__getattribute", name
4. return object.__getattribute__(self, name)
5.
6.
7. >>> a = Class1()
8. >>> a.x
9. __getattribute x
10.
11.Traceback (most recent call last):
12. File "<pyshell#396>", line 1, in <module>
13. a.x
14. File "<pyshell#394>", line 4, in __getattribute__
15. return object.__getattribute__(self, name)
16.AttributeError: 'Class1' object has no attribute 'x'
17.>>> a.x = 123
18.>>> a.x
19.__getattribute x
20.123
21.>>>
- Python 学习笔记 - 11.模块(Module)
- Python 的 Module 更像 Object Pascal Unit,和 C# namespace 那种纯粹作为编译器名称识别符不同,Module 本身就是一种类型。
- >>> import types
- >>> types.ModuleType
- <type 'module'>
- >>> type(types)
- <type 'module'>
- >>>
- 我们可以在 Module 中定义变量、方法、类以及其他执行代码。
- >>> i = 15
- >>> def test():
- pass
- >>> class Class1:
- pass
- >>> print "Hello Python"
- Hello Python
-
通过 __name__ 可以判断当前 module 是被 import 还是 execute。- >>> if __name__=="__main__":
- print "Execute"
- else:
- print "Import"
- Execute
- >>>
-
可以使用 dir() 方法查看 module 的成员。- >>> import sys
- >>> dir(sys)
- ['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdout__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder', 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_clear', 'exc_info', 'exc_traceback', 'exc_type', 'exc_value', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefaultencoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'hexversion', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_cache', 'platform', 'prefix', 'setcheckinterval', 'setprofile', 'setrecursionlimit', 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoptions', 'winver']
- >>> dir()
- ['Class1', '__builtins__', '__doc__', '__name__', 'i', 'sys', 'test']
-
作为引入机制,我们可以用两种方法来导入其他 module 成员。- >>> import sys
- >>> sys.version
- '2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]'
- >>> from sys import version
- >>> version
- '2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]'
- >>> from sys import *
- >>> winver
- '2.5'
- >>>
- 除了使用 import 关键字以外,我们还可以使用内建函数 __import__() 来导入 module。两者的区别是,import 后面跟的必须是一个类型(type),而__import__() 的参数是一个字符串,这个字符串可能来自配置文件,也可能是某个表达式计算结果,这显然为我们提供了更大的灵活性。
- >>> m1=__import__("sys")
- >>> type(m1)
- <type 'module'>
- >>> m1.winver
- '2.5'
- >>>
- 使用 import 导入 module 时,Python 会将要导入的 module 编译成字节码,这种二进制文件(.pyc)虽然没有提高执行速度,但能加快装载速度。我们还可以调用相关方法来完成编译行为。
- >>> import py_compile
- >>> py_compile.compile("e:""Users""py""hello.py") # 编译单个 .py 文件
- >>> import compileall
- >>> compileall.compile_dir("e:""Users""py") # 编译指定目录下的所有 .py 文件
- Listing e:"Users"py ...
- 1
- >>>
-
Python 通过 PYTHONPATH 环境变量来查找 module,我们可以使用 sys.path 来查看或添加新的路径。- >>> sys.path
- ['D:""Python25""Lib""idlelib', 'C:""WINDOWS""system32""python25.zip', 'D:""Python25""DLLs', 'D:""Python25""lib', 'D:""Python25""lib""plat-win', 'D:""Python25""lib""lib-tk', 'D:""Python25', 'D:""Python25""lib""site-packages']
- >>> sys.path.append("e:""Users""py")
- >>> sys.path
- ['D:""Python25""Lib""idlelib', 'C:""WINDOWS""system32""python25.zip', 'D:""Python25""DLLs', 'D:""Python25""lib', 'D:""Python25""lib""plat-win', 'D:""Python25""lib""lib-tk', 'D:""Python25', 'D:""Python25""lib""site-packages', 'e:""Users""py']
- >>>
- Package
我们可以将多个 module 组合成一个 package。
方法很简单:
1. 在 Python"Lib 或者其他可以被搜索到的路径下创建一个子文件夹,文件夹名就是包名称。
2. 将所有需要加入的 module 放到该子文件夹中。
3. 创建一个包含代码或为空的 __init__.py 文件。在第一次 import 该包时,该文件会被自动执行。
在 import 该包的时候,需要添加包名称前缀。 - >>> import mypackage
- >>> import mypackage.module1
- >>> from mypackage import *
- >>> from mypackage.module1 import *
- Python 学习笔记 - 12.流程控制(Control Flow)
if...elif...else
1. >>> def test(i):
2. if 0<i<10:
3. print "small.."
4. elif 10<=i<20:
5. print "midle.."
6. elif 20<=i<30:
7. print "large.."
8. else:
9. print "invalid.."
10.
11.
12.>>> test(15)
13.midle..
14.>>>
for...in...
1. >>> for i in range(4):
2. print i
3.
4.
5. 0
6. 1
7. 2
8. 3
9. >>>
10.>>> for k, v in {1:"a", 2: "b", 3:"m"}.items():
11. print "%d=%s"%(k,v)
12.
13.
14.1=a
15.2=b
16.3=m
17.>>>
当然,我们可以用 range() 来实现 C# for(++)/for(--) 的效果。
1. >>> for i in range(len(a)):
2. print "%d: %s"%(i, a[i])
3.
4.
5. 0: a
6. 1: b
7. 2: c
8. >>>
9. >>> for i in range(len(a)-1, -1, -1):
10. print "%d: %s"%(i, a[i])
11.
12.
13.2: c
14.1: b
15.0: a
16.>>>
while
1. >>> while i < 5:
2. print i
3. i=i+1;
4.
5.
6. 0
7. 1
8. 2
9. 3
10.4
11.>>>
12.>>> while True:
13. print i
14. i +=1;
15. if i == 5:break
16.
17.
18.0
19.1
20.2
21.3
22.4
23.>>>
continue, break
和大多数语言一样,Python 循环同样支持 continue 和 break。这没什么好说的。
Changing horses in midstream
我们看一个有意思的例子。
1. >>> a=range(3)
2. >>> for i in a:
3. print i
4. a=range(10)
5.
6.
7. 0
8. 1
9. 2
10.>>>
你会发现在循环体内部对 a 的修改并没有起到作用,为什么会这样呢?改一下代码就明白了。
1. >>> a=range(3)
2. >>> hex(id(a))
3. '0xdc36e8'
4. >>> for i in a:
5. print i
6. a=range(19)
7. print(id(a))
8.
9.
10.0
11.14411376
12.1
13.14431896
14.2
15.14386240
16.>>>
哦~~~ 原来内部所谓修改的 a 完全是一个新的对象,自然不会影响到循环体本身了。这和 Python 变量的作用范围有关。
xrange()
如果你用 range() 创建一个很大的列表时,你会发现内存一下涨了很多~~~~~ ,这时候你应该用 xrange() 来代替。虽然这两者从表面看没什么区别,但实际上他们生成的结果类型并不一样。
1. >>> type(range(10))
2. <type 'list'>
3. >>> type(xrange(10))
4. <type 'xrange'>
5. >>>
- Python 学习笔记 - 13.异常(Exception)
Python 的异常处理机制和 C# 类似。
1. >>> try:
2. raise Exception("a", "b")
3. except Exception,e:
4. print e
5. finally:
6. print "final..."
7.
8.
9. ('a', 'b')('a', 'b')
10.final...
11.>>>
except Exception,e:
finally:
同样可以处理多个异常筛选。
1. >>> try:
2. raise EOFError("aa", "bb")
3. except RuntimeError, e:
4. print "[RuntimeErro]: ", e
5. except EOFError, e:
6. print "[EOFError]: ", e
7. except Exception, e:
8. print "[Error]: ", e
9. finally:
10. print "final..."
11.
12.
13.[EOFError]: ('aa', 'bb')
14.final...
15.>>>
except RuntimeError, e:
except EOFError, e:
except Exception, e:
finally:
('aa', 'bb')
除了异常参数,我们还可以用sys的一些方法来获取异常信息。
1. >>> import sys
2. >>> try:
3. raise RuntimeError("the runtime error raised")
4. except:
5. print sys.exc_info()
6.
7.
8. (<type 'exceptions.RuntimeError'>, RuntimeError('the runtime error raised',), <traceback object at 0x00DC5CB0>)
9. >>>
except:
缺省情况下,异常类都继承自 Exception。
1. >>> class MyException(Exception):
2. pass
3.
4. >>> try:
5. raise MyException("My Exception raised!")
6. except:
7. print sys.exc_info()
8.
9.
10.(<class '__main__.MyException'>, MyException('My Exception raised!',), <traceback object at 0x00DC58F0>)
11.>>>
- Python 学习笔记 - 14.技巧(Tips)
多变量赋值
1. >>> a = b = c = 1
2. >>> print a, b, c
3. 1 1 1
4. >>> (a, b, c) = range(3)
5. >>> print a, b, c
6. 0 1 2
7. >>> (a, b, c) = ("a", "b", "c")
8. >>> print a, b, c
9. a b c
连接字符串
1. >>> (a, b, c) = ("a", "b", "c")
2. >>> print a, b, c
3. a b c
4. >>> s = ("a", "b", "c")
5. >>> ",".join(s)
6. 'a,b,c'
7. >>> s = {1:"a", 2:"b", 3:"c"}
8. >>> ",".join(["%d:%s" % (k, v) for k, v in s.items()])
9. '1:a,2:b,3:c'
使用 0 < i < 10 要比使用 i > 0 and i < 10 性能更好一些
1. >>> def test(i):
2. if (0 < i < 10):
3. print "ok"
4. else:
5. print "..."
6.
7. >>> test(4)
8. ok
9. >>> test(12)
10....
11.>>> test(0)
12....
if (0 < i < 10):
print "ok"
else:
print "..."
不要使用 ++i 来递增
Python 虽然支持 ++i,但实际表示的意思是 +(+i),我们可以使用 i += 1 来实现递增。
1. >>> i = -10
2. >>> ++i
3. -10
4. >>> i += 1
5. >>> i
6. -9