www.6165.compython基础教程_学习笔记:序列-1

字符串

《python基础教程》笔记之 字符串,python基础教程

  • 字符串格式化

字符串格式化使用字符串格式化操作符即百分号%来实现。在%的左侧放置一个字符串(格式化字符串),而在右侧则放置希望格式化的值,可以使用一个值,如一个字符串或者数字,也可以使用多个值的元组或者字典,如

>>> print “hello. %s.%s enough for ya?” % (‘world’, ‘Hot’)
hello. world.Hot enough for ya?

如果右操作数是元组的话,则其中的每一个元素都会被单独格式化,每个值都需要一个对应的转换说明符。

基本的转换说明符包括以下部分,注意,这些项的顺序是至关重要的。

  1. %字符:标记转换说明符的开始。

2.
转换标志(可选):-表示左对齐;+表示在转换值之前要加上正负号;“”表示正数之前保留空格;0表示转换值若位数不够则用0填充。

3.
最小字段宽度(可选):转换后的字符串至少应该具有该值指定的宽度。如果是*,则宽度会从值元组中读出。

4.
点(.)后跟精度值(可选):如果转换的是实数,精度值就表示出现在小数点后的位数。如果转换的是字符串,那么该数字就表示最大字段宽度。如果是*,那么精度将会从元组中读出。

  1. 转换类型:见下表

www.6165.com 1

#使用给定的宽度打印格式化后的价格列表
width = input('width:')
price_width = 10
item_width = width - price_width

header_format = '%-*s%*s'
format        = '%-*s%*.2f'

print '-' * width

print header_format % (item_width, 'Item', price_width, 'Price')

print '-' * width

print format % (item_width, 'Apples', price_width, 0.4)
print format % (item_width, 'Pears', price_width, 0.5)
print format % (item_width, 'Cantaloupes', price_width, 1.92)
print format % (item_width, 'Dried Apricots(16 0z.)', price_width, 8)
print format % (item_width, 'prunex(4 1bs)', price_width, 12)

print '=' * width

结果如下

异常

抽象

懒惰即美德。

序列

数据结构:通过某种方式组织在一起的数据元素的集合,这些数据元素可以是数字或者字符,甚至可以是其他数据结构。

python中,最基本的数据结构是序列。

序列中的每个元素被分配一个序号——即元素的位置,也称为索引。第一个索引是0,第二个是1,以此类推。

基本字符串操作

字符串也是序列,因此序列的基本操作(索引、分片、连接、乘法、长度、求最大值和最小值、成员资格)对字符串同样适用:

索引

>>> ‘a_string'[0]

‘a’

长度

>>> len(‘a_string’)

8

求最大值

>>> max(‘a_string’)

‘t’

求最小值

>>> min(‘a_string’)

‘_’

乘法

>>> ‘a_string’*2

‘a_stringa_string’

连接

>>> ‘a_string’+’another_string’

‘a_stringanother_string’

分片

>>> ‘a_string'[2:6]

‘stri’

>>> ‘a_string'[1:7:3]

‘_r’

赋值

>>> ‘a_string'[3]=’b’

Traceback (most recent call last):

File “”, line 1, in

TypeError: ‘str’ object does not support item assignment

因为字符串是不可修改的,因此,赋值操作对字符串不可用。

width:35

什么是异常

Python用异常对象来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(Traceback,一种错误信息)终止执行:

>>> 1/0

Traceback (most recent call last):

File “”, line 1, in

1/0

ZeroDivisionError: integer division or modulo by zero

每个异常都是一些类的实例,这些实例可以被引发,并且可以用很多方法进行捕捉,使得程序可以捉住错误并对其进行处理,而不是让整个程序失败。

抽象和结构

抽象可以节省大量工作,实际上它的作用还要更大,它是使得计算机程序可以让人读懂的关键。

序列概览

python包含6种内建的序列:列表、元组、字符串、Unicode字符串、buffer对象和xrange对象。

列表和元组的主要区别在于,列表可以修改,元组不能。

使用后者的理由通常是技术性的,它与python内部的运作方式有关。这也是内建函数可能返回元组的原因。

一般来说,在几乎所有的情况下,列表都可以代替元组。其中一种需要注意到例外情况:使用元组作为字典的键。在这种情况下,因为键不可修改,所以不能使用列表。

字符串格式化

字符串格式化使用字符串格式化操作符,即百分号%来实现。

在%的左侧放置一个字符串(格式化字符串),而右侧则放置希望格式化的值。可以使用一个值,如一个字符串或者数字:

>>> print “Hello,%s!” %’signjing’

Hello,signjing!

>>> age=20

>>> print “I’m %d years old!” %age

I’m 20 years old!

也可以使用多个值的元组或者字典。一般情况下使用元组:

>>> format=”Hello,%s,%s enough for ya?”

>>> values=(‘world’,’Hot’)

>>> print format % values

Hello,world,Hot enough for ya?

如果使用列表或者其他序列代替元组,序列会被解释为一个值。只有元组和字典可以格式化一个以上的值。

格式化字符串的%s部分称为转换说明符,它们标记了需要插入转换值的位置。s表示值会被格式化为字符串——如果不是字符串,则会用str将其转换为字符串。这个方法对大多数值都有效。

如果要在格式化字符串里面包括百分号,那么必须使用%%,指引python就不会将百分号误认为是转换说明符了。

>>> print “%s %s” %’test’

Traceback (most recent call last):

File “”, line 1, in

TypeError: not enough arguments for format string

>>> print “%s %%s” %’test’

test %s

>>> print “%%s %s” %’test’

%s test

如果要格式化实数(浮点数),可以使用f说明符类型,同时提供所需要的精度:一个句点再加上希望保留的小数位数。因为格式化说明符总是以表示类型的字符结束,所以精度应该放在类型字符前面:

>>> print “PI is %.2f” %3.1415926

PI is 3.14

格式化操作符的右操作数可以是任何东西,如果是元组或者映射类型(如字典),那么字符串格式化将会有所不同。

如果右操作数是元组的话,其中的每一个元素都会被单独格式化,每个值都需要一个对应的转换说明符。如果需要转换的元组作为转换表达式的一部分存在,那么必须将它用圆括号括起来,以免出错:

正确

>>> ‘%s plus %s is %s’ %(12,3,4)

’12 plus 3 is 4′

错误

>>> ‘%s plus %s is %s’ %12,%3,%4

File “”, line 1

‘%s plus %s is %s’ %12,%3,%4

^

SyntaxError: invalid syntax

>>> ‘%s plus %s is %s’ %12 %3 %4

Traceback (most recent call last):

File “”, line 1, in

TypeError: not enough arguments for format string

>>> ‘%s plus %s is %s’ %12 %3 %4

Traceback (most recent call last):

File “”, line 1, in

TypeError: not enough arguments for format string

Item                            Price

Apples                         0.40
Pears                          0.50
Cantaloupes                 1.92
Dried Apricots(16 0z.)     8.00

按自己的方式出错

异常可以在某些东西出错时自动引发。

创建函数

函数可以调用(可能包含参数,也就是放在圆括号中的值),它执行某种行为并且返回一个值。一般来说,内建的callable函数可以用来判断函数是否可调用:

>>> import math

>>> y=1

>>> x=math.sqrt

>>> callable(x)

True

>>> callable(y)

False

创建函数是组织程序的关键。那么怎样定义函数呢?

使用def(或“函数定义”)语句即可:

>>> def hello(name):

return ‘Hello, ‘ + name + ‘!’

传入不同的参数,得到不同的结果:

>>> print hello(‘signjing’)

Hello, signjing!

>>> print hello(‘jiao’)

Hello, jiao!

斐波那契数列的获取方法(例如,前10项)为:

>>> f=[0,1]

>>> for i in range(8):

f.append(f[-1]+f[-2])

>>> print f

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

如果用函数的方法实现,则为:

>>> def fibs(num):

result=[0,1]

for i in range(num-2):

result.append(result[-2]+result[-1])

return result

执行结果:

>>> fibs(10)

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34]

>>> fibs(16)

[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610]

return语句是用来从函数中返回值的。

通用序列操作

所有序列类型都可以进行某些特定的操作。这些操作包括:索引、分片、加、乘以及检查某个元素是否属于序列的成员(成员资格)。除此之外,python还有计算序列长度、找出最大元素和最小元素的内建函数。

注:另外一个重要的操作:迭代,后续会接触到。

基本的转换说明符

基本的转换说明符(不包括映射键的说明符)包括如下[这些项的顺序是至关重要的]:

%[转换标志][最小字段宽度][.精度值]转换类型

%字符:

标记转换说明符的开始

转换标志(可选):

-表示左对齐;

+表示在转换值之前要加上正负号;

””(空白字符)表示正数之前保留空格;

0表示转换值若位数不够则用0填充;

最小字段宽度(可选):

转换后的字符串至少应该具有该值指定的宽度。

如果是*,则宽度会从值元组中读出。

点(.)后跟精度值(可选):

如果转换的是实数,精度值就表示出现在小数点后的位数。

如果转换的是字符串,那么该数字就表示最大字段宽度。

如果是*,那么精度将会从元组中读出。

转换类型:见下表;

字符串格式化转换类型

转换类型 含义

d,i 带符号的十进制整数

o 不带符号的八进制

u 不带符号的十进制

x 不带符号的十六进制(小写)

X 不带符号的十六进制(大写)

e 科学计数法表示的浮点数(小写)

E 科学计数法表示的浮点数(大写)

f,F 十进制浮点数

g 如果指数大于-4或者小于精度值则和e相同,其它情况与f相同

G 如果指数大于-4或者小于精度值则和E相同,其它情况与F相同

c 单字符(接受整数或者单字符字符串)

r 字符串(使用repr转换任意python对象)

s 字符串(使用str转换任意python对象)

prunex(4 1bs)               12.00

  • 字符串方法

find —
在一个较长的字符串中找子字符串,它返回子串所在位置的最左端索引,未找到则返回-1。此方法还接收可选的起始点和结束点参数。

>>> title = ‘hello. world.Hot enough for ya?’
>>> title.find(‘wor’)
7
>>> title.find(‘wor’, 2, 6)
-1

join — 在队列中添加元素

>>> seq = list(‘12345’)
>>> sep = ‘+’
>>> sep.join(seq)
‘1+2+3+4+5’
>>> dirs = ”,’usr’,’bin’,’env’
>>> ‘/’.join(dirs)
‘/usr/bin/env’
>>> ‘C:’+’\\’.join(dirs)
‘C:\\usr\\bin\\env’

lower — 返回字符串的小写字母版

replace — 返回某字符串的所有匹配项均被替换之后得到的字符串。

split — 将字符串分割成序列

>>> ‘1+2+3+4+5’.split(‘+’)
[‘1’, ‘2’, ‘3’, ‘4’, ‘5’]
>>> ‘/usr/bin/env’.split(‘/’)
[”, ‘usr’, ‘bin’, ‘env’]
>>> ‘C:\\usr\\bin\\env’.split(‘\\’)
[‘C:’, ‘usr’, ‘bin’, ‘env’]

strip  —
返回除去两侧(不包括内部)空格的字符串,也可以指定需要去除的字符。

>>> ‘++!**1+2+3+4+5*++’.strip(‘+!*’)
‘1+2+3+4+5’

translate —
可以替换字符串中的某些部分,只处理单个字符,并且可以同时进行多个替换。第一个参数指定需要替换的表,第二个参数指定需要删除的字符。

>>> from string import maketrans
>>> table = maketrans(‘cs’, ‘kz’)
>>> ‘This is an incredible test’.translate(table)
‘Thiz iz an inkredible tezt’

>>> ‘This is an incredible test’.translate(table, ‘ ‘)
‘Thizizaninkredibletezt’

 

字符串,python基础教程
字符串格式化
字符串格式化使用字符串格式化操作符即百分号%来实现。在%的左侧放置一…

raise语句

为了引发异常,可以使用一个类(应该是Exception的子类)或者实例参数调用raise语句。使用类时,程序会自动创建实例。

>>> raise Exception

Traceback (most recent call last):

File “”, line 1, in

raise Exception

Exception

>>> raise Exception(‘hyperdrive overload’)

Traceback (most recent call last):

File “”, line 1, in

raise Exception(‘hyperdrive overload’)

Exception: hyperdrive overload

第一个例子引发了一个没有任何有关错误信息的普通异常;

第二个例子则添加了一些hyperdive overload错误信息。

内建的异常类有很多。

>>> import exceptions

>>> dir(exceptions)

[‘ArithmeticError’, ‘AssertionError’, ‘AttributeError’,
‘BaseException’, ‘BufferError’, ‘BytesWarning’, ‘DeprecationWarning’,
‘EOFError’, ‘EnvironmentError’, ‘Exception’, ‘FloatingPointError’,
‘FutureWarning’, ‘GeneratorExit’, ‘IOError’, ‘ImportError’,
‘ImportWarning’, ‘IndentationError’, ‘IndexError’, ‘KeyError’,
‘KeyboardInterrupt’, ‘LookupError’, ‘MemoryError’, ‘NameError’,
‘NotImplementedError’, ‘OSError’, ‘OverflowError’,
‘PendingDeprecationWarning’, ‘ReferenceError’, ‘RuntimeError’,
‘RuntimeWarning’, ‘StandardError’, ‘StopIteration’, ‘SyntaxError’,
‘SyntaxWarning’, ‘SystemError’, ‘SystemExit’, ‘TabError’, ‘TypeError’,
‘UnboundLocalError’, ‘UnicodeDecodeError’, ‘UnicodeEncodeError’,
‘UnicodeError’, ‘UnicodeTranslateError’, ‘UnicodeWarning’,
‘UserWarning’, ‘ValueError’, ‘Warning’, ‘WindowsError’,
‘ZeroDivisionError’, ‘__doc__’, ‘__name__’, ‘__package__’]

所有这些异常都可以用于raise语句:

>>> raise ZeroDivisionError

Traceback (most recent call last):

File “”, line 1, in

raise ZeroDivisionError

ZeroDivisionError

>>> raise BaseException

Traceback (most recent call last):

File “”, line 1, in

raise BaseException

BaseException

一些最重要的内建异常类:

类名 描述
Exception 所有异常的基类
AttributeError 特性引用或赋值失败时引发
IOError 试图打开不存在的文件(包括其他情况)时引发
IndexError 在使用序列不存在的索引时引发
KeyError 在使用映射中不存在的键时引发
NameError 在找不到名字(变量)时引发
SyntaxError 在代码为错误形式时引发
TypeError 在内建操作或函数应用于错误类型的对象时引发
ValueError 在内建操作或者函数应用于正确类型的对象,但该对象使用不合适的值时引发
ZeroDivisionError 在除法或模除操作的第二个参数为0时引发

记录函数

如果想给函数写文档,让后面使用该函数的人能理解的话,可以加入注释(以#开头)。

另外一个方式是直接写上字符串。这里字符串在其它地方可能会非常有用,比如在def语句后面(以及在模块或类的开头)。如果在函数的开头写下字符串,它就会成为函数的一部分进行存储,称为文档字符串。

>>> def fibs(num):

‘fibs is a funtion:*************’

result=[0,1]

for i in range(num-2):

result.append(result[-2]+result[-1])

return result

>>> fibs.__doc__

‘fibs is a funtion:*************’

注意:__doc__是函数属性。

内建的help函数非常有用。在交互式解释器中使用它,就可以得到关于函数,包括它的文档字符串的信息。

>>> help(fibs)

Help on function fibs in module __main__:

fibs(num)

fibs is a funtion:*************

索引

序列中的所有元素都是编号的——从0开始递增。这些元素可以通过编号分别访问。使用负数索引时,python会从右边,也就是最后一个元素开始计数。最后1个元素的位置编号是-1(记住:不是0)

字符串

>>> greeting = ‘hello’

>>> greeting[0]

‘h’

>>> greeting[-1]

‘o’

>>> greeting[1]

‘e’

>>> greeting[-2]

‘l’

字符串字面值也可以使用索引。

>>> ‘hello'[-1]

‘o’

>>> ‘hello'[-2]

‘l’

列表

>>>greeting=[‘hello’,’world’,’you’,’and’,’i’]

>>> greeting[0]

‘hello’

>>> greeting[-1]

‘i’

元组

>>>greeting=(‘hello’,’world’,’you’,’i’)

>>> greeting[0]

‘hello’

>>> greeting[-2]

‘you’

如果一个函数调用返回一个序列,可以直接对返回结果进行索引操作。

>>>forth_num=raw_input(“Please input a num(lenght>4):
“)[3]

Please input a num(lenght>4): 20140508

>>> forth_num

‘4’

简单转换

带符号的十进制整数

>>> “Price is $%d” %42

‘Price is $42’

>>> “Price is $%i” %42

‘Price is $42’

不带符号的八进制

>>> “number is %o” %42

‘number is 52’

不带符号的十进制

>>> “number is %u” %100

‘number is 100’

不带符号的十六进制(大写)

>>> ‘number is %X’ %155

‘number is 9B’

不带符号的十六进制(小写)

>>> ‘number is %x’ %155

‘number is 9b’

科学计数法表示的浮点数(小写)

>>> ‘number is %e’ %155

‘number is 1.550000e+02’

科学计数法表示的浮点数(大写)

>>> ‘number is %E’ %155

‘number is 1.550000E+02’

十进制浮点数

>>> ‘number is %f’ %155

‘number is 155.000000’

>>> ‘number is %F’ %155

‘number is 155.000000’

如果指数大于-4或者小于精度值则和E相同,其它情况与F相同

>>> ‘number is %G’ %0.000000126

‘number is 1.26E-07’

>>> ‘number is %g’ %0.000000126

‘number is 1.26e-07’

>>> ‘number is %G’ %126

‘number is 126’

>>> ‘number is %g’ %126

‘number is 126’

>>> ‘number is %g’ %1260000000000

‘number is 1.26e+12’

>>> ‘number is %G’ %1260000000000

‘number is 1.26E+12’

单字符(接受整数(0~255)或者单字符字符串)

>>> ‘number is %c’ %123

‘number is {‘

>>> ‘number is %c’ %’b’

‘number is b’

>>> ‘number is %c’ %255

‘number is \xff’

>>> ‘number is %c’ %256

Traceback (most recent call last):

File “”, line 1, in

OverflowError: unsigned byte integer is greater than maximum

>>> ‘number is %c’ %0

‘number is \x00’

>>> ‘number is %c’ %-1

Traceback (most recent call last):

File “”, line 1, in

OverflowError: unsigned byte integer is less than minimum

字符串(使用str转换任意python对象)

>>> ‘Using str:%s’ %12L

‘Using str:12’

字符串(使用repr转换任意python对象)

>>> ‘Using repr:%r’ %12L

‘Using repr:12L’

自定义异常类

有些时候需要创建自己的异常类。

class SomeCustomException(Exception): pass

可以向自动义异常类中增加方法,此处什么也没做。

并非真正函数的函数

数学意义上的函数,总在计算其参数后返回点什么。python的有些函数却并不返回任何东西。

没有return语句,或者虽有return语句但return后边没有跟任何值的函数不返回值。

>>> def test():

print “This is printed”

return

print ‘this is not’

>>> x=test()

This is printed

上述函数中的return语句只起到结束函数的作用。

>>> x

>>> print x

None

所以,所有的函数的确都返回了东西:当不需要它们返回值的时候,它们就返回None。

分片

使用分片操作可以访问一定范围内的元素,通过冒号相隔的两个索引来实现。

字符串

>>> greeting = ‘Hello,world!’

>>> greeting[0:3]

‘Hel’

列表

>>> greeting=[‘hello’,’world’,’you’,’and’,’i’]

>>> greeting[1:3]

[‘world’, ‘you’]

元组

>>>greeting=(‘hello’,’world’,’you’,’i’)

>>> greeting[0:3]

(‘hello’, ‘world’, ‘you’)

可知,分片中第一个索引是需要提取部分的第一个元素的编号,第二个索引是分片之后剩下部分的第1个元素的编号。简言之,分片操作的实现需要提供两个索引作为边界,第一个索引是包含在分片内的,第2个则不包含在分片内。

字段宽度和精度

转换说明符可以包括字符宽度和精度。

字符宽度:

是转换后的值所保留的最小字符个数,

精度:

(对于数字来说)则是结果中应该包含的小数位数;

(对于字符串转换来说)是转换后的值所包含的最大字符个数;

这两个参数都是整数(首先是字符宽度,然后是精度),通过点号(.)分隔。虽然两个都是可选的参数,但如果只给出精度,就必须包含点号:

>>> from math import pi

>>> ‘%10f’ %pi

‘ 3.141593’

>>> ‘%10.2f’ %pi

‘ 3.14’

>>> ‘%.2f’ %pi

‘3.14’

>>> ‘%.5s’ % ‘Signjing’

‘Signj’

可以使用*(星号)作为字段宽度或者精度(或者两者都使用*),此时数值会从元组参数中读出:

>>> ‘%.*s’ % (5,”signjing”)

‘signj’

>>> ‘%.*s’ % (7,”signjing”)

‘signjin’

捕捉异常

关于异常最有意思的地方就是可以处理它们(通常叫做诱捕或者捕捉异常)。

这个功能可以使用try/except来实现。

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

如果用户输入0作为第二个数,则出现ZeroDivisionError异常。

为了捕捉异常并且做出一些错误处理:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

参数魔法

优雅的捷径

如果需要访问序列的最后几个元素呢?当然可以显式的操作:

>>> greeting=[‘hello’,’world’,’you’,’and’,’i’]

>>> greeting[1:5]

[‘world’, ‘you’, ‘and’, ‘i’]

索引5指向的元素并不存在,这种方法当然是可行的。但如果需要从列表的结尾开始计数呢?

>>> greeting[-4:-1]

[‘world’, ‘you’, ‘and’]

>>> greeting[-4:0]

[]

这并不是我们想要的结果。

实际上,只要分片最左边的索引比右边的晚出现在序列中,结果就是一个空序列。可以使用捷径:如果分片所得部分包含序列结尾的元素,置空最后一个索引即可:

>>> greeting[-4:]

[‘world’, ‘you’, ‘and’, ‘i’]

同样可以用于序列开始的元素:

>>> greeting[:3]

[‘hello’, ‘world’, ‘you’]

同理,想要复制整个序列,可以将两个索引置空(冒号不能省略):

>>> greeting[:]

[‘hello’, ‘world’, ‘you’, ‘and’, ‘i’]

符号、对齐和0填充

在字段宽度和精度值之前还可以放置一个“标表”,该标表可以是零、加号、减号或空格。零表示数字将会用0进行填充。

>>> ‘%10.2f’ %pi

‘ 3.14’

>>> ‘%010.2f’ %pi

‘0000003.14’

>>> ‘%+010.2f’ %pi

‘+000003.14’

>>> ‘%-010.2f’ %pi

‘3.14 ‘

>>> ‘% 10.2f’ %pi

‘ 3.14’

注意:

在010中开头的那个0并不意味着字段宽度说明符为八进制,它只是个普通的python数值。

当使用010作为字符宽度说明符的时候,表示字段宽度为10,并且用0进行填充空位,而不是说字段宽度为8:

>>> 010

8

减号(-)用来左对齐数值:

空白(“”)意味着在正数前加上空格,这在需要对齐正负数时会很用。

>>> ‘% .2f’ %pi

‘ 3.14’

>>> ‘% .2f’ %-pi

‘-3.14’

加号(+),表示不管是正数还是负数都标示出符号(同样是在对齐时很有用):

>>> print (‘%+5d’ %10)+’\n’+(‘%+5d’ % -10)

+10

-10

看,没参数

>>> class MuffledCalculator:

muffled=False

def calc(self,expr):

try:

return eval(expr)

except ZeroDivisionError:

if self.muffled:

print “Division by zero is illegal”

else:

raise

>>> calculator=MuffledCalculator()

>>> calculator.calc(’10/2′)

5

>>> calculator.calc(’10/0′)

Traceback (most recent call last):

File “”, line 1, in

calculator.calc(’10/0′)

File “”, line 5, in calc

return eval(expr)

File “”, line 1, in

ZeroDivisionError: integer division or modulo by zero

>>> calculator.muffled=True

>>> calculator.calc(’10/0′)

Division by zero is illegal

值从哪里来

写在def语句中函数名后面的变量通常叫函数的形式参数,而调用函数时提供的值是实际参数,或者成为参数。

更大的步长

进行分片,分片的开始和结束点需要进行指定,另外一个参数——步长——通常是隐式设置的。在普通的分片中,步长是1——分片操作就是按照这个步长逐个遍历序列的元素,然后返回开始和结束点之间的所有元素。

>>> numbers=[1,2,3,4,5,6,7,8,9,10]

>>> numbers[0:10:2]

[1, 3, 5, 7, 9]

捷径在这里依然适用。将每4个元素中的第一个提取出来:

>>> numbers[::4]

[1, 5, 9]

步长不能为0,因为无法向下进行:

>>> numbers[::0]

Traceback (most recent call last):

File “”, line 1, in

numbers[::0]

ValueError: slice step cannot be zero

步长可以是负数,即从右到左提取元素:

>>> numbers[8:3:-1]

[9, 8, 7, 6, 5]

>>> numbers[::-2]

[10, 8, 6, 4, 2]

>>> numbers[:5:-2]

[10, 8]

>>> numbers[5::-2]

[6, 4, 2]

>>> numbers[3:8:-1]

[]

记住:分片最左边的索引比右边的晚出现在序列中,结果就是一个空序列。

当使用一个负数作为步长时,必须让开始点大于结束点。在没有明确指定开始点和结束点的时候,正负数的使用可能会带来一些混淆。

总之,对于一个正数步长,python会从序列的头部开始向右提前元素,直至最后一个元素;

对于负数步长,从序列的尾部开始向左提取元素,直到第一个元素。

数据结构:通过某种方式组织在一起的数据元素的集合,这些数据元素可以是数字或者字符,
甚至可以是其他数据结构。 python中,最…

字符串方法

字符串方法太多,此处只列举几个比较有用的。

不止一个except子句

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

如果用户输入“HelloWorld”作为第二个参数,将引发错误:

TypeError: unsupported operand type(s) for /: ‘int’ and ‘str’

因为except子句只寻找ZeroDivisionError异常,这次的错误就溜过了检查并导致程序终止。为了捕捉这个异常,可以直接在同一个try/except语句后面加上另一个except子句:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except ZeroDivisionError:

print “The 2nd number can’t be zero!”

except TypeError:

print “That wasn’t a number,was it?”

我能改变参数吗?

在函数内为参数赋予新值不会改变外部任何变量的值。

>>> def try_to_change(n):

n=”Hello , signjing”

>>> say=”Hello , jiao”

>>> try_to_change(say)

>>> say

‘Hello , jiao’

字符串(以及数字和元组)是不可变的,即无法被修改。所以它们做参数的时候也就无需多做介绍。但如果将可变的数据结构如列表做参数的时候会发生什么:

>>> def change(n):

n[0]=’signjing’

>>> names=[‘Li lei’,’Han meimei’]

>>> change(names)

>>> names

[‘signjing’, ‘Han meimei’]

下面不用函数调用再做一次:

>>> names=[‘Li lei’,’Han meimei’]

>>> n=names

>>> n[0]=’signjing’

>>> names

[‘signjing’, ‘Han meimei’]

之前也出现过这种情况:当两个变量同时引用一个列表的时候,它们的确是同时引用一个列表。如果想避免这种情况,可以复制一个列表的副本。当在序列中做切片的时候,返回的切片总是一个副本。因此,如果你复制了整个列表的切片,将会得到一个副本:

>>> n=names[:]

>>> n

[‘Li lei’, ‘Han meimei’]

>>> names

[‘Li lei’, ‘Han meimei’]

>>> n is names

False

>>> m=n

>>> m is n

True

在某些语言(如c++、Ada)中,重绑定参数并且使这些改变影响到函数外的变量是很平常的事情。但在python中是不可能的,函数只能修改参数对象本身。但如果参数不可变,如数字,又该怎么办呢?答案是没有办法。这时候应该从函数中返回所有需要的值,如果值多于一个,则以元组形式返回。

例如,将变量数值增1的函数可以这样写:

>>> def inc(x):return x+1

>>> foo=10

>>> foo=inc(foo)

>>> foo

11

如果真的想改变参数,可以使用一点小技巧,即将值放置在列表中:

>>> def inc(x):x[0]=x[0]+1

>>> foo=[10]

>>> inc(foo)

>>> foo

[11]

这样就只会返回新值。

find

find方法可以在一个较长的字符串中查找子字符串,返回子串所在位置的最左端索引,如果没有找到则返回-1(与列表或元组的index方法找不到时则返回错误)。

>>> ‘I\’m a sunny boy’.find(‘sun’)

6

>>> ‘I\’m a sunny boy’.find(‘sunb’)

-1

find方法还可以接受可选的起始点和结束点参数:

只提供起始点:

>>> ‘I\’m a sunny boy’.find(‘sun’,5)

6

>>> ‘I\’m a sunny boy’.find(‘sun’,9)

-1

提供起始点和结束点

>>> ‘I\’m a sunny boy’.find(‘sun’,5,7)

-1

>>> ‘I\’m a sunny boy’.find(‘sun’,5,9)

6

记住,就像列表的分片操作一样,find方法的第2和第3个参数,包含第二个参数的索引值,但不包括第3个参数的索引值,这是python中的一个惯例。

>>> ‘I\’m a sunny boy’.find(‘sun’,6,9)

6

>>> ‘I\’m a sunny boy’.find(‘sun’,6,8)

-1

用一个块捕捉两个异常

如果需要用一个块捕捉多个类型异常,可以将它们作为元组列出:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except (ZeroDivisionError,TypeError):

print “Your numers are bogus!”

关键字参数和默认值

目前我们所使用的参数都叫做位置参数,因为它们的位置很重要——事实上比它们的名字更重要。

>>> def hello_1(greeting,name):

print ‘%s,%s’ %(greeting,name)

>>> def hello_2(name,greeting):

print ‘%s,%s’ %(name,greeting)

>>> hello_1(‘hello’,’boy’)

hello,boy

>>> hello_2(‘hello’,’girl’)

hello,girl

有些时候(尤其是参数很多的时候),参数的顺序是很难记住的。为了让事情简单些,可以提供参数的名字:

>>> hello_1(greeting=’hello’,name=’boy’)

hello,boy

>>> hello_1(name=’boy’,greeting=’hello’)

hello,boy

但参数名和值一定要对应:

>>> hello_2(name=’boy’,greeting=’hello’)

boy,hello

>>> hello_2(greeting=’hello’,name=’boy’)

boy,hello

这类使用参数名提供的参数叫做关键字参数。主要作用是明确每个参数的作用。

关键字参数最厉害的地方在于可以在函数中给参数提供默认值。当参数具有默认值的时候,调用的时候就不用提供参数了。可以不提供、提供一些或者提供所有的参数:

>>> def hello_3(greeting=’hello’,name=’world’):

print ‘%s,%s!’ %(greeting,name)

>>> hello_3()

hello,world!

>>> hello_3(‘Greeting’)

Greeting,world!

>>> hello_3(‘Greeting’,’universe’)

Greeting,universe!

>>> hello_3(name=’boys’)

hello,boys!

位置和关键字参数是可以联合使用的。把位置参数放置在前面就可以了。

注意:除非完全清楚程序的功能和参数的意义,否则应该避免混合使用位置参数和关键字参数。

join(非常重要)

join方法是非常重要的字符串方法,它是split方法的逆方法,用来在队列中添加元素:

>>> seq=[1,2,3,4,5]

>>> sep=’+’

>>> sep.join(seq)

Traceback (most recent call last):

File “”, line 1, in

TypeError: sequence item 0: expected string, int found

>>> seq=[‘1′,’2′,’3′,’4′,’5’]

>>> sep=’+’

>>> sep.join(seq)

‘1+2+3+4+5’

可见,需要添加的队列元素都必须是字符串。

捕捉对象

如果想让程序继续运行,但是又因为某种原因想记录下错误,捕捉对象就很有用。

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except (ZeroDivisionError,TypeError),e:

print e

收集参数

有时候让用户提供任意数量的参数是很有用的。试着像下面这样定义函数:

>>> def print_params(*params):

print params

>>> print_params(1,2)

(1, 2)

>>> print_params(1,2,’ab’)

(1, 2, ‘ab’)

参数前的星号将所有值放置在同一个元组中。可以说是将这些值收集起来,然后使用。

>>> def print_params_2(title,*params):

print title

print params

>>> print_params_2(‘Params: ‘,1,2,3)

Params:

(1, 2, 3)

如果不提供任何供收集的元素,params就是空元组:

>>> print_params_2(‘Nothing: ‘)

Nothing:

()

>>> print_params_2(‘Hmm…’,something=42)

Traceback (most recent call last):

File “”, line 1, in

print_params_2(‘Hmm…’,something=42)

TypeError: print_params_2() got an unexpected keyword argument
‘something’

我们需要另外一个能处理关键字参数的“收集”操作。

>>> def print_params_3(**params):

print params

>>> print_params_3(x=1,y=2,z=3)

{‘y’: 2, ‘x’: 1, ‘z’: 3}

lower

lower方法返回字符串的小写字母版:

>>> “Signjing”.lower()

‘signjing’

>>> “signjing”.lower()

‘signjing’

如果想编写“不区分大小写”的代码的话,该方法就派上用场了。

真正的全捕捉

就算程序能处理好几种类型的异常,但有些异常还是会从眼皮底下溜走。

以除法为例子,在提示符下直接按回车,不输入任何东西,会得倒一个类似下面的错误信息:

SyntaxError: unexpected EOF while parsing

这个异常逃过了try/except语句的检查。这种情况下,与其用那些并非捕捉这些异常的try/except语句隐藏异常,还不如让程序立刻崩溃。

但如果真的想用一段代码捕获所有异常,可以在except子句中忽略所有的异常类:

try:

x=input(‘1st number: ’)

y=input(‘2nd number: ’)

print x/y

except:

print ‘Something wrong happened…’

警告:像这样捕捉所有异常是危险的,因为它会隐藏所有程序员未想到并且未做好准备处理的错误。它同样会捕捉用户终止执行的Ctrl+c企图,以及用sys.exit函数终止程序的企图,等等。这时用except
Exception,e会更好些,或者对异常对象e进行一些检查。

反转过程

>>> def add(x,y):

return x+y

>>> params=(1,2)

>>> add(*params)

3

在调用中使用而不是在定义中使用。

对于参数列表来说工作正常,只要扩展到部分是最新的就可以。可以使用同样的技术来处理字典——使用双星号运算符。

>>> def hello_3(greeting=’hello’,name=’world’):

print ‘%s, %s!’ %(greeting,name)

>>> params={‘name’:’Sir Robin’,’greeting’:’Well met’}

>>> hello_3(*params)

name, greeting!

>>> hello_3(**params)

Well met, Sir Robin!

星号只在定义函数(允许使用不定数目的参数)或者调用(“分割”字典或者序列)时才有用。

replace

replace方法返回某字符串的所有匹配项均被替换之后得到字符串。

>>> “Signjing”.replace(“Si”,”fin”)

‘fingnjing’

>>> “This is a test”.replace(“is”,”eez”)

‘Theez eez a test’

万事大吉

有些情况下,一些坏事发生时执行一段代码是很有用的,可以给try/except语句加个else子句:

>>> try:

print ‘A simple task’

except:

print ‘what?’

else:

print ‘nothing’

A simple task

nothing

作用域

变量和所对应的值用的是个“不可见”的字典。实际上这么说已经很接近真实情况了。内建的vars函数可以返回这个字典:

>>> x=1

>>> scope=vars()

>>> scope[‘x’]

1

>>> scope[‘x’]+=1

>>> x

2

这类“不可见字典”叫做命名空间或者作用域。到底有多少个命名空间?除了全局作用域外,每个函数调用都会创建一个新的作用域;

参数的工作原理类似于局部变量,所以用全局变量的名字作为参数名并没有问题。

如果需要在函数内部访问全局变量,应该怎么办呢?而且只想读取变量的值(也就是说不想重绑定变量),一般来说是没有问题的:

>>> def combine(parameter):

print parameter+external

>>> external=’berry’

>>> combine(‘Shrub’)

Shrubberry

读取全局变量一般来说并不是问题,但是还是有个会出问题的事情。如果局部变量或者参数的名字和想要访问的全局变量名相同的话,就不能直接访问了。全局变量会被局部变量屏蔽。

如果的确需要的话,可以使用globals函数获取全局变量值,该函数的近亲是vars,它可以返回全局变量的字典(locals返回局部变量的字典)。

重绑定全局变量(使变量引用其他新值):如果在函数内部将值赋予一个变量,它会自动成为局部变量——除非告知python将其声明为全局变量。

>>> x=1

>>> def change_global():

global x

x=x+1

>>> change_global()

>>> x

2

split(非常重要)

它是join的逆方法,用来将字符串分割为序列。

>>> ‘id,index,name,info’.split(‘,’)

[‘id’, ‘index’, ‘name’, ‘info’]

如果不提供任何分隔符,程序会把所有空格作为分割符(空格、制表、换行等)。

>>> ‘id index name info’.split()

[‘id’, ‘index’, ‘name’, ‘info’]

>>> ‘id index name info’.split()

[‘id’, ‘index’, ‘name’, ‘info’]

最后……

finally子句,用来在可能的异常后进行清理。

>>> try:

print ‘A simple task’

except:

print ‘what?’

else:

print ‘nothing’

finally:

print ‘clean up’

A simple task

nothing

clean up

递归

想到了一个笑话:

你要想理解递归,首先得理解递归。

好吧,有点冷,继续热乎的话题….

递归的定义(包括递归函数定义)包括它们自身定义内容的引用。

需要查找递归的意思,结果它告诉请参见递归,无穷尽也,一个类似的函数定义如下:

>>> def recursion():

return recursion()

显然它什么也做不了,理论上讲,它应该永远运行下去。

由于每次调用函数都会用掉一点内存,在足够的函数调用发生后,空间就不够了,程序以一个“超过最大递归深度”的错误信息结束:

Traceback (most recent call last):

File “”, line 1, in

recursion()

File “”, line 2, in recursion

return recursion()

……

File “”, line 2, in recursion

return recursion()

RuntimeError: maximum recursion depth exceeded

这类递归叫无穷递归,类似于while
True开始的无穷循环,中间没有break或return语句。

有用的递归函数包括以下几个部分:

当函数直接返回值时有基本实例(最小可能性问题);

递归实例,包括一个或者多个问题最小部分的递归调用;

strip

strip方法返回去除两侧(不包括内部)空格的字符串:

>>> ” space space “.strip()

‘space space’

strip方法和lower方法一起使用可以很方便地对比输入的和存储的值。

也可以指定需要去除的字符:

>>> ‘space space’.strip(‘e’)

‘space spac’

>>> ‘space space’.strip(‘se’)

‘pace spac’

异常和函数

异常和函数很自然地一起工作。如果异常在函数内引发而不被处理,它会传播至函数调用的地方。如果在那里也没有处理异常,它会继续传播,一直到达主程序(全局作用域)。如果那里没有异常处理程序,程序会带着堆栈跟踪终止。

>>> def faulty():

raise Exception(‘something is wrong’)

>>> def ignore_exception():

faulty()

>>> def handle_exception():

try:

faulty()

except:

print ‘Exception handled’

>>> ignore_exception()

Traceback (most recent call last):

File “”, line 1, in

ignore_exception()

File “”, line 2, in ignore_exception

faulty()

File “”, line 2, in faulty

raise Exception(‘something is wrong’)

Exception: something is wrong

>>> handle_exception()

Exception handled

什么是异常
Python用异常对象来表示异常情况。遇到错误后,会引发异常。如果异常对象并未被处理或捕捉,程序就会用所谓的回溯(…

两个经典:阶乘和幂

>>> def factorial(n):

result=n

for i in range(1,n):

result*=i

return result

>>> factorial(5)

120

递归的实现方式:

>>> def factorial(n):

if n==1:

return 1

else:

return n*factorial(n-1)

>>> factorial(4)

24

>>> def power(x,n):

result=1

for i in range(n):

result*=x

return result

>>> power(5,3)

125

递归实现:

>>> def power(x,n):

if n==0:

return 1

else:

return x*power(x,n-1)

>>> power(4,4)

256

translate

translate方法和replace方法一样,可以替换字符串中的某些部分,但和后者不同的是,translate方法只处理单个字符。它的优势在于可以同时进行多个替换,有些时候比replace效率高得多。

在使用translate转换之前,需要先完成一张转换表。转换表中是以字符替换某字符的对应关系。因为这个表(事实上是字符串)有多达256个项目,可以直接使用string模块里面的maketrans函数。

maketrans函数接受两个参数:两个等长的字符串,表示第一个字符串中的每个字符都用第二个字符串中相同位置的字符替换。

>>> from string import maketrans

>>> table=maketrans(‘cs’,’kz’)

>>> len(table)

256

>>> table

‘\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f
!”#$%&\'()*+,-./0123456789:;<=>[email protected][\\]^_`abkdefghijklmnopqrztuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff’

>>> table[97:123]

‘abkdefghijklmnopqrztuvwxyz’

>>> maketrans(”,”)[97:123]

‘abcdefghijklmnopqrstuvwxyz’

>>> maketrans(‘cs’,’kz’)[97:123]

‘abkdefghijklmnopqrztuvwxyz’

创建这个表后,可以用作translate方法的参数,进行字符串的转换如下:

>>> ‘this is an incredible test’.translate(table)

‘thiz iz an inkredible tezt’

第二个参数可选,用来指定需要删除的字符:

>>> ‘this is an incredible test’.translate(table,’ ‘)

‘thizizaninkredibletezt’

>>> ‘this is an incredible test’.translate(table,’thi’)

‘z z an nkredble ez’

基本字符串操作
字符串也是序列,因此序列的基本操作(索引、分片、连接、乘法、长度、求最大和最小、成员资)对字符串同样…

另一个经典:二元查找

此处略;

对象的魔力

创建自己的对象(尤其是类型或者被称为类的对象)是python的核心概念——非常核心。

面向对象程序设计中的术语对象基本上可以看作数据(特性)以及由一系列可以存取、操作这些数据的方法所组成的集合。

对象最重要的优点包括以下几个方面:

多态:可以对不同类的对象使用同样的操作;

封装:对外部世界隐藏对象的工作细节;

继承:以普通的类为基础建立专门的类对象;

类和类型

类到底是什么

类就是一种对象。所有的对象都属于某一个类,成为类的实例。

当一个对象所属的类是另外一个对象所属类的子集时,前者就被称为后者的子类,相反,后者就称为前者的超类(基类)。

在面向对象程序设计中,子类的关系是隐式的,因为一个类的定义取决于它所支持的方法。定义子类只是定义更多(也有可能是重载已经存在的)的方法的过程。

创建自己的类

>>> __metaclass__ = type

>>> class Person:

def setName(self,name):

self.name=name

def getName(self):

return self.name

def greet(self):

print “Hello,world!I’m %s.” %self.name

>>> foo=Person()

>>> bar=Person()

>>> foo.setName(‘abc’)

>>> foo.getName()

‘abc’

>>> foo.greet()

Hello,world!I’m abc.

self是对于对象自身的引用。没有它,成员方法就没法访问他们要对其特性进行操作的对象本身了。

特效、函数和方法

默认情况下,程序可以从外部访问一个对象的特性。

为了让方法或特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可:

>>> class Secretive:

def __inaccessible(self):

print “Bet you can’t see me…”

def accessible(self):

print “The secret message is:”

self.__inaccessible()

>>> s.__inaccessible()

Traceback (most recent call last):

File “”, line 1, in

s.__inaccessible()

AttributeError: ‘Secretive’ object has no attribute ‘__inaccessible’

>>> s.accessible()

The secret message is:

Bet you can’t see me…

类的内部定义中,所有以双下划线开始的名字都被“翻译”成前面加上单下划线和类名的形式:

>>> Secretive._Secretive__inaccessible

简而言之,确保其他人不会访问对象的方法和特性是不可能的,但是这类“名称变化术”就是他们不应该访问这些函数或者特性的强有力信号。

类的命名空间

类的定义其实就是执行代码块,这一点非常有用。

指定超类

将其他类名写在class语句后的圆括号内可以指定超类:

>>> class Filter:

def init(self):

self.blocked=[]

def filter(self,sequence):

return [x for x in sequence if x not in self.blocked]

>>> class SPAMFilter(Filter):

def init(self):

self.blocked=[‘SPAM’]

Filter是个用于过滤序列的通用类,事实上它不能过滤任何东西:

>>> f=Filter()

>>> f.init()

>>> f.filter([1,3,4])

[1, 3, 4]

Filter类的用处在于它可以用作其他类的基类(超类),可以将序列中的“SPAM”过滤出去。

>>> s=SPAMFilter()

>>> s.init()

>>> s.filter([‘abc’,’SPAM’,”SPAM”,’SPAM’,’signjing’])

[‘abc’, ‘signjing’]

调查继承

想要查看一个类是否是另一个的子类,可以使用内建的issubclass函数:

>>> issubclass(SPAMFilter,Filter)

True

>>> issubclass(Filter,SPAMFilter)

False

如果想要知道已知类的基类(们),可以直接使用它的特殊特性__bases__:

>>> SPAMFilter.__bases__

(,)

>>> Filter.__bases__

(,)

同样,还能使用isinstance方法检查一个对象是否是一个类的实例:

>>> isinstance(s,SPAMFilter)

True

>>> isinstance(s,Filter)

True

>>> isinstance(s,str)

False

S是SPAMFilter类的(直接)成员,但也是Filter类的间接成员,因为SPAMFilter是Filter的子类。

如果想知道一个对象属于哪个类,可以使用__class__特性:

>>> s.__class__

多个超类

>>> class Calculator:

def calculate(self,expression):

self.value=eval(expression)

>>> class Talker:

def talk(self):

print ‘Hi,my value is’,self.value

>>> class TalkingCalculator(Calculator,Talker):

pass

超类可以有多个。

在这里,子类不做任何事,从自己的超类继承所有的行为。

这种行为成为多重继承,是个非常有用的工具。

使用多重继承时,有个需要注意的地方。如果一个方法从多个超类继承,必须要注意一下超类的顺序:

先继承的类中的方法会重写后继承的类中的方法。

懒惰即美德。 抽象和结构
抽象可以节省大量工作,实际上它的作用还要更大,它是使得计算机程序可以让人读懂的关键。
创建函数…

You may also like...

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图