分享

Python完全新手教程 -- 2

 krrish 2010-09-26

Lesson 7 Python基本语法要素齐动员
现在的目的是尽量想出一个用的东西仅限于内置的变量类型和语句的一个综合的例子,我想还是那个联系人表的例子吧

     代码: [复制到剪贴板]  
################
#呵呵,还忘记了讲注释
#第一个算是完整的程序
################
contact = {}
contact_list = []
while 1:
       contact['name'] = raw_input("please input name: ")
       contact['phone'] = raw_input("please input phone number: ")
       contact_list.append(contact.copy())
       go_on = raw_input("continue?\n")
       if go_on == "yes":
           pass
       elif go_on == "no":
           break
       else:
           print "you didn't say no\n"
i = 1
for contact in contact_list:
       print "%d: name=%s" % (i, contact['name'])
       print "%d: phone=%s" % (i, contact['phone'])
       i = i + 1

首先是回忆一下字符串
字符串既能够用""也能够用''。然后是很有特色的%操作,起到格式化字符串的作用,前面仅仅在字符串中有一个%s,现在有%d和%s两个,分别代表插入十进制数值和字符串于%x标记的位置处。

然后是列表
列表是顺序的序列,用append在后面附加,也能构用索引值索引。所以我们完全可以用一个变量保存len(contact_list)得到的长度,然后一个个的遍历,不过这里展示了另外一种非常方便的方法。而且值得注意的是append()中的参数,我使用了contact.copy(),你可以尝试着把copy()给去掉,观察结果你就知道了所谓的append是怎么干的了,特别是你对指针之类的东西很有感觉的话(但是在Python中是没有指针这个概念的)

再来看看字典
字典是键(key)和值(value)的对应组合成的无序的序列。所以你存的时候要指明键(name或者phone),而且取的时候也是一样的。

接下来是判断
if是很好用的,==表示判断两个是否相等,=表示把右边的赋给左边的。而且可以直接判断字符串是否相等,这个太方便了,如果你曾经用过strcpy()的话,就知道了。elif是表示else if的意思,如果if不满足就判断elif的条件是否满足,最后是到else中去。

循环是个主体
while和for都是循环。不过这里while就没什么说的了,又是很经典的while 1,死循环,然后必须在里面用break来跳出。for和C中的for是不一样的,for in才是一个完整的语句,指的是从一个能够逐一取值的序列中(比如list),一个一个的取出值赋给for后面指定的变量中,直到取空,循环结束。其实回想一般用C中的for的经历,也大体如此。而且你还可以用for i in range(1,100)来指定一个范围从多少到多少。可以说for in充分体现了python的体贴周到,用起来很直观,不会绕弯。

接下来就是运行了,大家慢慢调试吧。下次可能是讲异常处理,因为我觉得在深入到使用各种高级的要素之前,先要学会怎么去处理异常。最常见的异常应该是input(),然后你给出的输入是一个无法转换为数字的字符串了,那么我们就要来处理它。

Lesson 8 Python中的错误检测
写程序什么最重要?完成功能最重要。但是程序中难免要有用户的输入,对于这些写的时候未可预知的因素中间可能出现的错误,一般称作异常。对于异常情况的处理,不同语言有不同的做法,比如检查函数的返回值之类的,但是那种办法会把代码弄成一团浆糊。Python在这个方面是比较先进的,我们从一个例子来看看:

     代码: [复制到剪贴板]  
print input()

呵呵,看不同吧。其实input是输入,print是输出。也就是把输入的东西立即输出。但是这个和

     代码: [复制到剪贴板]  
print raw_input()

有什么不同呢?
不同的地方是,input()会在raw_input()接收了“字符串”的输入之后进行一些处理,比如你是输入1+2,然后输出的就是3了,而raw_input就是原原本本的1+2的输出了。用代码表示就是

     代码: [复制到剪贴板]  
eval(raw_input())

eval是求表达式的值,任何一个简单的python表达式,就像1+2这样的作为字符串送入,就能把值从eval处理之后取出来。
现在你实验一下"sdfsdf”之后,你会发现提示你

     引用:
Traceback (most recent call last):
     File "<pyshell#4>", line 1, in -toplevel-
       input()
     File "<string>", line 0, in -toplevel-
NameError: name 'sdfsdf' is not defined

如果输入其他稀奇古怪的字符串还可能有其他的出错提示,我们现在要做的就是捕捉这种由用户输入引起的错误。这么来作:

     代码: [复制到剪贴板]  
try:
       print input()
except:
       print 'there is an error in your input'

这下你无论怎么输入都不会有什么其他的提示了,就是自己设定的print语句作为提示。现在把try except的组合去掉,回到print input()你再尝试一下:
1/0
这个显然是一个错误,被零除的错误。那么专门来捕捉一下这个错误:

     代码: [复制到剪贴板]  
try:
       print input()
except ZeroDivisionError:
       print 'can not be divided by zero'

这下你能够捕捉到被零除的错误了。然后你再尝试其他的输入,可能错误就没有被捕捉了。所以再补上:

     代码: [复制到剪贴板]  
try:
       print input()
except ZeroDivisionError:
       print 'can not be divided by zero'
except:
       print 'there is an error in your input'

注意,捕捉所有错误的except必须放在所有的except的最后一位。明白了?OK

还有更多的能够捕捉的错误,自己查手册吧(暂时看不了手册没关系,慢慢来嘛)。以后还能够自己raise(引发)异常呢。不过那都是比较高级的应用了,对于出错处理从一开始就有这个印象,并牢记在心中对于以后写大一些的软件很有好处。

Lesson 9 走向模块化的第一步
大规模的程序设计需要你把一个大的程序拆分成n个模块。然后把模块进行组合,交互成为一个完整的程序。你不可能像现在这样,从顶写到尾。。。
那么我们从函数开始。

     代码: [复制到剪贴板]  
def square(x):
       return x**2

print square(5)

简单吧,这个是我看过的函数定义中最简洁的。def表示这个开始定义一个函数,x是参数,参数是不需要类型的,因为python是不需要明确指出类型的。return是返回值,返回的值插入到调用函数的地方。再复杂一些

     代码: [复制到剪贴板]  
def multiply(a, b):
       return a*b

print multiply(1,2)

这是两个参数的函数。那么返回两个值呢?

     代码: [复制到剪贴板]  
def swap(a, b):
       return (b,a)
print swap(1,2)

呵呵,其实这里返回的并不是两个值,而是一个值。怎么说呢。(b, a)就是一个东西,是一个元组(turple),你可以用这样的方式成生一个元组,并使用它。元组是基本的变量类型:

     代码: [复制到剪贴板]  
my_turple = (1, 2, 3)
my_list = []
for i in my_turple:
       my_list.append(i)
print my_list

其实元组和列表非常像,但是列表的长度是可以变化的,而且成员是可以改变的。但是元组是什么都不能变的,是只读的。

对于高级一点的话题:传递进来的参数是否可以被修改,这个问题取决于你传递了什么近来。如果是数字或者字符串,是不能够改变的,但是如果是这样的:

     代码: [复制到剪贴板]  
def test_func(list_be_passed):
       list_be_passed[0] = 'towin'
my_list = ['taowen']
print my_list
test_func(my_list)
print my_list

就能够改变传递近来的参数了,所以处理的时候要小心,必要的时候copy一下再传递。

函数简单吧,但是很好用的。想起C中的函数那么那么多麻烦,真是感慨万千啊。下面是应该讲GUI编程呢,还是面向对象呢?思考一下

Lesson 10 Python的文件操作
文件操作....是一个语言和外界联系的主要方法....现在以txt为例简单的讲一下...



首先是建立关联...假设在存在以下文件 c:\a.txt

     代码: [复制到剪贴板]  
This is line #1
This is line #2
This is line #3
END



     代码: [复制到剪贴板]  
>>> xxx = file('c:\\a.txt', 'r')

关键字的第一部分,是文件路径及名称。注意这里面,路径需要用\\
第二部分,是对文件的模式或者叫权限,一般有以下3种 "r" (read), "w" (write)和 "a"(append).



之后,就可以利用
xxx_content = infile.read()
xxx_content = infile.readlines()
来读取文件内容了

     代码: [复制到剪贴板]  
>>> xxx = file('c:\\a.txt', 'r')
>>> xxx_content = xxx.read()
>>> print xxx_content
This is line #1
This is line #2
This is line #3
END
>>> xxx.close()
>>>



>>> infile = file('c:\\a.txt', 'r')
>>> xxx = file('c:\\a.txt', 'r')
>>> for xxx_line in xxx.readlines():
           print 'Line:', xxx_line

        
Line: This is line #1

Line: This is line #2

Line: This is line #3

Line: END
>>> xxx.close()
>>>

然后是文件的写入

     代码: [复制到剪贴板]  
>>> xxx=file('c:\\test.txt','w')
>>> xxx.write('billrice')
>>> xxx.write('testtest')
>>> xxx.write('enter\n')
>>> xxx.writelines(['billrice','ricerice'])
>>> xxx.close()
>>>
>>> xxx=file('c:\\test.txt','r')
>>> content=xxx.read()
>>> print content
billricetesttestenter
billricericerice
>>>

需要注意的是...在xxx.close()之前,c盘下面只有一个空空的test.txt,xxx.close()的作用相当于最后的存盘。

Lesson 11 走向模块化的第二步
函数上面还能是什么呢?内嵌函数^_^,其实python是支持的。不过用起来会让你吐血的,LGB名称查找规则。。。(寒)。python是面向对象的,对于面向对象的支持挺好玩的。

     代码: [复制到剪贴板]  
class person:
       def __init__(self):
           self.name = 'taowen'
           self.id = 20022479
       def say_id(self):
           print "%s's id is %d" % (self.name, self.id)


me = person()
me.say_id()

比较复杂了吧。如果不熟悉面向对象的概念的,可能会觉得晕。我来解释一下。所谓面向对象是把数据和操作数据的函数放到同一个类中去,然后用类来创建对象,操作的时候能够比较方便(很不精确的说法,任何一个OO高手都可以把我骂得屁都不是)。


类是class关键来定义的。class person:就是说定义一个类,名字叫person。

对象
对象是用类来产生的。所以me就是对象,产生的办法就是像调用函数一样,person(),而且()中是能够放参数的,什么时候要参数,看下面的“初始化函数“

初始化函数
类可以有自己的初始化函数,每次类被创建的时候(调用person()这样的语句的时候),都会调用它。这个在C++中的名称是构造函数。__init__是必须的名字,你不能用其他名字来当初始化函数。但是你可以没有初始化函数。

类的数据
类的数据是所有类产生的对象共享的数据。这里没有用到类的数据,要写的话是这样:

     代码: [复制到剪贴板]  
class person:
       school = 'bit'
       def __init__(self):
           self.name = 'taowen'
           self.id = 20022479
       def say_id(self):
           print "%s's id is %d" % (self.name, self.id)


me = person()
me.say_id()
print me.school

对象的数据
对象的数据是用
self.变量名 = 。。。
来生成的。这里self.name就是对象的数据。对象的数据和类的数据不同,因为对象之间的数据是互不共享的,而类的数据是被所有由类生成的对象共享的。

对象的函数(类的函数)
两个没有区别,是类的就是对象的。其实就是类的(我说的是底层实现,不过不用管,如果关心怎么实现的,等我写Hacking OO吧,还没影呢)。say_id就是对象的函数,你能够调用它。每个对象的函数都需要一个self参数,表示[color]这个对象[/color]。

为什么使用面向对象编程
除去让人觉得你比较专业外,当然由切实的好处。比较浅显的是你能够表达一定的层次关系,类与类之间能够有包含和继承的关系(当然你现在还不会。。。)。而且对象能够把数据和操作数据的函数放在一起,能够比较清晰。虽然有所谓的数据隐藏的概念,但是在python中其实就是一个不要直接调用对象中的数据的约定,而要用一个函数作为中转。其实不懂面向对象很正常,其实有的时候就是要在用的中间感悟的。什么时候把用函数编程用牛了,用出个道道来了,说不定你已经感觉到了什么是面向对象编程。另外:所谓什么OO,都是一些认为规定,不用语法支持,只要心中有这个想法(什么想法?自己悟啊),就能够写出OO的代码,不管你用的是什么语言,什么语法。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多