python学习备忘录--2
上一篇:http://www.2cto.com/kf/201202/118740.html
1,前言
前面的备忘录提到了python的基本教程,基本上本文例子都是沈洁元的简明教程里面的内容,这两篇都是读书笔记,算不上派生,主要也是自己备忘用的,译者见谅。
基本上本文的解释是自己的理解,没有采用书本中的讲解,觉得自己解释可能更容易记住。
上篇备忘主要是面向过程来讲述的,其实python是凡事都是对象的一种解释语言。包括类型int啊等等都是对象,与C/C++显然不同,在这两个语言中,类型是作为原子来定义的,主要是用来分配内存字节而用,没有所谓方法,当然这点在VC中做了一定改变,比如对字符串的处理显然是比C要方便一些。
python和perl,还是Python容易懂些,效率差了
2,面向对象的python
2.1,类创建一个新类型,而对象这个类的 实例。
2.2,对象可以使用普通的 属于 对象的变量存储数据。属于一个对象或类的变量被称为域。对象也可以使用 属于 类的函数来具有功能。这样的函数被称为类的方法。域和方法可以合称为类的属性。
2.3,域有两种类型——属于每个实例/类的对象或属于类本身。它们分别被称为实例变量和类变量。类使用class关键字创建。类的域和方法被列在一个缩进块中。
3,类
3.1,self参数
类的方法与普通的函数只有一个特别的区别——它们必须有一个额外的第一个参数名称,但是在调用这个方法的时候你不为这个参数赋值,Python会提供这个值。这个特别的变量指对象本身,按照惯例它的名称是self。
self 本身不需要赋值,由python自动完成功能,如果你的实例调用一个方法,例如:假如你有一个类称为MyClass和这个类的一个实例MyObject。当你调用这个对象的方法MyObject.method(arg1, arg2)的时候,这会由Python自动转为MyClass.method(MyObject, arg1, arg2)
3.2,创建一个类
我们看下面这个例子:
[python]
#!/usr/bin/python
# Filename: simplestclass.py
class Person:
pass # An empty block
p = Person()
print p
#!/usr/bin/python
# Filename: simplestclass.py
class Person:
pass # An empty block
p = Person()
print p 如果你去掉pass前面的缩进,会提示错误,期待一个缩进,一定要记住python是由缩进来区别语句块的,习惯C的人要留心。
结果打印的是这个实例的内存地址。
再者要注意的是:python中表示空语句必须写个pass,而不是像C中括号一括完事,因为python是用缩进来区别语句块的。所以你不缩进,解释器就不懂了。
3.3,对象的方法
对象方法与函数类似,只不过多了一个额外的self变量。
我们来看一个方法:
[python]
#!/usr/bin/python
# Filename: method.py
class Person:
def sayHi(self):
print 'Hello, how are you?'
p = Person()
p.sayHi()
#!/usr/bin/python
# Filename: method.py
class Person:
def sayHi(self):
print 'Hello, how are you?'
p = Person()
p.sayHi() # This short example can also be written as Person().sayHi()
要注意sayHi方法没有任何参数。我个人觉得之所以需要一个self做方法默认参数可能是由于python是门解释型语言,便于解释器解释。刚学这只是种感觉,不对之处请指正。
3.4,一些特殊方法
这里面其实涉及了一些并不陌生的概念
3.4.1 __init__方法
这个方法其实就是构造函数啊,大家懂了吧,而且上篇没有提到,python是变量不需要事前声明的,说实话看到下面这个例子,还是多少有点不适应
[python]
#!/usr/bin/python
# Filename: class_init.py
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
p = Person('Swaroop')
p.sayHi()
# This short example can also be written as Person('Swaroop').sayHi()
#!/usr/bin/python
# Filename: class_init.py
class Person:
def __init__(self, name):
self.name = name
def sayHi(self):
print 'Hello, my name is', self.name
p = Person('Swaroop')
p.sayHi()
# This short example can also be written as Person('Swaroop').sayHi()这里面的属性域没有声明啊,也不说什么类型,在语法严格C++中显的是相当糟糕。
创建一个类的新实例的时候,把参数包括在圆括号内跟在类名后面,从而传递给__init__方法。
这个你要是习惯C++/Java之类的强制类型申明语言,看到这个self.name很不适应。还是把self参数当成系统需要的参数就好了。
下面这个例子可以解释一下为什么实例的属性域可以不用声明,对于python而已,创建实例适合,调用的__init__方法
[python]
#!/usr/bin/python
# Filename: objvar.py
class Person:
'''''Represents a person.'''
population = 0
def __init__(self, name):
'''''Initializes the person's data.'''
self.name = name
print '(Initializing %s)' % self.name
# When this person is created, he/she
# adds to the population
Person.population += 1
def __del__(self):
'''''I am dying.'''
print '%s says bye.' % self.name
Person.population -= 1
if Person.population == 0:
print 'I am the last one.'
else:
print 'There are still %d people left.' % Person.population
def sayHi(self):
'''''Greeting by the person.
Really, that's all it does.'''
print 'Hi, my name is %s.' % self.name
def howMany(self):
'''''Prints the current population.'''
if Person.population == 1:
print 'I am the only person here.'
else:
print 'We have %d persons here.' % Person.population
swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()
kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()
swaroop.sayHi()
swaroop.howMany()
#!/usr/bin/python
# Filename: objvar.py
class Person:
'''Represents a person.'''
population = 0
def __init__(self, name):
'''Initializes the person's data.'''
self.name = name
print '(Initializing %s)' % self.name
# When this person is created, he/she
# adds to the population
Person.population += 1
def __del__(self):
'''I am dying.'''
print '%s says bye.' % self.name
Person.population -= 1
if Person.population == 0:
print 'I am the last one.'
else:
print 'There are still %d people left.' % Person.population
def sayHi(self):
'''Greeting by the person.
Really, that's all it does.'''
print 'Hi, my name is %s.' % self.name
def howMany(self):
'''Prints the current population.'''
if Person.population == 1:
print 'I am the only person here.'
else:
print 'We have %d persons here.' % Person.population
swaroop = Person('Swaroop')
swaroop.sayHi()
swaroop.howMany()
kalam = Person('Abdul Kalam')
kalam.sayHi()
kalam.howMany()
swaroop.sayHi()
swaroop.howMany() 观察可以发现__init__方法用一个名字来初始化Person实例。在这个方法中,我们让population增加1,这是因为我们增加了一个人。同样可以发现,self.name的值根据每个对象指定,这表明了它作为对象的变量的本质。
运行上述脚本,提示Exception AttributeError: "'NoneType' object has no attribute 'population'" in <bound method Person.__del__ of <__main__.Person instance at 0xb7746eec>> ignored;
原因是对象销毁时,全局变量的问题。
我另写了一篇备注,记录学习一下错误和心得,这里先列出遇到的问题。记住一点,不要使用__def__方法。
你只能使用self变量来参考同一个对象的变量和方法。这被称为 属性参考 。
在这个程序中,我们还看到docstring对于类和方法同样有用。我们可以在运行时使用Person.__doc__和Person.sayHi.__doc__来分别访问类与方法的文档字符串。
就如同__init__方法一样,还有一个特殊的方法__del__,它在对象消逝的时候被调用。对象消逝即对象不再被使用,它所占用的内存将返回给系统作它用。在这个方法里面,我们只是简单地把Person.population减1。
当对象不再被使用时,__del__方法运行,但是很难保证这个方法究竟在 什么时候 运行。
我们正常运行一次:
我们在这个脚本里面添加:
print Person.__doc__
print Person.sayHi.__doc__
我们看下运行结果:
b2c@b2c-server:~$ python demo.py
(Initializing Swaroop)
Hi, my name is Swaroop.
I am the only person here.
(Initializing Abdul Kalam)
Hi, my name is Abdul Kalam.
We have 2 persons here.
Hi, my name is Swaroop.
We have 2 persons here.
Represents a person.
Greeting by the person.
Really, that's all it does.
Abdul Kalam says bye.
There are still 1 people left.
Swaroop says bye.
I am the last one.
有没有发现什么?可以看到我们的文档字符串或者说是说明文字不是最后显示,而脚本中其实是最后两条语句,这个是因为__del__方法,脚本执行最后,实例被销毁,所以方法执行,出现提示。明白了没。
所以这个__del__是析构函数,类似概念。
这里面多说一句,python其实类中成员默认都是公开的,私有成员是后来语言加入的特性,以双下划线__作为标志。如一个变量__var为私有变量,包括子类在内的外部调用都是无效的。python 是采用从新命名这个私有变量名字而避开外部调用的,非常简单,所以会提示你找不到。
缩进要注意逻辑对齐!
3.5,继承
面向对象的核心概念之一,为了代码重用和逻辑相关性而定义。有过OOP基础的都应该不陌生。
子类型实例可以自然的被当作父类型使用,支持多重继承。
[python]
#!/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
#!/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这个例子可以看出继承的基本含义。另外说一点,子类构造函数必须人工构造父类的构造函数,不能自动完成,这点与其他OOP语言有点区别。
Python不会自动调用基本类的constructor,你得亲自专门调用它。
4,I/O
4.1,文件
你可以通过创建一个file类的对象来打开一个文件。
这个IO操作还是比较方便,能直接调用file()
[python]
#!/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 Perl!
'''
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
#!/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 Perl!
'''
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 我们通过指明我们希望打开的文件和模式来创建一个file类的实例。模式可以为读模式('r')、写模式('w')或追加模式('a')。事实上还有多得多的模式可以使用,你可以使用help(file)来了解它们的详情。
如果没有指定模式,读将作为默认模式。
在一个循环中,我们使用readline方法读文件的每一行。这个方法返回包括行末换行符的一个完整行。所以,当一个 空的 字符串被返回的时候,即表示文件末已经到达了,于是我们停止循环。
这里面有个小疑问就是while语句的true是根据上下文来判断的么?我改成f也是可以的.
注意,因为从文件读到的内容已经以换行符结尾,所以我们在print语句上使用逗号来消除自动换行。最后,我们用close关闭这个文件。
4.2 存储器
Python提供一个标准的模块,称为pickle。使用它你可以在一个文件中储存任何Python对象,之后你又可以把它完整无缺地取出来。这被称为 持久地 储存对象。
还有另一个模块称为cPickle,它的功能和pickle模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle快1000倍)。C就是牛逼啊。哈哈
[python]
#!/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
#!/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函数的返回来取回对象。这个过程称为 取储存 。
这个是涉及I/O操作用的
5,异常处理
应该说高级语言里面都有异常处理的内容。
我们程序出现问题的适合,解释器会告诉我们出错了,有些时候对用户显示这些显然是不友好的。所以,有点类似catch...throw,这里面有try...except。
[python]
#!/usr/bin/python
# Filename: try_except.py
import sys
try:
s = raw_input('Enter something --> ')
except EOFError:
print '/nWhy did you do an EOF on me?'
sys.exit() # exit the program
except:
print '/nSome error/exception occurred.'
# here, we are not exiting the program
print 'Done'
#!/usr/bin/python
# Filename: try_except.py
import sys
try:
s = raw_input('Enter something --> ')
except EOFError:
print '/nWhy did you do an EOF on me?'
sys.exit() # exit the program
except:
print '/nSome error/exception occurred.'
# here, we are not exiting the program
print 'Done'这个程序运行以后,按“Ctrl+C”或者“Ctrl+D”看看结果。。
5.2,自定义异常
可以自己定义异常来显示。
你可以使用raise语句 引发 异常。你还得指明错误/异常的名称和伴随异常 触发的 异常对象。你可以引发的错误或异常应该分别是一个Error或Exception类的直接或间接导出类。
自己定义的异常类要是Exception类的子类。
这里,我们创建了我们自己的异常类型,其实我们可以使用任何预定义的异常/错误。这个新的异常类型是ShortInputException类。它有两个域——length是给定输入的长度,atleast则是程序期望的最小长度。
在except从句中,我们提供了错误类和用来表示错误/异常对象的变量。这与函数调用中的形参和实参概念类似。在这个特别的except从句中,我们使用异常对象的length和atleast
[python]
#!/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.'
#!/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.' 这里,我们创建了我们自己的异常类型,其实我们可以使用任何预定义的异常/错误。这个新的异常类型是ShortInputException类。它有两个域——length是给定输入的长度,atleast则是程序期望的最小长度。
在except从句中,我们提供了错误类和用来表示错误/异常对象的变量。这与函数调用中的形参和实参概念类似。在这个特别的except从句中,我们使用异常对象的length和atleast域来为用户打印一个恰当的消息.
5.3,try..finally
单词意思可知,finally是无论异常发生与否都要完成的动作。
[python]
#!/usr/bin/python
# Filename: finally.py
import time
try:
f = file('poem.txt')
while True: # our usual file-reading idiom
line = f.readline()
if len(line) == 0:
break
time.sleep(2)
print line,
finally:
f.close()
print 'Cleaning up...closed the file'
#!/usr/bin/python
# Filename: finally.py
import time
try:
f = file('poem.txt')
while True: # our usual file-reading idiom
line = f.readline()
if len(line) == 0:
break
time.sleep(2)
print line,
finally:
f.close()
print 'Cleaning up...closed the file'睡了2秒,是故意延长时间,好让你按“Ctrl+D”,按了你也发现,文件还是关闭了最后。
6,python标准库
6.1,sys模块
顾名思义,系统库。
[python]
#!/usr/bin/python
# Filename: cat.py
import sys
def readfile(filename):
'''''Print a file to the standard output.'''
f = file(filename)
while True:
line = f.readline()
if len(line) == 0:
break
print line, # notice comma
f.close()
# Script starts from here
if len(sys.argv) < 2:
print 'No action specified.'
sys.exit()
if sys.argv[1].startswith('--'):
option = sys.argv[1][2:]
# fetch sys.argv[1] but without the first two characters
if option == 'version':
print 'Version 1.2'
elif option == 'help':
print '''''/
This program prints files to the standard output.
Any number of files can be specified.
Options include:
--version : Prints the version number
--help : Display this help'''
else:
print 'Unknown option.'
sys.exit()
else:
for filename in sys.argv[1:]:
readfile(filename)
#!/usr/bin/python
# Filename: cat.py
import sys
def readfile(filename):
'''Print a file to the standard output.'''
f = file(filename)
while True:
line = f.readline()
if len(line) == 0:
break
print line, # notice comma
f.close()
# Script starts from here
if len(sys.argv) < 2:
print 'No action specified.'
sys.exit()
if sys.argv[1].startswith('--'):
option = sys.argv[1][2:]
# fetch sys.argv[1] but without the first two characters
if option == 'version':
print 'Version 1.2'
elif option == 'help':
print '''/
This program prints files to the standard output.
Any number of files can be specified.
Options include:
--version : Prints the version number
--help : Display this help'''
else:
print 'Unknown option.'
sys.exit()
else:
for filename in sys.argv[1:]:
readfile(filename)这里面说明一下:argv自动将脚本文件名认为是argv[0],从0开始计数,与C语言一样,如果出现argv[1][2:]则是第二个参数,用户角度是第一个参数抛弃前两个字符,截取剩余字符的意思。
至于argv[1:]则应该是从用户角度的第一个参数依次到参数列表的最后。
readfile()函数输出文件内容,首先判断参数数量,少于2个显然是没有输入文件名称,给出提示反馈,如果参数是以--开头的则抛弃前两个字符,截取剩下字符通过流程匹配分别输出提示。最后,把参数列表中的文件一个个输出就是了
这里面有三个模块比较常用先记下:sys.stdin、sys.stdout和sys.stderr它们分别对应你的程序的标准输入、标准输出和标准错误流。
6.2,OS模块
这个模块包含普遍的操作系统功能。如果你希望你的程序能够与平台无关的话,这个模块是尤为重要的。即它允许一个程序在编写后不需要任何改动,也不会发生任何问题,就可以在Linux和Windows下运行。一个例子就是使用os.sep可以取代操作系统特定的路径分割符。
这个对于我那是相当重要了,毕竟现在用LINUX桌面的人简直是凤毛麟角啊。
os模块里面有很多方法很有用,平时可以查看一下文档。
[python]
os.name字符串指示你正在使用的平台.
os.getcwd()函数得到当前工作目录。
os.linesep字符串给出当前平台使用的行终止符。
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。类似地,os.path.existe()函数用来检验给出的路径是否真地存在。
os.name字符串指示你正在使用的平台.
os.getcwd()函数得到当前工作目录。
os.linesep字符串给出当前平台使用的行终止符。
os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。类似地,os.path.existe()函数用来检验给出的路径是否真地存在。基本上python基本东西都在这里么了,当然讲的也是皮毛,在以后真正开发中我会不断添加内容和学习备忘的。
摘自 DesignLab