Python学习总结
先说Python的安装,如果是linux用户,可以命令行输入python -V ,看看是否安装,没有显示版本号的话那就是没有装了,这种情况比较少遇到,这时候你可以直接网上安装,或者编译源码安装。如果是windows用户可以访问Python.org/download,从网站上下载最新的版本。在Windows命令行中使用Python如果你想要从Windows命令行调用Python,那么你需要先正确的设置PATH变量。
点击控制面板->系统->高级->环境变量。在“系统变量”表单中点击叫做PATH的变量,然后编辑这个变量,把;C:\Python23加到它的结尾。当然,是Python所在的正确目录名。
windows下可以有Python的IDE写,也可以使用命令行进行,不细说,主要说linux。linux下也可以直接在终端运行python进入解释器进行编写,也可以使用IDE或者VIM。首先开始Python的hello world
$ python
>>> print 'hello world'
hello world
>>>
>>>是Python的命令提示符。
另外也可以编写到Python程序文件里运行:
#!/usr/bin/python
# Filename : helloworld.py
print 'Hello World'
类似shell的脚本文件,需要使用chmod +x 给相应文件的可执行权限。给了执行权限后就可以:$ python helloworld.py 这样运行了,或者直接./helloworld.py 运行。同样的你可以修改环境变量PATH,然后直接运行helloworld.py,或者去掉后缀会让你看着更舒服一点。
如果需要看Python内的东西的帮助,使用help(),几乎可查到所有东西。按q键退出帮助信息。比如:help(str) 或 help('print') 。你可能注意到为什么前者没有引号而后者有,主要是为了告诉解释器这个print不是用来输入的。
在Python中有4种类型的数——整数、长整数、浮点数和复数。(-5+4j)和(2.3-4.6j)是复数的例子。
字符串这种数据类型也必不可少,字符串用单引号(')或双引号(")引起来的内容,所有的空白,即空格和制表符都照原样保留。有一个特殊的就是三引号('''三个单引号或"""三个双引号)。利用三引号,你可以指示一个多行的字符串。你可以在三引号中自由的使用单引号和双引号。例如:
'''This is a multi-line string. This is the first line.
This is the second line.
"What's your name?," I asked.
He said "Bond, James Bond."
'''
有了字符串,那转义符也必不可少了,比如字符串里想使用单引号,雷同其他语言\'即可。还有值得注意的一件事是,在一个字符串中,行末的单独一个反斜杠表示字符串在下一行继续,而不是开始一个新的行。这对有各种语言基础的你可能就是废话了,还是提一下。
Python有个新的(对我来说)字符串概念,自然字符串:如果你想要指示某些不需要如转义符那样的特别处理的字符串,那么你需要指定一个自然字符串。自然字符串通过给字符串加上前缀r或R来指定。例如r"Newlines are indicated by \n"。
好吧,关于字符串不止一个新的概念对我来说,Unicode字符串:Unicode是书写国际文本的标准方法。如果你想要用你的母语如北印度语或阿拉伯语写文本,那么你需要有一个支持Unicode的编辑器。类似地,Python允许你处理Unicode文本——你只需要在字符串前加上前缀u或U。例如,u"This is a Unicode string."。
记住,在你处理文本文件的时候使用Unicode字符串,特别是当你知道这个文件含有用非英语的语言写的文本。
有一点是要注意的,字符串是不可变的。这意味着一旦你创造了一个字符串,你就不能再改变它了。
和shell一样,如果你把两个字符串按字面意义相邻放着,他们会被Python自动级连。例如,'What\'s' 'your name?'会被自动转为"What's your name?"。
给C/C++程序员的注释
在Python中没有专门的char数据类型。确实没有需要有这个类型,我相信你不会为此而烦恼。
给Perl/PHP程序员的注释
记住,单引号和双引号字符串是完全相同的——它们没有在任何方面有不同。
给正则表达式用户的注释
一定要用自然字符串处理正则表达式。否则会需要使用很多的反斜杠。例如,后向引用符可以写成'\\1'或r'\1'。
Python字符串对象还有很多成员函数,详细使用查看help(str)
关于Python的变量,起名规则还是国际管理,不再赘述。也不需要声明,所以不用指定类型的随便使用。
1 2 3 4 5 6 7 8 9 |
# Filename : var.py i = 5 print i i = i + 1 print i i = '''This is a multi-line string. This is the second line.''' print i |
Python可以使用分号;来明确程序的分句,但是惯例是尽量不使用分号的。
缩进在其他语言可能还没什么特别说明,只是为了好看,但是在Python里必须特别注意,在逻辑行首的空白(空格和制表符)用来决定逻辑行的缩进层次,从而用来决定语句的分组。这意味着同一层次的语句必须有相同的缩进。每一组这样的语句称为一个块。你需要记住的一样东西是错误的缩进会引发错误:SyntaxError: invalid syntax
新的缩进不是可以随意开启的,除了住语句块这个。开启新的缩进你可能也会想到,就是if拉,for拉之类的。另外不要混合使用制表符和空格来缩进,因为这在跨越不同的平台的时候,无法正常工作。
关于Python的操作符差不多也是大家熟悉的,+-*/都有,按位操作的^&|~也都有,位移<<, >>也有,比较符号,逻辑运算等。这里特别指出几个:
** ,就是指数运算了,2**3 =8
// ,就是除法取整运算符,这里说一下/ ,如果4/3 得1 没什么问题,如果4.0/3 或者 4/3.0 就会得到1.333333... 这样,但是使用//整除,就只会得到1.0。
还有就是 or and 和 not,就是或与非了。
关于这些优先级,基本上都是你熟悉的那些,如果你实在把不准你表达式的运算顺序,那你还是用括号吧。
在Python中有三种控制流语句——if、for和while。
if语句的语法给个例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#!/usr/bin/python # Filename: if.py number = 23 guess = int(raw_input('Enter an integer : ')) if guess == number: print 'Congratulations, you guessed it.' # New block starts here print "(but you do not win any prizes!)" # New block ends here elif guess < number: print 'No, it is a little higher than that' # Another block # You can do whatever you want in a block ... else: print 'No, it is a little lower than that' # you must have guess > number to reach here print 'Done' # This last statement is always executed, after the if statement is executed |
再提一下,缩进很重要,同样的缩进解释器会认识它们是同一语句块。if后边没有括号,else if 缩写成elif类似shell。
while语句只要在一个条件为真的情况下,while语句允许你重复执行一块语句。while语句是所谓 循环 语句的一个例子。while语句有一个可选的else从句:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
#!/usr/bin/python # Filename: while.py number = 23 running = True while running: guess = int(raw_input('Enter an integer : ')) if guess == number: print 'Congratulations, you guessed it.' running = False # this causes the while loop to stop elif guess < number: print 'No, it is a little higher than that' else: print 'No, it is a little lower than that' else: print 'The while loop is over.' # Do anything else you want to do here print 'Done' |
其实后边while的else从句比较多余,估计是一般不会用。。。
for循环:
1 2 3 4 5 6 7 |
#!/usr/bin/python # Filename: for.py for i in range(1, 5): print i else: print 'The for loop is over' |
Python的for循环从根本上不同于C/C++的for循环。C#程序员会注意到Python的for循环与C#中的foreach循环十分类似。Java程序员会注意到它与Java 1.5中的for (int i : IntArray)相似。在C/C++中,如果你想要写for (int i = 0; i < 5; i++),那么用Python,你写成for i in range(0,5)。你会注意到,Python的for循环更加简单、明白、不易出错。 else从句用样让人感觉到多余。
循环语句中Python支持break和continue
Python使用def关键字来定义函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
#!/usr/bin/python # Filename: function1.py def sayHello(): print 'Hello World!' # block belonging to the function sayHello() # call the function def printMax(a, b): if a > b: print a, 'is maximum' else: print b, 'is maximum' printMax(3, 4) # directly give literal values x = 5 y = 7 printMax(x, y) # give variables as arguments |
有了函数概念之后,自然的让人想到局部变量和全局变量,Python同样有这些,细节和其他语言差不多。如果你想在内部使用全局变量,可以使用关键字个global。
Python函数同样支持默认参数。类似这样def say(message, times = 1):。另外还有一个概念是关键参数,例子说明:
1 2 3 4 5 6 7 8 9 |
#!/usr/bin/python # Filename: func_key.py def func(a, b=5, c=10): print 'a is', a, 'and b is', b, 'and c is', c func(3, 7) func(25, c=24) func(c=50, a=100) |
输出就是:
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50
即你可以指定对参数的赋值顺序。
每个函数都暗含一个return,如果你没指定的话。Python里边有个特殊关键字pass,表示一个空语句块,可以使用pass写一个空函数之类的。
Python有一个很奇妙的特性,称为 文档字符串 ,它通常被简称为 docstrings 。DocStrings是一个重要的工具,由于它帮助你的程序文档更加简单易懂,你应该尽量使用它。你甚至可以在程序运行的时候,从函数恢复文档字符串!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#!/usr/bin/python # Filename: func_doc.py def printMax(x, y): '''Prints the maximum of two numbers. The two values must be integers.''' x = int(x) # convert to integers, if possible y = int(y) if x > y: print x, 'is maximum' else: print y, 'is maximum' printMax(3, 5) print printMax.__doc__ |
输出:
$ python func_doc.py 5 is maximum Prints the maximum of two numbers. The two values must be integers.
其实就类似一个你写的注释,也类似函数帮助之类的,你可以在程序中查看这个内容。__doc__(注意双下划线)调用printMax函数的文档字符串属性
文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。 强烈建议 你在你的函数中使用文档字符串时遵循这个惯例。
如果你已经在Python中使用过help(),那么你已经看到过DocStings的使用了!它所做的只是抓取函数的__doc__属性,然后整洁地展示给你。你可以对上面这个函数尝试一下——只是在你的程序中包括help(printMax)。记住按q退出help。
自动化工具也可以以同样的方式从你的程序中提取文档。因此,我 强烈建议 你对你所写的任何正式函数编写文档字符串。随你的Python发行版附带的pydoc命令,与help()类似地使用DocStrings。
有了函数,我们可以重用我们的代码,但是如何像C/C++那样更多的重用我们写的函数呢?其实雷同,使用import来引用我们写的一个单独的Python函数文件就行了。首先我们先使用标准库模块:
1 2 3 4 5 6 7 8 9 10 |
#!/usr/bin/python # Filename: using_sys.py import sys print 'The command line arguments are:' for i in sys.argv: print i print '\n\nThe PYTHONPATH is', sys.path, '\n' |
输出
$ python using_sys.py we are arguments The command line arguments are: using_sys.py we are arguments The PYTHONPATH is ['/home/swaroop/byte/code', '/usr/lib/python23.zip', '/usr/lib/python2.3', '/usr/lib/python2.3/plat-linux2', '/usr/lib/python2.3/lib-tk', '/usr/lib/python2.3/lib-dynload', '/usr/lib/python2.3/site-packages', '/usr/lib/python2.3/site-packages/gtk-2.0']
首先,我们利用import语句 输入 sys模块。基本上,这句语句告诉Python,我们想要使用这个模块。sys模块包含了与Python解释器和它的环境有关的函数。
当Python执行import sys语句的时候,它在sys.path变量中所列目录中寻找sys.py模块。如果找到了这个文件,这个模块的主块中的语句将被运行,然后这个模块将能够被你 使用 。注意,初始化过程仅在我们 第一次 输入模块的时候进行。另外,“sys”是“system”的缩写。
sys模块中的argv变量通过使用点号指明——sys.argv——这种方法的一个优势是这个名称不会与任何在你的程序中使用的argv变量冲突。另外,它也清晰地表明了这个名称是sys模块的一部分。
sys.argv变量是一个字符串的 列表 (列表会在后面的章节详细解释)。特别地,sys.argv包含了 命令行参数 的列表,即使用命令行传递给你的程序的参数。
如果你使用IDE编写运行这些程序,请在菜单里寻找一个指定程序的命令行参数的方法。
这里,当我们执行python using_sys.py we are arguments的时候,我们使用python命令运行using_sys.py模块,后面跟着的内容被作为参数传递给程序。Python为我们把它存储在sys.argv变量中。
记住,脚本的名称总是sys.argv列表的第一个参数。所以,在这里,'using_sys.py'是sys.argv[0]、'we'是sys.argv[1]、'are'是sys.argv[2]以及'arguments'是sys.argv[3]。注意,Python从0开始计数,而非从1开始。
sys.path包含输入模块的目录名列表。我们可以观察到sys.path的第一个字符串是空的——这个空的字符串表示当前目录也是sys.path的一部分,这与PYTHONPATH环境变量是相同的。这意味着你可以直接输入位于当前目录的模块。否则,你得把你的模块放在sys.path所列的目录之一。
这里我自己写了一个test.py模块进行自己的模块测试,发现总是自动生成一个test.pyc的文件,查了一下知道这个是Python自动给的一个字节编译文件,与平台无关,可以加速模块的使用。引用的时候直接 import test 即可,不要带.py。另外如果你的模块名字是test,没有.py后缀,也是可以引用的,但是不会自动生成加速的字节编译文件.pyc,至少我测试的是这种情况。引用自己写的模块的内容一样是引用名加点.加模块内内容名。如:test.hello() 或 test.version 。
如果你想要直接输入argv变量到你的程序中(避免在每次使用它时打sys.),那么你可以使用from sys import argv语句。如果你想要输入所有sys模块使用的名字,那么你可以使用from sys import *语句。这对于所有模块都适用。一般说来,应该避免使用from..import而使用import语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
每个模块都有一个名称,在模块中可以通过语句来找出模块的名称。这在一个场合特别有用——就如前面所提到的,当一个模块被第一次输入的时候,这个模块的主块将被运行。假如我们只想在程序本身被使用的时候运行主块,而在它被别的模块输入的时候不运行主块,我们该怎么做呢?这可以通过模块的__name__属性完成。
1 2 3 4 5 6 7 |
#!/usr/bin/python # Filename: using_name.py if __name__ == '__main__': print 'This program is being run by itself' else: print 'I am being imported from another module' |
输出
$ python using_name.py This program is being run by itself $ python >>> import using_name I am being imported from another module
你可以使用内建的dir函数来列出模块定义的标识符。标识符有函数、类和变量。当你为dir()提供一个模块名的时候,它返回模块定义的名称列表。如果不提供参数,它返回当前模块中定义的名称列表。比如刚才我自己写的一个模块test:
>>>import test
>>>dir(test)
['__builtins__', '__doc__', '__file__', '__name__', '__package__', 'test']
为了观察dir的作用,我们定义一个新的变量a并且给它赋一个值,然后检验dir,我们观察到在列表中增加了以上相同的值。我们使用del语句删除当前模块中的变量/属性,这个变化再一次反映在dir的输出中。
关于del——这个语句在运行后被用来 删除 一个变量/名称。在这个例子中,del a,你将无法再使用变量a——它就好像从来没有存在过一样。
下边讲一个Python的数据结构--list,可以理解成数组,一个功能强大的数组,也类似STL里的list容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
#!/usr/bin/python # Filename: using_list.py #声明一个list shoplist = ['apple', 'mango', 'carrot', 'banana'] #测试list长度 print 'I have', len(shoplist),'items to purchase.' #遍历list print 'These items are:', # Notice the comma at end of the line for item in shoplist: print item, #向list添加元素 print '\nI also have to buy rice.' shoplist.append('rice') #遍历输出list print 'My shopping list is now', shoplist #list内元素排序,这个排序是稳定排序 print 'I will sort my list now' shoplist.sort() print 'Sorted shopping list is', shoplist #按下标读取list元素,起始下标为0 print 'The first item I will buy is', shoplist[0] olditem = shoplist[0] #删除某一个元素 del shoplist[0] print 'I bought the', olditem print 'My shopping list is now', shoplist |
也可以del shoplist 来删除整个列表。还有更多使用方式如:insert、remove、reverse、pop等等,可以查看help(list)获取详情。
元组和列表十分类似,只不过元组和字符串一样是 不可变的,即你不能修改元组。元组通过圆括号中用逗号分割的项目定义。元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候,即被使用的元组的值不会改变。
1 2 3 4 5 6 7 8 9 10 11 |
#!/usr/bin/python # Filename: using_tuple.py zoo = ('wolf', 'elephant', 'penguin') print 'Number of animals in the zoo is', len(zoo) new_zoo = ('monkey', 'dolphin', zoo) print 'Number of animals in the new zoo is', len(new_zoo) print 'All animals in new zoo are', new_zoo print 'Animals brought from old zoo are', new_zoo[2] print 'Last animal brought from old zoo is', new_zoo[2][2] |
输出
$ python using_tuple.py Number of animals in the zoo is 3 Number of animals in the new zoo is 3 All animals in new zoo are ('monkey', 'dolphin', ('wolf', 'elephant', 'penguin')) Animals brought from old zoo are ('wolf', 'elephant', 'penguin') Last animal brought from old zoo is penguin
变量zoo是一个元组,我们看到len函数可以用来获取元组的长度。这也表明元组也是一个序列。还有注意元组之内的元组不会失去它的身份。
我们可以通过一对方括号来指明某个项目的位置从而来访问元组中的项目,就像我们对列表的用法一样。这被称作 索引 运算符。我们使用new_zoo[2]来访问new_zoo中的第三个项目。我们使用new_zoo[2][2]来访问new_zoo元组的第三个项目的第三个项目。
含有0个或1个项目的元组。一个空的元组由一对空的圆括号组成,如myempty = ()。然而,含有单个元素的元组就不那么简单了。你必须在第一个(唯一一个)项目后跟一个逗号,这样Python才能区分元组和表达式中一个带圆括号的对象。即如果你想要的是一个包含项目2的元组的时候,你应该指明singleton = (2 , )。
给Perl程序员的注释
列表之中的列表不会失去它的身份,即列表不会像Perl中那样被打散。同样元组中的元组,或列表中的元组,或元组中的列表等等都是如此。只要是Python,它们就只是使用另一个对象存储的对象。
元组最通常的用法是用在打印语句中,下面是一个例子:
1 2 3 4 5 6 7 8 |
#!/usr/bin/python # Filename: print_tuple.py age = 22 name = 'Swaroop' print '%s is %d years old' % (name, age) print 'Why is %s playing with that python?' % name |
输出
$ python print_tuple.py
Swaroop is 22 years old
Why is Swaroop playing with that python?
print语句可以使用跟着%符号的项目元组的字符串。这些字符串具备定制的功能。定制让输出满足某种特定的格式。定制可以是%s表示字符串或%d表示整数。元组必须按照相同的顺序来对应这些定制。类似C/C++中的printf,或者shell里的print。
在第二个print语句中,我们使用了一个定制,后面跟着%符号后的单个项目——没有圆括号。这只在字符串中只有一个定制的时候有效。
最后更多元组详情请参考help(tuple)
字典类似于hash map,剩下的你都懂得。注意,你只能使用不可变的对象(比如字符串)来作为字典的键,但是你可以不可变或可变的对象作为字典的值。基本说来就是,你应该只使用简单的对象作为键。
键值对在字典中以这样的方式标记:d = {key1 : value1, key2 : value2 }。注意它们的键/值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。
记住字典中的键/值对是没有顺序的。如果你想要一个特定的顺序,那么你应该在使用前自己对它们排序。
字典是dict类的实例/对象。详情还是参见help(dict)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#!/usr/bin/python # Filename: using_dict.py # 'ab' is short for 'a'ddress'b'ook ab = { 'Swaroop' : 'swaroopch@byteofpython.info', 'Larry' : 'larry@wall.org', 'Matsumoto' : 'matz@ruby-lang.org', 'Spammer' : 'spammer@hotmail.com' } print "Swaroop's address is %s" % ab['Swaroop'] # Adding a key/value pair ab['Guido'] = 'guido@python.org' # Deleting a key/value pair del ab['Spammer'] print '\nThere are %d contacts in the address-book\n' % len(ab) for name, address in ab.items(): print 'Contact %s at %s' % (name, address) if 'Guido' in ab: # OR ab.has_key('Guido') print "\nGuido's address is %s" % ab['Guido'] |
输出
$ python using_dict.py
Swaroop's address is swaroopch@byteofpython.info
There are 4 contacts in the address-book
Contact Swaroop at swaroopch@byteofpython.info
Contact Matsumoto at matz@ruby-lang.org
Contact Larry at larry@wall.org
Contact Guido at guido@python.org
Guido's address is guido@python.org
使用items方法可以返回一个以键和值为内容的元组。
使用in操作符来检验一个键/值对是否存在,或者使用dict类的has_key方法。你可以使用help(dict)来查看dict类的完整方法列表。
关于序列,它是一个概念,列表、元组和字符串都是序列,序列的两个主要特点是索引操作符和切片操作符。关于序列的例子简单说明一下,有点类似matlab里的数组下标应用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
shoplist = ['apple', 'mango', 'carrot', 'banana'] #可以定义这么一个list #shoplist[0],shoplist[1],shoplist[-1],shoplist[-2]可以这么用下标引用序列值 # Slicing on a list print 'Item 1 to 3 is', shoplist[1:3] print 'Item 2 to end is', shoplist[2:] print 'Item 1 to -1 is', shoplist[1:-1] print 'Item start to end is', shoplist[:] # Slicing on a string name = 'swaroop' print 'characters 1 to 3 is', name[1:3] print 'characters 2 to end is', name[2:] print 'characters 1 to -1 is', name[1:-1] print 'characters start to end is', name[:] |
输出
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop
关于参考概念,类似指针或引用。当你创建一个对象并给它赋一个变量的时候,这个变量仅仅 参考 那个对象,而不是表示这个对象本身!也就是说,变量名指向你计算机中存储那个对象的内存。这被称作名称到对象的绑定。
就是说你创建一个对象,然后又用一个变量指向该对象,删除该对象的内容,则引用的变量也随之改变。如果不想引发这种情况,那么你需要创建的时候是想要对象的一个拷贝。你可以使用切片操作符来建立序列的拷贝。 如:
mylist = shoplist[:] #这是一个拷贝
mylist = shoplist #这是一个参考
说两个你可能用到的模块,至此可以编写一些常用工具了。
import os #可以使用os.system("...") 来执行shell命令,详细help
import time #可以获取当地时间 time.strftime('%Y/%m/%d'),详细请help,
关于Python的面向对象编程。Python中所有对象都是一个类,包括int等等。在类里,使用self指自身,类似其他语言里的this指针。类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。
__init__方法在类的一个对象被建立时,马上运行,类似构造函数。这个方法可以用来对你的对象做一些你希望的 初始化 。注意,这个名称的开始和结尾都是双下划线。
还有一个特殊的方法__del__,它在对象消逝的时候被调用。类似析构函数。
现在我们来看一下类的数据部分。事实上,它们只是与类和对象的名称空间 绑定 的普通变量,即这些名称只在这些类与对象的前提下有效。有两种类型的 域 ——类的变量和对象的变量,它们根据是类还是对象 拥有 这个变量而区分。
类的变量 由一个类的所有对象(实例)共享使用。只有一个类变量的拷贝,所以当某个对象对类的变量做了改动的时候,这个改动会反映到所有其他的实例上。
对象的变量 由类的每个对象/实例拥有。因此每个对象有自己对这个域的一份拷贝,即它们不是共享的,在同一个类的不同实例中,虽然对象的变量有相同的名称,但是是互不相关的。类似静态成员属性和非静态成员属性的区别。
Python中所有的类成员(包括数据成员)都是 公共的 ,所有的方法都是 有效的 。
只有一个例外:如果你使用的数据成员名称以 双下划线前缀 比如__privatevar,Python的名称管理体系会有效地把它作为私有变量。
这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。
关于类的继承看下列例子:(可以多重继承)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
#!/usr/bin/python # Filename: inherit.py class SchoolMember: '''Represents any school member.''' def __init__(self, name, age): self.name = name self.age = age print '(Initialized SchoolMember: %s)' % self.name def tell(self): '''Tell my details.''' print 'Name:"%s" Age:"%s"' % (self.name, self.age), class Teacher(SchoolMember): '''Represents a teacher.''' def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) self.salary = salary print '(Initialized Teacher: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Salary: "%d"' % self.salary class Student(SchoolMember): '''Represents a student.''' def __init__(self, name, age, marks): SchoolMember.__init__(self, name, age) self.marks = marks print '(Initialized Student: %s)' % self.name def tell(self): SchoolMember.tell(self) print 'Marks: "%d"' % self.marks t = Teacher('Mrs. Shrividya', 40, 30000) s = Student('Swaroop', 22, 75) print # prints a blank line members = [t, s] for member in members: member.tell() # works for both Teachers and Students |
关于Python的文件操作:(file 对象)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
#!/usr/bin/python # Filename: using_file.py poem = '''\ Programming is fun When the work is done if you wanna make your work also fun: use Python! ''' f = file('poem.txt', 'w') # open for 'w'riting f.write(poem) # write text to file f.close() # close the file f = file('poem.txt') # if no mode is specified, 'r'ead mode is assumed by default while True: line = f.readline() if len(line) == 0: # Zero length indicates EOF break print line, # Notice comma to avoid automatic newline added by Python f.close() # close the file |
储存器
Python提供一个标准的模块,称为pickle。使用它你可以在一个文件中储存任何Python对象,之后你又可以把它完整无缺地取出来。这被称为 持久地 储存对象。
还有另一个模块称为cPickle,它的功能和pickle模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle快1000倍)。你可以使用它们中的任一个,而我们在这里将使用cPickle模块。记住,我们把这两个模块都简称为pickle模块。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/usr/bin/python # Filename: pickling.py import cPickle as p #import pickle as p shoplistfile = 'shoplist.data' # the name of the file where we will store the object shoplist = ['apple', 'mango', 'carrot'] # Write to the file f = file(shoplistfile, 'w') p.dump(shoplist, f) # dump the object to a file f.close() del shoplist # remove the shoplist # Read back from the storage f = file(shoplistfile) storedlist = p.load(f) print storedlist |
首先,请注意我们使用了import..as语法。这是一种便利方法,以便于我们可以使用更短的模块名称。在这个例子中,它还让我们能够通过简单地改变一行就切换到另一个模块(cPickle或者pickle)!在程序的其余部分的时候,我们简单地把这个模块称为p。
为了在文件里储存一个对象,首先以写模式打开一个file对象,然后调用储存器模块的dump函数,把对象储存到打开的文件中。这个过程称为 储存 。接下来,我们使用pickle模块的load函数的返回来取回对象。这个过程称为 取储存 。
当你的程序中出现某些 异常的 状况的时候,异常就发生了。例如,当你想要读某个文件的时候,而那个文件不存在。或者在程序运行的时候,你不小心把它删除了。上述这些情况可以使用异常来处理。try..except和try..finally
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/usr/bin/python # Filename: raising.py class ShortInputException(Exception): '''A user-defined exception class.''' def __init__(self, length, atleast): Exception.__init__(self) self.length = length self.atleast = atleast try: s = raw_input('Enter something --> ') if len(s) < 3: raise ShortInputException(len(s), 3) # Other work can continue as usual here except EOFError: print '\nWhy did you do an EOF on me?' except ShortInputException, x: print 'ShortInputException: The input was of length %d, \ was expecting at least %d' % (x.length, x.atleast) else: print 'No exception was raised.' |
Python标准库。
sys模块
sys模块包含系统对应的功能。我们已经学习了sys.argv列表,它包含命令行参数。对于有经验的程序员,sys模块中其他令人感兴趣的项目有sys.stdin、sys.stdout和sys.stderr它们分别对应你的程序的标准输入、标准输出和标准错误流。
os模块
这个模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在Linux和Windows下运行。一个例子就是使用os.sep可以取代操作系统特定的路径分割符。下面列出了一些在os模块中比较有用的部分。它们中的大多数都简单明了。
os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
os.getcwd()函数得到当前工作目录,即当前Python脚本工作的目录路径。
os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
os.listdir()返回指定目录下的所有文件和目录名。
os.remove()函数用来删除一个文件。
os.system()函数用来运行shell命令。
os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'\r\n',Linux使用'\n'而Mac使用'\r'。
os.path.split()函数返回一个路径的目录名和文件名。
>>> os.path.split('/home/swaroop/byte/code/poem.txt')
('/home/swaroop/byte/code', 'poem.txt')
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。类似地,os.path.existe()函数用来检验给出的路径是否真地存在。
你可以利用Python标准文档去探索更多有关这些函数和变量的详细知识。你也可以使用help(sys)等等。
其他模块需要自行学习。下边说一下类中的特殊的方法
在类中有一些特殊的方法具有特殊的意义,比如__init__和__del__方法,它们的重要性我们已经学习过了。
一般说来,特殊的方法都被用来模仿某个行为。例如,如果你想要为你的类使用x[key]这样的索引操作(就像列表和元组一样),那么你只需要实现__getitem__()方法就可以了。想一下,Python就是对list类这样做的!下面这个表中列出了一些有用的特殊方法。如果你想要知道所有的特殊方法,你可以在《Python参考手册》中找到一个庞大的列表。
名称 | 说明 |
---|---|
__init__(self,...) | 这个方法在新建对象恰好要被返回使用之前被调用。 |
__del__(self) | 恰好在对象要被删除之前调用。 |
__str__(self) | 在我们对对象使用print 语句或是使用str() 的时候调用。 |
__lt__(self,other) | 当使用 小于 运算符(<)的时候调用。类似地,对于所有的运算符(+,>等等)都有特殊的方法。 |
__getitem__(self,key) | 使用x[key] 索引操作符的时候调用。 |
__len__(self) | 对序列对象使用内建的len() 函数的时候调用。 |
列表综合
通过列表综合,可以从一个已有的列表导出一个新的列表。例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最理想的方法。
listone = [2, 3, 4]
listtwo = [2*i for i in listone if i > 2]
print listtwo
在函数中接收元组和列表
当要使函数接收元组或字典形式的参数的时候,有一种特殊的方法,它分别使用*和**前缀。这种方法在函数需要获取可变数量的参数的时候特别有用。
1 2 3 4 5 6 7 8 9 10 11 |
>>> def powersum(power, *args): ... '''Return the sum of each argument raised to specified power.''' ... total = 0 ... for i in args: ... total += pow(i, power) ... return total ... >>> powersum(2, 3, 4) 25 >>> powersum(2, 10) 100 |
由于在args变量前有*前缀,所有多余的函数参数都会作为一个元组存储在args中。如果使用的是**前缀,多余的参数则会被认为是一个字典的键/值对。
lambda形式
lambda语句被用来创建新的函数对象,并且在运行时返回它们。
1 2 3 4 5 6 7 8 9 10 |
#!/usr/bin/python # Filename: lambda.py def make_repeater(n): return lambda s: s*n twice = make_repeater(2) print twice('word') print twice(5) |
输出
$ python lambda.py
wordword
10
这里,我们使用了make_repeater函数在运行时创建新的函数对象,并且返回它。lambda语句用来创建函数对象。本质上,lambda需要一个参数,后面仅跟单个表达式作为函数体,而表达式的值被这个新建的函数返回。注意,即便是print语句也不能用在lambda形式中,只能使用表达式。
exec和eval语句
exec语句用来执行储存在字符串或文件中的Python语句。例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句。下面是一个简单的例子。
>>> exec 'print "Hello World"'
Hello World
eval语句用来计算存储在字符串中的有效Python表达式。下面是一个简单的例子。
>>> eval('2*3')
6
assert语句用来声明某个条件是真的。例如,如果你非常确信某个你使用的列表中至少有一个元素,而你想要检验这一点,并且在它非真的时候引发一个错误,那么assert语句是应用在这种情形下的理想语句。当assert语句失败的时候,会引发一个AssertionError。类似C/C++里的断言宏
repr函数
repr函数用来取得对象的规范字符串表示。反引号(也称转换符)可以完成相同的功能。注意,在大多数时候有eval(repr(object)) == object。
>>> i = []
>>> i.append('item')
>>> `i`
"['item']"
>>> repr(i)
"['item']"
基本上,repr函数和反引号用来获取对象的可打印的表示形式。你可以通过定义类的__repr__方法来控制你的对象在被repr函数调用的时候返回的内容。
至此已经把Python过一遍了,你可以继续深入学习:
Python的GUI编程:PyQt 这是Qt工具包的Python绑定。yGTK 这是GTK+工具包的Python绑定。
Python.org——Python编程语言的官方主页。你可以在上面找到Python语言和解释器的最新版本。另外还有各种邮件列表活跃地讨论Python的各方面内容。
《Python实用大全》是一个极有价值的秘诀和技巧集合,它帮助你解决某些使用Python的问题。这是每个Python用户必读的一本书。
《迷人的Python》是David Mertz编著的一系列优秀的Python相关文章。
《深入理解Python》是给有经验的Python程序员的一本很优秀的书。如果你已经完整地阅读了本书,那么我强烈建议你接下来阅读《深入理解Python》。它覆盖了包括XML处理、单元测试和功能性编程在内的广泛的主题。
Jython是用Java语言实现的Python解释器。这意味着你可以用Python语言编写程序而同时使用Java库!Jython是一个稳定成熟的软件。如果你也是一个Java程序员,我强烈建议你尝试一下Jython。
IronPython是用C#语言实现的Python解释器,可以运行在.NET、Mono和DotGNU平台上。这意味着你可以用Python语言编写程序而使用.NET库以及其他由这三种平台提供的库!IronPython还只是一个前期alpha测试软件,现在还只适合用来进行试验。