python学习笔记
本篇笔记根据python简明教程中觉得值得注意的地方摘取而成
基本概念
- 4种类型的数——长整数,整数,浮点数,负数。
- 三引号可以表示多行的字符串,三引号中可以自由的使用单引号和双引号
- python中用到的任何东西都称之为对象,使用变量时只需要给它们赋一个值。不需要声明或定义数据类型。
控制流
if语句
注意
if
语句在结尾处包含一个冒号——我们通过它告诉Python下面跟着一个语句块。然后,我们检验猜测是否小于我们的数,如果是这样的,我们告诉用户它的猜测大了一点。我们在这里使用的是elif
从句,它事实上把两个相关联的if else-if else
语句合并为一个if-elif-else
语句。这使得程序更加简单,并且减少了所需的缩进数量。elif和
else从句都必须在逻辑行结尾处有一个冒号,下面跟着一个相应的语句块(当然还包括正确的缩进)。在Python中没有
switch
语句。你可以使用if..elif..else
语句来完成同样的工作while循环之中可以使用else从句
for循环
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)
相似。for..in
循环对于任何序列都适用。这里我们使用的是一个由内建range
函数生成的数的列表,但是广义说来我们可以使用任何种类的由任何对象组成的序列!
函数
如果你想要为一个定义在函数外的变量赋值,那么你就得告诉Python这个变量名不是局部的,而是 全局 的。我们使用
global
语句完成这一功能。没有global
语句,是不可能为定义在函数外的变量赋值的。你可以使用定义在函数外的变量的值(假设在函数内没有同名的变量)。然而,我并不鼓励你这样做,并且你应该尽量避免这样做,因为这使得程序的读者会不清楚这个变量是在哪里定义的。使用
global
语句可以清楚地表明变量是在外面的块定义的。def func(): global x print 'x is', x x = 2 print 'Changed local x to', x x = 50 func() print 'Value of x is', x
关键参数
如果你的某个函数有许多参数,而你只想指定其中的一部分,那么你可以通过命名来为这些参数赋值——这被称作 关键参数 ——我们使用名字(关键字)而不是位置(我们前面所一直使用的方法)来给函数指定实参。
这样做有两个 优势 ——一,由于我们不必担心参数的顺序,使用函数变得更加简单了。二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值。
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)
使用DocStrings 文档字符串的惯例是一个多行字符串,它的首行以大写字母开始,句号结尾。第二行是空行,从第三行开始是详细的描述。
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__
模块
- 如果你想要直接输入
argv
变量到你的程序中(避免在每次使用它时打sys.
),那么你可以使用from sys import argv
语句。如果你想要输入所有sys
模块使用的名字,那么你可以使用from sys import *
语句。这对于所有模块都适用。一般说来,应该避免使用from..import
而使用import
语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
数据结构
python中三种内建的数据结构,列表,元组,字典
list
shoplist = ['apple', 'mango', 'carrot', 'banana'] print 'I have', len(shoplist),'items to purchase.' print 'These items are:', # Notice the comma at end of the line for item in shoplist: print item, print '\nI also have to buy rice.' shoplist.append('rice') #添加元素 print 'My shopping list is now', shoplist print 'I will sort my list now' shoplist.sort() #排序 print 'Sorted shopping list is', shoplist 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
元组
元组和列表十分类似,只不过元组和字符串一样是 不可变的 即你不能修改元组。元组通过圆括号中用逗号分割的项目定义。元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候,即被使用的元组的值不会改变。
print语句
age = 22 name = 'Swaroop' print '%s is %d years old' % (name, age) print 'Why is %s playing with that python?' % name
print
语句可以使用跟着%
符号的项目元组的字符串。这些字符串具备定制的功能。定制让输出满足某种特定的格式。定制可以是%s
表示字符串或%d
表示整数。元组必须按照相同的顺序来对应这些定制。观察我们使用的第一个元组,我们首先使用
%s
,这对应变量name
,它是元组中的第一个项目。而第二个定制是%d
,它对应元组的第二个项目age
。字典
字典类似于你通过联系人名字查找地址和联系人详细情况的地址簿,即,我们把键(名字)和值(详细情况)联系在一起。注意,键必须是唯一的,就像如果有两个人恰巧同名的话,你无法找到正确的信息。
注意,你只能使用不可变的对象(比如字符串)来作为字典的键,但是你可以不可变或可变的对象作为字典的值。基本说来就是,你应该只使用简单的对象作为键。
键值对在字典中以这样的方式标记:
d = {key1 : value1, key2 : value2 }
。注意它们的键/值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。记住字典中的键/值对是没有顺序的。如果你想要一个特定的顺序,那么你应该在使用前自己对它们排序。
字典是
dict
类的实例/对象。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'] # 添加键值对 ab['Guido'] = 'guido@python.org' # 删除键值对 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会为你抓取序列中对应位置的项目。记住,Python从0开始计数。因此,
shoplist[0]
抓取第一个项目,shoplist[3]
抓取shoplist
序列中的第四个元素。索引同样可以是负数,在那样的情况下,位置是从序列尾开始计算的。因此,
shoplist[-1]
表示序列的最后一个元素而shoplist[-2]
抓取序列的倒数第二个项目。切片操作符是序列名后跟一个方括号,方括号中有一对可选的数字,并用冒号分割。注意这与你使用的索引操作符十分相似。记住数是可选的,而冒号是必须的。
切片操作符中的第一个数(冒号之前)表示切片开始的位置,第二个数(冒号之后)表示切片到哪里结束。如果不指定第一个数,Python就从序列首开始。如果没有指定第二个数,则Python会停止在序列尾。注意,返回的序列从开始位置 开始 ,刚好在 结束 位置之前结束。即开始位置是包含在序列切片中的,而结束位置被排斥在切片外。
这样,
shoplist[1:3]
返回从位置1开始,包括位置2,但是停止在位置3的一个序列切片,因此返回一个含有两个项目的切片。类似地,shoplist[:]
返回整个序列的拷贝。你可以用负数做切片。负数用在从序列尾开始计算的位置。例如,
shoplist[:-1]
会返回除了最后一个项目外包含所有项目的序列切片。
面向对象的编程
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是
self
。虽然你可以给这个参数任何名称,但是 强烈建议 你使用
self
这个名称——其他名称都是不赞成你使用的。使用一个标准的名称有很多优点——你的程序读者可以迅速识别它,如果使用self
的话,还有些IDE(集成开发环境)也可以帮助你。class Person: def sayHi(self): print 'Hello, how are you?' p = Person() p.sayHi()
__init__方法
类似c++里头的构造函数
Python中所有的类成员(包括数据成员)都是 公共的 ,所有的方法都是 有效的 。
只有一个例外:如果你使用的数据成员名称以 双下划线前缀 比如__privatevar
,Python的名称管理体系会有效地把它作为私有变量。
这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。python中的继承示例
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###
输入输出
文件输入输出
poem = '''\ Programming is fun When the work is done if you wanna make your work also fun: use Python! ''' f = file('poem.txt', 'w') # 写模式 f.write(poem) # 直接把字符串写入文件 f.close() # 关闭文件 f = file('poem.txt') # 默认是读文件模式 while True: line = f.readline() if len(line) == 0: # 表示文件尾 break print line, # 使用逗号来清除自动换行 f.close() # close the file
Python提供一个标准的模块,称为
pickle
。使用它你可以在一个文件中储存**任何**Python对象,之后你又可以把它完整无缺地取出来。这被称为 持久地 储存对象。还有另一个模块称为
cPickle
,它的功能和pickle
模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle
快1000倍)。你可以使用它们中的任一个,而我们在这里将使用cPickle
模块。记住,我们把这两个模块都简称为pickle
模块。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
函数的返回来取回对象。这个过程称为 取储存 。
其他
列表综合
listone = [2, 3, 4] listtwo = [2*i for i in listone if i > 2] print listtwo
通过列表综合,可以从一个已有的列表导出一个新的列表。例如,你有一个数的列表,而你想要得到一个对应的列表,使其中所有大于2的数都是原来的2倍。对于这种应用,列表综合是最理想的方法
在函数中接受元组和列表
当要使函数接收元组或字典形式的参数的时候,有一种特殊的方法,它分别使用
*
和**
前缀。这种方法在函数需要获取可变数量的参数的时候特别有用。>>> 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
中。如果使用的是**
前缀,多余的参数则会被认为是一个字典的键/值对。