python中if语句缺省else_python 1

>>> f = fib

>>> f(100)

1 1 2 3 5 8 13 21 34 55 89

>>>

你可能会说 fib

不是函数而是过程。Python和C一样,过程只是不返回值的函数。实际上,严格地说,过程也返回一个值,只不过是一个很没意思的值。这个值叫做

None(这是一个内置的名字)。解释程序交互运行时如果只需要显示这个值的话就会忽略不显示。如果希望显示的话可以用 print 语句:

>>> print fib(0)

None

>>>

也可以写一个函数返回Fibonacci 序列的数值列表而不是显示这些值:

>>> def fib2(n): # 返回直到n的Fibonacci 序列值

... result = []

... a, b = 0, 1

... while b < n:

... result.append(b) # 解释见下面

... a, b = b, a+b

... return result

...

>>> f100 = fib2(100) # 调用

>>> f100 # 输出结果

[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

>>>

这个例子也演示了新的Python特色:return语句从函数中退出并返回一个值。不带返回值的return可以从过程中间退出,运行到过程的末尾也可以退出,这两种情况下返回None。

语句result.append(b)调用列表对象result的一个方法。方法是“属于”一个对象的函数,引用格式为obj.methodname,其中obj是某个对象(也允许是一个表达式),

methodname

是由该对象的类型定义的一个方法的名字。不同的不同的方法。不同类型的方法可以使用相同的名字而不致引起误解。(可以定义自己的对象类型和方法,使用类,本文后面会讨论这个话题)。例子中的append()方法时列表对象的方法,它在列表末尾增加一个新元素。在本例中这等价于“result

= result + [b]”,只是更有效。

4.7 函数参数

可以定义使用可变个数参数的函数。这样的定义方法有三种,可以联合使用。

4.7.1 参数缺省值

可以为一个参数或几个参数指定缺省值。这样定义的函数在调用时实参个数可以比定义时少。例如:def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):

while 1:

ok = raw_input(prompt)

if ok in ('y', 'ye', 'yes'): return 1

if ok in ('n', 'no', 'nop', 'nope'): return 0

retries = retries - 1

if retries < 0: raise IOError, 'refusenik user'

print complaint

这个函数在调用时既可以这样调用:ask_ok('Do you really want to quit?'),或者可以这样调用:ask_ok('OK to

overwrite the file?', 2)。缺省值是在函数定义时的定义作用域中计算的,所以例如:i = 5

def f(arg = i): print arg

i = 6

f()

将显示5。

注意:缺省值只计算一次。当缺省值是可变对象如列表或字典时这一点是要注意的。例如,以下函数会在以后的调用中累加它的值:def f(a, l = []):

l.append(a)

return l

print f(1)

print f(2)

print f(3)

This will print

[1]

[1, 2]

[1, 2, 3]

如果你不希望缺省值在连续的调用中被保留,可以象下面这样改写函数:def f(a, l = None):

if l is None:

l = []

l.append(a)

return l

4.7.2 关键字参数

函数调用时也可以象“关键字 = 值”这样指定实参,其中关键字是定义时使用的形参的名字。例如:def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):

print "-- This parrot wouldn't", action,

print "if you put", voltage, "Volts through it."

print "-- Lovely plumage, the", type

print "-- It's", state, "!"

可以用如下几种方式调用:parrot(1000)# 缺省值

parrot(action = 'VOOOOOM', voltage = 1000000)# 关键字,缺省值,次序可变

parrot('a thousand', state = 'pushing up the daisies')# 位置参数,缺省值,关键字

parrot('a million', 'bereft of life', 'jump')# 位置参数,缺省值

但以下几种调用方式是错误的:

parrot() # 非缺省的参数没有提供

parrot(voltage=5.0, 'dead') # 关键字参数后面又出现了非关键字参数

parrot(110, voltage=220) # 参数值重复提供

parrot(actor='John Cleese') # 未知关键字

一般说来,实参表中位置参数在前,关键字参数在后,关键字名字必须是形参名字。形参有没有缺省值都可以用关键字参数的形式调用。每一形参至多只能对应一个实参,因此,已经由位置参数传入值的形参就不能在同一调用中再作为关键字参数。

如果形参表中有一个形为**name的形参,在调用时这个形参可以接收一个字典,字典中包含所有不与任何形参匹配的关键字参数。形参表中还可以使用一个特殊的如*name的形参,它将接受所有不能匹配的位置参数组成的一个序表。*name只能在**name之前出现。例如,如果定义了下面的函数:def cheeseshop(kind, *arguments, **keywords):

print "-- Do you have any", kind, '?'

print "-- I'm sorry, we're all out of", kind

for arg in arguments: print arg

print '-'*40

for kw in keywords.keys(): print kw, ':', keywords[kw]

就可以象下面这样调用:cheeseshop('Limburger', "It's very runny, sir.",

"It's really very, VERY runny, sir.",

client='John Cleese',

shopkeeper='Michael Palin',

sketch='Cheese Shop Sketch')

结果显示:-- Do you have any Limburger ?

-- I'm sorry, we're all out of Limburger

It's very runny, sir.

It's really very, VERY runny, sir.

----------------------------------------

client : John Cleese

shopkeeper : Michael Palin

sketch : Cheese Shop Sketch

4.7.3 任意个数参数

在所有有名的形参的后面可以有两个特殊的形参,一个以*args的形式命名,一个以**kw

的形式命名。有了*args形式的形参后函数在调用时就可以在正常的能匹配的实参表后面输入任意个数的参数,这些参数组成一个序表赋给args形参,不能匹配的关键字参数组成一个字典赋给kw形参。在任意个数形参之前可以有0到多个正常的参数。例如:def fprintf(file, format, *args):

file.write(format % args)

4.7.4 Lambda形式

因为许多人的要求,Python中加入了一些在函数编程语言和Lisp中常见的功能。可以用lambda

关键字来定义小的无名函数。这是一个返回其两个参数的和的函数:“lambda a, b: a+b”

。Lambda形式可以用于任何需要函数对象的地方。从句法上讲lambda形式局限于一个表达式。从语义上讲,这只是正常的函数定义的句法甜食。像嵌套函数定义一样,lambda形式不能访问包含其定义的作用域中的变量,但审慎地使用缺省参数之可以绕过这个限制。例如:def make_incrementor(n):

return lambda x, incr=n: x+incr

4.7.5 文档字符串

关于文档字符串的内容与格式正在形成一些惯例。第一行应该为简短的对象目的概括说明。为了简明起见,这一行不应该提及对象的名字或类型,因为这些可以通过其他途径得知(当然如果对象名字就是一个描述函数操作的动词则当然可以提及其名字)。着以行应该用大些字母开始,以句点结尾。如果文档字符串中有多行,第二行应该是空行,把概括说明与其它说明分开。以下的行可以是一段或几段,描述对象的调用方法,它的副作用,等等。

Python的扫描程序不会从多行字符串中去掉缩进空白,所以处理文档的工具需要自己处理缩进。只要遵循如下的惯例就可以有利于缩进空白的处理。在第一行之后的第一个非空白的行决定整个文档字符串的缩进数量(我们不用第一行,因为它经常是直接跟在表示字符串开始的引号后面)。文档字符串中除第一行以外的各行都要删除等价于此行的缩进量的空白。对制表符将扩展为空格后再删除。

第五章 Python数据结构

本章更详细地讨论一些已经讲过的数据类型的使用,并引入一些新的类型。

5.1 列表

列表数据类型还有其它一些方法。下面是列表对象的所有方法:

insert(i, x) ---- 在指定位置插入一项。第一自变量是要在哪一个元素前面插入,用下标表示。例如,a.insert(0,

x)在列表前面插入,a.insert(len(a), x)等价于a.append(x) 。

append(x) ---- 等价于a.insert(len(a), x)

index(x) ---- 在列表中查找值x然后返回第一个值为x的元素的下标。没有找到时出错。

remove(x) ---- 从列表中删去第一个值为x的元素,找不到时出错。

sort() ---- 对列表元素在原位排序。注意这个方法改变列表,而不是返回排序后的列表。

reverse() ---- 把列表元素反序。改变列表。

count(x) ---- 返回x在列表中出现的次数。

下例使用了所有的列表方法:>>> a = [66.6, 333, 333, 1, 1234.5]

>>> print a.count(333), a.count(66.6), a.count('x')

2 1 0

>>> a.insert(2, -1)

>>> a.append(333)

>>> a

[66.6, 333, -1, 333, 1, 1234.5, 333]

>>> a.index(333)

1

>>> a.remove(333)

>>> a

[66.6, -1, 333, 1, 1234.5, 333]

>>> a.reverse()

>>> a

[333, 1234.5, 1, 333, -1, 66.6]

>>> a.sort()

>>> a

[-1, 1, 66.6, 333, 333, 1234.5]

5.1.1 函数程序设计工具

Python中有一些函数程序设计风格的东西,例如前面我们看到的lambda形式。关于列表有三个非常有用的内置函数:filter(),

map()和reduce()。

“filter(函数,

序列)”返回一个序列(尽可能与原来同类型),序列元素是原序列中由指定的函数筛选出来的那些,筛选规则是“函数(序列元素)=true”。filter()可以用来取出满足条件的子集。例如,为了计算一些素数:>>> def f(x): return x % 2 != 0 and x % 3 != 0

...

>>> filter(f, range(2, 25))

[5, 7, 11, 13, 17, 19, 23]

“map(函数,序列)”对指定序列的每一项调用指定的函数,结果为返回值组成的列表。map() 可以对序列进行隐式循环。例如,要计算三次方,可用:>>> def cube(x): return x*x*x

...

>>> map(cube, range(1, 11))

[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

可以有多个序列作为自变量,这时指定的函数必须也有相同个数的自变量,函数从每个序列分别取出对应元素作为自变量进行调用(如果某个序列比其它的短则取出的值是None)。如果指定的函数是None,map()把它当成一个返回自己的自变量的恒同函数。在函数用None的情况下指定多个序列可以把多个序列搭配起来,比如“map(None,

list1, list2)”可以把两个列表组合为一个成对值的列表。见下例:>>> seq = range(8)

>>> def square(x): return x*x

...

>>> map(None, seq, map(square, seq))

[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25), (6, 36), (7, 49)]

“reduce(函数,

序列)”用来进行类似累加这样的操作,这里的函数是一个两个子变量的函数,reduce()先对序列的前两项调用函数得到一个结果,然后对结果和序列下一项调用函数得到一个新结果,如此进行到序列尾部。例如,要计算1到10的和:>>> def add(x,y): return x+y

...

>>> reduce(add, range(1, 11))

55

如果序列中只有一个值则返回这个值,序列为空时会产生例外。可以指定第三个自变量作为初始值。有初始值时对空序列函数将返回初始值,否则函数先对初始值和序列第一项作用,然后对结果和序列下一项作用,如此进行到序列尾。例如:>>> def sum(seq):

... def add(x,y): return x+y

... return reduce(add, seq, 0)

...

>>> sum(range(1, 11))

55

>>> sum([])

0

5.2 del语句

上面我们看到,列表的remove()方法可以从列表中删去某个取值的项,我们还可以用del

语句来删除指定下标的项。也可以用del语句从列表中删除一个片断(前面我们是用给片断赋空列表的办法删除片断的)。例如:>>> a

[-1, 1, 66.6, 333, 333, 1234.5]

>>> del a[0]

>>> a

[1, 66.6, 333, 333, 1234.5]

>>> del a[2:4]

>>> a

[1, 66.6, 1234.5]

del也可以用来删除整个变量,例如:

>>> del a

变量删除以后再引用该变量就会出错(除非又给它赋值了)。后面我们还会看到del的其它一些应用。

5.3 序表和序列

我们看到列表和字符串有许多共同点,例如,下标和片断运算。它们都属于序列数据类型。因为Python是一个正在不断发展的语言,以后还可能会加入其它的序列数据类型。现在还有一种标准的序列数据类型,称为序表(tuple)。

序表由一系列值用逗号分隔而成,例如:>>> t = 12345, 54321, 'hello!'

>>> t[0]

12345

>>> t

(12345, 54321, 'hello!')

>>> # 序表允许嵌套:

... u = t, (1, 2, 3, 4, 5)

>>> u

((12345, 54321, 'hello!'), (1, 2, 3, 4, 5))

输出的序表总是用括号包围,这样可以保证嵌套序表得以正确解释。输入时可以有括号也可以没有括号,当经常是必须有括号(如果序表是一个大表达式的一部分)。

序表有许多用处,例如,(x,y)坐标对,数据库中的职工纪录,等等。序表与字符串一样是不可变的:不允许对序表的某一项赋值。

生成序表时对0项或1项的序表有特殊的规定:空序表用一对空括号表示;只有一项的序表用一个之后面跟一个抖好表示(指把这个值放在括号内是不够的)。这样写不够美观,但很有效。例如:>>> empty = ()

>>> singleton = 'hello', # >> len(empty)

0

>>> len(singleton)

1

>>> singleton

('hello',)

语句t = 12345, 54321, 'hello!'是序表打包的一个实例:12345,

54321和'hello!'这些值被打包进了一个序表中。相反的操作也是允许的,例如:

>>> x, y, z = t

这叫做序表解包。序表解包要求等号左边的变量个数等于序表的长度。注意多重赋值只是序表打包和序表解包的联合使用。有时也对列表进行类似操作,即列表解包。只要把各变量写成一个列表就可以进行解包:>>> a = ['spam', 'eggs', 100, 1234]

>>> [a1, a2, a3, a4] = a

5.4 字典

Python内置的另一个有用的数据类型是字典。字典在其它语言中有时被称为“关联记忆”

或“关联数组”。字典不象序列,它不是用在一个范围之内的数字下标来索引,而是用键值来索引,键值可以是任何不可变类型。字符串和数值总可以作键值。如果序表只包含字符串、数值或序表则序表也可以作键值使用。列表不能用作键值,因为列表可以用其append()方法就地改变值。

最好把字典看成是一系列未排序的“键值:值”的集合,在同一字典内键值是互不相同的。一对空大括号产生一个空字典:{}。在大括号内加入用逗号分开的“键值:值”对可以在字典内加入初始的键值和值对,字典在输出时也是这样显示的。对字典的主要操作是以某个键值保存一个值,以及给定键值后查找对应的值。也可以用del删除某个键值:值对。如果用一个已有定义的键值保存某个值则原来的植被遗忘。用不存在的键值去查找会出错。

字典对象的keys()方法返回字典中所有键值组成的列表,次序是随机的。需要排序时只要对返回的键值列表使用sort()方法。为了检查某个键值是否在字典中,使用字典的has_key()

方法。

下面是字典使用的一个简单例子:>>> tel = {'jack': 4098, 'sape': 4139}

>>> tel['guido'] = 4127

>>> tel

{'sape': 4139, 'guido': 4127, 'jack': 4098}

>>> tel['jack']

4098

>>> del tel['sape']

>>> tel['irv'] = 4127

>>> tel

{'guido': 4127, 'irv': 4127, 'jack': 4098}

>>> tel.keys()

['guido', 'irv', 'jack']

>>> tel.has_key('guido')

1

5.5 条件的进一步讨论

在while语句和if语句中使用的条件除了可以使用比较之外还可以包含其它的运算符。比较运算符“in”和“not

in”可以检查一个值是否在一个序列中。运算符“is”和“is not

”比较两个对象是否恰好是同一个对象,这只对象列表这样的可变对象有意义。所有比较运算优先级相同,而比较运算的优先级比所有数值运算优先级低。

比较允许连写,例如,a < b == c检查是否a小于等于b而且b等于c。

比较可以用逻辑运算符and和or连接起来,比较的结果(或其它任何逻辑表达式)可以用not

取反。逻辑运算符又比所有比较运算符低,在逻辑运算符中,not优先级最高,or的优先级最低,所以“A and not B or C”应解释为“(A and

(not B)) or C”。当然,可以用括号来表示所需的组合条件。

逻辑运算符and和or称为“短路”运算符:运算符两侧的表达式是先计算左边的,如果左边的结果已知则整体结果已知就不再计算右边的表达式。例如,如果A和C为真而B为假则“A

and B and C”不会计算表达式C。一般地,当短路运算符的运算结果不是用作逻辑值的时候返回的是最后求值的那个表达式的值。

可以把比较或其它逻辑表达式的结果赋给一个变量。例如:>>> string1, string2, string3 = '', 'Trondheim', 'Hammer Dance'

>>> non_null = string1 or string2 or string3

>>> non_null

'Trondheim'

注意Python和C不同,表达式中不能进行赋值。

5.6 序列与其它类型的比较

序列对象可以和其它同序列类型的对象比较。比较使用字典序:先比较最前面两项,如果这两项不同则结果可以确定;如果这两项相同,就比较下面的两项,如此下去,直到有一个序列到头为止。如果某两项本身也是同类型的序列,则进行递归的字典序比较。如果两个序列的所有各项都相等,则这两个序列相等。如果一个序列是另一个序列的一个初始子序列,短的一个是较小的一个。字符串的字典序比较按各个字符的ASCII次序进行。下面是一些序列比较的实例:(1, 2, 3) < (1, 2, 4)

[1, 2, 3] < [1, 2, 4]

'ABC' < 'C' < 'Pascal' < 'Python'

(1, 2, 3, 4) < (1, 2, 4)

(1, 2) < (1, 2, -1)

(1, 2, 3) = (1.0, 2.0, 3.0)

(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)

注意不同类型的对象比较目前也是合法的。结果是确定的但却没有什么意义:不同类型是按类型的名字排序的。所以,列表(list)总是小于字符串(string),字符串总是小于序表(tuple),等等。但是程序中不能依赖这样的比较规则,语言实现可能会改变。不同的数值类型可以按数值来比较,所以0等于0.0,等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值