python之条件-循环和其他语句

发布时间:2019-06-25 09:54:21编辑:auto阅读(1158)

    5.1.1 使用逗号输出

    如何使用print来打印表达式----不管是字符串还是其他类型进行自动转换后的字符串。

    >>> print 'age:' , 42

    age: 42

    >>>


    >>> print 1,2,3

    1 2 3

    >>> 1,2,3

    (1, 2, 3)

    >>> print (1,2,3)

    (1, 2, 3)

    >>>


    如果想要同时输出文本和变量值,却不希望使用字符串格式化的话,那这个特性就非常有用了

    >>> name = 'Gumby'

    >>> salutation = 'Mr'

    >>> greeting = 'Hello'

    >>> print greeting,salutation,name

    Hello Mr Gumby

    >>>


    注意,如果greeting字符串不带逗号,那么结果中怎么能得到逗号呢?像下面这样做是不行的

    print greeting,',',salutation,name

    因为上面的语句会在逗号前加入空格。下面是一种解决方案:

    print greeting + ',',salutation,name

    这样一来,问候语后面就只会增加一个逗号.

    如果在结尾处加上逗号,那么接下来的语句会与前一条语句在同一行打印。例如:

    print 'Hello,',

    print 'world!'



    5.1.2 把某件事作为另一件事导入

    从模块导入函数的时候,可以使用

    import somemodule

    或者

    from somemodule import somefunction

    或者

    from somemodule import somefunction,anotherfunction,yetanotherfunction

    或者

    from somemodule import *


    只有确定自己想要从给定的模块导入所有功能时,才应该使用最后一个版本。但是如果两个模块都有open函数,那又该怎么办?只需使用第一种方式导入,然后像下面这样使用函数:

    module1.open(...)

    module2.open(...)

    但还有另外的选择:可以再语句末尾增加一个as子句,在该子句后给出名字,或为整个模块提供别名:

    >>> import math as foobar

    >>> foobar.sqrt(4)

    2.0

    >>>

    也可以为函数提供别名

    >>> from math import sqrt as foobar

    >>> foobar(4)

    2.0

    >>>


    对于open函数,可以像下面这样使用

    from module1 import open as open1

    from modulel import open as open2


    5.2 赋值魔法

    5.2.1 序列解包

    赋值语句的例子已经给过不少,其中包括对变量和数据结构成员的(比如列表中的位置和分片以及字典中的槽)赋值。但赋值的方法还不止这些。比如,多个赋值操作可以同时进行:

    >>> x,y,z = 1,2,3

    >>> print x,y,z

    1 2 3

    >>>


    用它交换两个(或更多个)变量也是没问题的:

    >>> x,y = y,x

    >>> print x,y,z

    2 1 3

    >>>


    事实上,这里所做的事情叫做序列解包或可选代解包------将多个值的序列解开,然后放到变量的序列中。更形象一点的表示出来就是:

    >>> values = 1,2,3

    >>> values

    (1, 2, 3)

    >>> x,y,z = values

    >>> x

    1

    >>>


    当函数或者方法返回元组时,这个特性尤其有用。假设需要获取字典中任意的键-值对,可以使用popitem方法,这个方法将键-值作为元组返回。那么这个元组就可以直接赋值到两个变量中:


    >>> scoundrel = {'name':'Robin','girlfriend':'Marion'}

    >>> key,value = scoundrel.popitem()

    >>> key

    'girlfriend'

    >>> value

    'Marion'

    >>>



    它允许函数返回一个以上的值并且打包成元组,然后通过一个赋值语句很容易进行访问。所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则python会在赋值时引发异常:

    >>> x,y,z = 1,2

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    ValueError: need more than 2 values to unpack

    >>> x,y,z = 1,2,3,4

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    ValueError: too many values to unpack

    >>>


    python3.0中有另外一个解包的特性:可以像在函数的参数列表中一样使用星号运算符。


    5.2.2 链式赋值

    链式赋值是将同一个值赋给多个变量的捷径.它看起来有些像上节中的并行赋值,不过这里只处理一个值:

    x = y = somefunction()

    和下面语句的效果是一样的

    y = somefunction()

    x = y

    注意上面的语句和下面的语句不一定等价

    x = somefunction()

    y = somefunction()


    5.2.3 增量赋值

    这里没有将赋值表达式写为x=x+1,而是将表达式运算符放置在赋值运算符=的左边,写成x+=1.这种写法叫做增量赋值,对于* / %等标准运算符都适用

    >>> x = 2

    >>> x += 1

    >>> x *= 2

    >>> x

    6

    >>>


    对于其他数据类型也适用

    >>> fnord = 'foo'

    >>> fnord += 'bar'

    >>> fnord *= 2

    >>> fnord

    'foobarfoobar'

    >>>


    5.3 语句块:缩排的乐趣

    语句块并非一种语句,而是在掌握后面的两节的内容之前应该了解的知识

    语句块是在条件为真时执行或执行多次的一组语句.在代码前放置空格来缩进语句即可创建语句块.


    使用tab字符也可以缩进语句块.python将一个tab字符解释为到下一个tab字符位置的移动,而一个tab字符位置为8个空格,但是标准且推荐的方式是只用空格,尤其是在每个缩进需要4个空格的时候.


    块中的每行都应该缩进同样的量.下面的伪代码展示了缩进的工作方式.

    this is a line

    this is another line:

    this is another block

    continuing the same block

    the last line of this block

    phew.there we escaped the inner block

    很多语言使用特殊单词或者字符来表示一个语句块的开始,用另外的单词或者字符表示语句块的结束.在python中,冒号用来标识语句块的开始,块中的每一个语句都是缩进的.当回退到和已经闭合的块一样的缩进量时,就表示当前块已经结束了.


    5.4 条件和条件语句


    5.4.1 这就是布尔变量的作用

    标准值False和None 所有类型的数字0 空序列以及空的字典都为假.其他的一切都被解释为真,包括特殊值True.

    也就是说python中的所有值都能被解释为真值,初次接触的时候可能会有些搞不明白,但是这点的确非常有用.标准的真值为True和False.在一些语言中,标准的真值为0和1.事实上,true和false只不过是1和0的一种华丽的说法而已.

    >>> true

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    NameError: name 'true' is not defined

    >>> True

    True

    >>> False

    False

    >>> True == 1

    True

    >>> False == 0

    True

    >>> True + False + 43

    44

    >>>

    那么,如果某个逻辑表达式返回1或0,那么它实际的意思是返回True或False

    布尔值True和False属于布尔类型,bool函数可以用来 ( 和list str以及tuple一样 )转换其他值

    >>> bool('I think,therefore I am')

    True

    >>> bool(42)

    True

    >>> bool('')

    False

    >>> bool(0)

    False

    >>>


    下面的值在作为布尔表达式的时候,会被解释器看作假(false)

    False None 0 “” () [] {} 


    因为所有值都可以作为布尔值,所以几乎不需要对它们进行显示转换.

    尽管[]和""都是假值( 也就是说bool([])==bool("")==False ),它们本身却并不相等 ( 也就是说[]!=""),对于其他不同类型的假值对象也是如此( 假如()!=False )



    5.4.2 条件执行和if 语句

    真值可以联合使用,但还是让我们先看看它们的作用。试着运行下面的脚本:

    #!/usr/bin/env python

    name = raw_input('What is your name?')

    if name.endswith('Gumby'):

            print 'Hello,Mr.Gumby'



    [root@pankuo ~]# ./python.py

    What is your name?a

    [root@pankuo ~]# ./python.py

    What is your name?Gumby

    Hello,Mr.Gumby


    这就是if语句,它可以实现条件执行。即如果条件(在if和冒号之间的表达式)判定为真,那么后面的语句块(本例中是单个print语句)机会被执行。如果条件为假,语句块就不会被执行。


    5.4.3 else子句

    前一节的例子中,如果用户输入了以"Gumby" 作为结尾的名字,那么name.endswith方法就会返回真,使得if进入语句块,打印出问候语。也可以用else子句增加一种选择之所以叫做子句是因为它不是独立的语句,而只能作为if语句的一部分。

    #!/usr/bin/env python

    name = raw_input('What is your name?')

    if name.endswith('Gumby'):

            print 'Hello,Mr.Gumby'

    else:

            print 'Hello. stranger'



    [root@pankuo ~]# ./python.py

    What is your name?a

    Hello. stranger


    如果第一个语句块没有被执行,那么就会转入第二个语句块,可以看到。


    5.4.4 elif子句

    如果需要检查多个条件,就可以使用slif,它是"elif if" 的简写,也就是if和else子句的联合使用-----也就是具有条件的else子句。

    #!/usr/bin/env python

    num = input('Enter a number:')

    if num > 0 :

            print 'The number is positive'

    elif num < 0:

            print 'The number is negative'

    else:

            print 'The number is zer0'



    [root@pankuo ~]# ./python.py

    Enter a number:5

    The number is positive

    [root@pankuo ~]# ./python.py

    Enter a number:0

    The number is zer0

    可以使用int(raw_input(...))函数来代替input(...)。


    5.4.5 嵌套代码块

    name=raw_input('what is your name?')

    if name.endswith('Gumby'):

    if name.startswith('Mr.'):

    print 'hello,Mr.Gumby'

    elif name.startswith('Mrs.'):

    print 'hello.Mrs.Gumby'

    else:

    print 'hello.Gumby'

    else:

    print 'hello.stranger'

    如果名字以Gumby结尾的话,还要检查名字的开头


    5.4.6 更复杂的条件

    1.比较运算符

    x==y

    x〈y

    x is y

    x is not y

    x in y   x是y容器(例如:序列)的成员

    x not in y    x不是y容器(例如:序列)的成员

    0<age<100


    2.相等运算符

    如果想知道两个东西是否相等

    〉〉〉“foo”==“foo”

    True

    〉〉〉“foo”==“bar”

    False


    3.is : 同一性运算符

    >>>x=y=[1,2,3]

    >>>z=[1,2,3]

    >>>x==y

    True

    >>>x==z

    True

    >>>x is y

    True

    >>>x is z

    False


    == 检测相等  is判断两者是否等同  is运算符是判定同一性而不是相等性


    >>>x=[1,2,3]

    >>>y=[2,4]

    >>>x is not y

    True

    >>>del x[2]

    >>>y[1]=1

    >>>y.reverse()

    尽量避免将is运算符用于比较类似数值和字符串这类不可变值。


    4.in:成员资格运算符

    #!/usr/bin/env python

    name=raw_input('what is your name?')

    if 's' in name:

    print 'your name contains the letter "s".'

    else:

    print 'your name does not contain the letter "s".'


    5.字符串和序列比较

    字符串可以按照字母顺序排列进行比较。

    >>> "alpha" < "beta"

    True

    >>> "a" < "b"

    True

    >>> "b" < "a"

    False

    >>> 


    如果字符串内包括大写字母,那么结果就会有点乱。可以转换大小写在比较

    >>> 'FnOrD'.lower() == 'Fnord'.lower()

    True

    >>> 


    其他的序列也可以同样的方式进行比较,不过比较的不是字符而是元素的其他类型。

    >>> [1,2]<[2,1]

    True

    >>> 


    如果一个序列中包括其他序列元素,比较规则也同样适用于序列元素。

    >>> [2,[1,4]]<[2,[1,5]]

    True

    >>> 


    6.布尔运算符

    例如 如果需要编写读取数字并且判断该数字是否位于1~10之间的程序,可以像下面这样做:

    #!/usr/bin/env python

    number=input('Enter a number between 1 and 10: ')

    if number <= 10:

            if number >=1:

                    print 'Great!'

            else:

                    print 'wrong!'

    else:

            print 'Wrong'


    或者

    #!/usr/bin/env python

    number=input('Enter a number between 1 and 10: ')

    if number <= 10 and number >=1:

            print 'Great!'

    else:

            print 'Wrong!'


    and运算符就是所谓的布尔运算符。它连接两个布尔值,并且在两者都为真时返回真,否则返回假。与它同样的还有两个运算符,or和not。使用这3个运算符就可以随意结合其值。

    if ((cash > price) or customer_has_good_credit) and not out_of_stock:

    give_goods()


    表达式x and y需要两个变量都为真时才为真,所以如果x为假,表达式就会立刻返回false,而不管y的值。实际上,如果x为假,表达式会返回x的值------否则它就返回y的值。 这种行为被称为短路逻辑或惰性求值:布尔运算符通常被称为逻辑运算符,就像你看到的那样第2个值时“被短路了”。这种行为对于or来说也同样适用。在表达式x or y中,x为真时,它直接返回x值,否则返回y值。它主要是避免了无用地执行代码,可以作为一种技巧使用,假设用户应该输入他/她的名字,但也可以选择什么都不输入,这时可以使用默认值'<unknown>'.可以使用if语句,但是可以很简洁的方式:

    name=raw_input('Please enter your name: ') or '<unknown>'

    换句话说,如果raw_input语句的返回值为真,那么它的值就会赋给name,否则将默认的'<unknown>'赋值给name


    a if b else c 如果b为真,返回a,否则,返回c


    5.4.7 断言

    与其让程序晚些时候崩溃,不如在错误条件出现时直接让它崩溃 。一般说来,你可以要求某些条件必须为真。语句中使用的关键字assert。

    >>> age=10

    >>> assert 0 < age < 100

    >>> age = -1

    >>> assert 0 < age < 100

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    AssertionError

    >>> 


    如果需要确保程序中的某个条件一定为真才能让程序正常工作的话,assert语句就有用了,它可以在程序中置入检查点。

    条件后可以添加字符串,用来解释断言:

    >>> age = -1

    >>> assert 0 < age < 100,'The age must be realistic'

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    AssertionError: The age must be realistic

    >>> 


    5.5 循环

    5.5.1 while循环

    x = 1

    while x<=100:

    print x

    x += 1

     那么python里面应该如何呢?

    name =  ''

    while not name:

    name=raw_input('Please enter your name:')

    print 'Hello,%s!' % name    替换name


    [root@pankuo ~]# python p.py 

    Please enter your name:

    Please enter your name:

    Please enter your name:

    Please enter your name:

    Please enter your name:hah

    Hello,hah!

    运行这个程序看看,然后再程序要求输入名字时按下回车键。程序会再次要求输入名字,因为name还是空字符串,其求值结果为false。


    如果直接输入一个空格作为名字又会如何?试试看。程序会接受这个名字,因为包括一个空格的字符串并不是空的,所以不会判定为假。小程序因此出现了瑕疵,修改起来也很简单:只需要把while not name改为while not name or name.isspace()即可,或者可以使用while not name.strip()。


    5.5.2 for循环

    while语句非常灵活。它可以用来在任何条件为真的情况下重复执行一个代码块。一般情况下这样就够用了,但是有些时候还得量体裁衣。比如要为一个集合(序列和其他可迭代对象)的每个元素都执行一个代码块。

    可迭代对象是指可以按次序迭代的对象。


    #!/usr/bin/env python

    words = ['this','is','ex','parrot']

    for word in words:

            print word


    [root@pankuo ~]# python p.py 

    this

    is

    ex

    parrot


    因为迭代某范围的数字是很常见的,所以有个内建的范围函数供使用:

    >>> range(0,10)

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    >>> 


    range函数的工作方式类似于分片。它包含下限,但不包含上限

    >>> range(11)

    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    >>> 

    下面的程序会打印1~100的数字

    for number in range(1,101):

    print number

    它比之前的while循环更简洁。


    如果能使用for循环,就尽量不用while循环。

    xrange函数的循环行为类似于range函数,区别在于range函数一次创建整个序列,而xrange一次只创建一个数。当需要迭代一个巨大的序列时xrange会更高效,不过一般情况下不需要过多关注它。


    5.5.3 循环遍历字典元素

    一个简单的for语句就能循环字典的所有键,就像处理序列一样:

    #!/usr/bin/env python

    d = {'x':1,'y':2,'z':3}

    for key in d:

            print key,'corresponds to',d[key]


    [root@pankuo ~]# python p.py 

    y corresponds to 2

    x corresponds to 1

    z corresponds to 3


    在python 2.2 之前,还只能用keys等字典方法来获取键。如果只需要值,可以使用d.values替代d.keys。d.items 方法会将键-值对作为元组返回,for循环的一大好处就是可以循环中使用序列解包:


    for key,value in d.items():

    print key,'corresponds to',value

    字典元素的顺序通常是没有定义的,换句话说,迭代的时候,字典中的键和值都能保证被处理,但是处理顺序不确定。如果顺序很重要的话,可以将键值保存在单独的列表中,例如在迭代前进行排序。


    5.5.4 一些迭代工具

    1.并行迭代

    程序可以同时迭代两个序列。比如有下面两个列表

    names = ['anne','beth','george','damon']

    ages = [12,45,32,102]

    如果想要打印名字和对应的年龄,可以像下面这样做:

    for i in range(len(names)):

    print names[i],'is',ages[i],'years old'

    这里i是循环索引的标准变量名。

    而内建的zip函数可以用来进行并行迭代,可以把两个序列“压缩”在一起,然后返回一个元组的列表:

    >>> zip(names,ages)

    [('anne', 12), ('beth', 45), ('george', 32), ('damon', 102)]

    现在我可以在循环中解包元组:

    for name,age in zip(names,ages):

    print name,'is ',age,'years old'

    zip函数也可以作用于任意多的序列。关于它很重要的一点是zip可以应付不等长的序列:当最短的序列“用完”的时候就会停止:

    >>> zip(range(5),xrange(6))

    [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

    >>> zip(range(5),xrange(2))

    [(0, 0), (1, 1)]

    >>> zip(range(5),xrange(5))

    [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]

    >>> 


    range会计算所有的数字,这要花费很长的时间。而使用xrange就没这个问题,它只计算前5个数字。


    2.编号迭代

    有些时候想要迭代序列中的对象,同时还要获取当前对象的索引。例如,在一个字符串列表中替换所有包含‘xxx’的子字符串。实现的方法肯定有很多,假设你想象下面这样做:

    index = 0

    for string in strings:

    if ‘xxx’ in strings

    strings[index] = ‘[censored]’

    index +=1

    方法有些笨,不过可以接受。另一种方法是使用内建的enumerate函数:

    for index,string in enumerate(strings):

    if 'xxx' in string:

    strings[index] = 'censored'

    这个函数可以提供索引的地方迭代索引-值对


    3.翻转和排序迭代 

    让我们看看另外两个有用的函数:reversed和sorted:它们同列表的reverse和sort方法类似,但作用于任何序列或可迭代对象上,不是原地修改对象,而是返回翻转或排序后的版本:

    >>> sorted([3,3,4,6,8])

    [3, 3, 4, 6, 8]

    >>> sorted ('hello,world!')

    ['!', ',', 'd', 'e', 'h', 'l', 'l', 'l', 'o', 'o', 'r', 'w']

    >>> list(reversed('hello,world!'))

    ['!', 'd', 'l', 'r', 'o', 'w', ',', 'o', 'l', 'l', 'e', 'h']

    >>> ''.join(reversed('hello,world!'))

    '!dlrow,olleh'

    >>> 


    注意,虽然sorted方法返回列表,reversed方法却返回一个更加不可思议的可迭代对象。它们具体的含义不用过多关注,大可在for循环以及join方法中使用,而不会有任何问题。不过却不能直接对它使用索引、分片以及调用list方法,如果希望进行上述处理,那么可以使用list类型转换返回的对象。



    5.5.5 跳出循环

    一般来说,循环会一直执行到条件为假,或者到序列元素用完时。但是有些时候可能会提前中断一个循环,进行新的迭代,或者仅仅就是想结束循环。

    1.break

    结束循环可以使用break语句。假设需要寻找100以内的最大平方数,那么程序可以开始从100往下迭代到0.当找到一个平方数时就不需要继续循环了,所以可以跳出循环:

    from math import sqrt

    for n in range(99,0,-1):

    root = sqrt(n)

    if root == int(root):

    print n

    break

    如果执行这个程序的话,会打印出81,然后程序停止。注意,上面代码中range函数增加了第3个参数---表示步长,步长表示每对相邻数字之间的差别。将其设置为负值的话就会像例子中一样反向迭代。它也可以用来跳过数字:

    >>> range(0,10,2)

    [0, 2, 4, 6, 8]

    >>> 


    2.continue

    continue语句比break语句用得要少得多,它会让当前的迭代结束,“跳”到下一轮循环的开始。它最基本的意思是”跳过剩余的循环体“,但是不结束循环。当循环体很大而且很复杂的时候,就会很有用,有些时候因为一些原因可能会跳过它----这个时候可以使用continue语句:

    for x in seq:

    if condition1: continue

    if condition2: continue

    if condition3: continue

    do_something()

    do_something_else()

    do_anohten_thing()

    etc()

    很多时候,只要使用if语句就可以了:

    for x in seq:

    if not (condition1 or condition2 or condition3):

    do_something()

    do_something_else()

    do_another_thing()

    etc()

    尽管continue语句非常有用,它却不是最本质的。应该习惯使用break语句,因为在while True语句中会经常用到它。


    3.while True/break习语

    python 中的while和for循环非常灵活,但一旦使用while语句就会遇到一个需要更多功能的问题。如果需要当用户在提示符下输入单词时做一些事情,并且在用户不输入单词后结束循环。

    word='dummy'      哑值

    while word:

    word = raw_input('Please enter a word:')

    #处理word:

    print 'The word was' + word


    [root@pankuo ~]# python p.py 

    Please enter a word:1

    the word was 1

    Please enter a word:2

    the word was 2

    Please enter a word:3

    the word was 3


    处理哑值

    #!/usr/bin/env python

    word = raw_input('Please enter a words:')

    while word:

            print 'the word was ' + word

            word = raw_input('Please enter a words:')

    减少重复代码

    #!/usr/bin/env python

    while True:

            word = raw_input('Please enter a words:')

            if not word: break

            print 'the word was ' + word


    while True的部分实现了一个永远不会自己停止的循环。但是在循环内部的if语句中加入条件可以的,在条件满足时调用break语句。这样以来就可以在循环内部任何地方而不是只在开头终止循环。if/break语句自然地将循环分为两部分:第一部分负责初始化,第2部分则在循环条件为真的情况下使用第1部分内初始化好的数据。

    尽管应该小心再代码中频繁使用break语句,但这个特殊的技术用得非常普遍,大多数python程序员都能理解你的意思。


    5.5.6 循环中德else子句

    当在循环内使用break语句时,通常是因为”找到了“某物或者因为某事”发生“了。跳出时做一些事情是很简单的,但是有些时候想要在没有跳出之前做些事情。那么怎么判断呢?可以使用布尔变量,在循环前将其设定为False,跳出后设定为True。然后再使用if语句查看循环是否跳出了:

    broke_out = False

    for x in seq:

    do_something(x)

    if condition(x)

    broke_out = True

    break

    do_something_else(x)

    if not broke_out:

    print "I didn't break out!"

    更简单的方式是在循环中增加一个else子句----它仅在没有调用break时执行。让我们用这个方法重写刚才的例子:

    from math import sqrt

    for n in range(99,55,-1)

    root=sqrt(n)

    if root == int(root):

    print n

    break

    else:

    print "Didn't find it!"


    [root@pankuo ~]# python p.py 

    81

    100以内的最大平方数81


    5.6 列表推导式------轻量级循环

    列表推导式是利用其他列表创建新列表(类似于数学术语中的集合推导式)的一种方法。它的工作方式类似于for循环,也很简单:

    >>> [x*x for x in range(10)]

    [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

    列表由range(10)中每个x的平方组成。如果只想打印出那些能被3整除的平方数,那么可以使用模除运算符-----y%3,当数字可以被3整除时返回0(注意,x能被3整除时x的平方必然能被3整除)。这个语句可以通过增加一个if部分添加到列表推导式中:

    >>> [x*x for x in range(10) if x % 3 == 0]

    [0, 9, 36, 81]

    >>> 


    也可以增加更多for语句的部分:

    >>> [(x,y) for x in range(3) for y in range(3)]

    [(0, 0), (0, 1), (0, 2), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2)]


    result = []

    for x in range(3):

    for y in range(3)

    result.append((x,y))

    也可以和if子句联合使用,像以前一样:

    >>> girls = ['alice','bernice','clarice']

    >>> boys = ['chris','arnold','bob']

    >>> [b+'+'+g for b in boys for g in girls if b[0] == g[0]]

    ['chris+clarice', 'arnold+alice', 'bob+bernice']


    使用普通的圆括号而不是方括号不会得到‘元组推导式’

    girls = ['alice','bernice','clarice']

    boys = ['chris','arnold','bob']

    letterGirls = {}

    for girl in girls:

    letterGirls.setdefault(girl[0],[]).append(girl)

    print [b+'+'+g for b in boys for g in letterGirls[b[0]]]


    更有方案

    [root@pankuo ~]# python p.py 

    ['chris+clarice', 'arnold+alice', 'bob+bernice']



    5.7 三人行

    5.7.1 什么都没发生

    >>> pass

    >>> 

    可以在代码中作为占位符使用。比如程序需要一个if语句,然后进行测试,但是缺少其中一个语句块的代码

    if name == ‘Ralph Auldus Melish':

    print 'Welcome!'

    elif name == 'Enid':

    #还没完

    elif name == 'Bill Gates'

    print 'Access Denied'

    代码不会执行,因为不合法

    但是如果这样  就可以

    if name == ‘Ralph Auldus Melish':

    print 'Welcome!'

    elif name == 'Enid':

    #还没完

    pass

    elif name == 'Bill Gates'

    print 'Access Denied'


    5.7.2 使用del删除

    一般来说,python会删除那些不再使用的对象:

    >>> scoundrel = {'age':42,'first name':'Robin','last name':'of Locksley'}

    >>> robin = scoundrel

    >>> scoundrel

    {'last name': 'of Locksley', 'first name': 'Robin', 'age': 42}

    >>> robin

    {'last name': 'of Locksley', 'first name': 'Robin', 'age': 42}

    >>> scoundrel = None

    >>> robin

    {'last name': 'of Locksley', 'first name': 'Robin', 'age': 42}

    >>> robin = None

    >>> robin

    >>> scoundrel

    >>> 

    首先,robin和scoundrel都被绑定到同一个字典上,所以当设置scoundrel为None的时候,字典通过robin还是可用的。但是当我把robin也设置为None的时候,字典就’漂‘在内存里面了,没有任何名字绑定到它上面。没有办法获取和使用它,所以python解释器直接删除了那个字典(这种行为被称为垃圾收集)。注意,也可以使用None之外的其他值。字典同样会"消失不见"。

    另外一个方法就是使用del。它不仅会移除一个对象的引用,也会移除那个名字本身

    >>> x=1

    >>> del x

    >>> x

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    NameError: name 'x' is not defined

    >>> 


    x和y都指向同一个列表。但是删除x并不会影响y。原因就是删除的只是名称,而不是列表本身。事实上,在python中是没有办法删除值的(也不需要过多考虑删除值得问题,因为在某个值不再使用的时候,python解释器会负责内存的回收)

    >>> x = ["hello","world"]

    >>> y=x

    >>> y[1]="Python"

    >>> x

    ['hello', 'Python']

    >>> del x

    >>> y

    ['hello', 'Python']

    >>> 


    5.7.3 使用exec和eval执行和求值字符串

    有些时候可能会需要动态地创造python代码,然后将其作为语句执行或作为表达式计算,这可能近似于”黑暗魔法“-------慎用


    学到如何执行存储在字符串中的python代码。这样做会有很严重的潜在安全漏洞。如果程序将用户提供的一段内容的一部分字符串作为代码执行,程序可能会失去对代码执行的控制,这种情况在网络应用程序----比如CGI脚本尤其危险。

    1.exec

    执行一个字符串的语句是exec:

    >>> exec "print 'hellp,world!'"

    hellp,world!

    >>> 

    但是,使用简单形式的exec语句绝不是好事。很多情况下可以给它提供命名空间----可以放置变量的地方。

    >>> from math import sqrt

    >>> exec "sqrt = 1"

    >>> sqrt(4)

    Traceback (most recent call last):

      File "<stdin>", line 1, in <module>

    TypeError: 'int' object is not callable

    >>> 

    exec语句最有用的地方在于可以动态地创建代码字符串。如果字符串是从其他地方获得的---很有可能是用户---那么几乎不能确定其中到底包含什么代码。所以为了安全起见,可以增加一个字典,起到命名空间的作用


    命名空间的概念,或成为作用域,是非常重要的知识。


    可以通过增加in<scope>来实现,其中的<scope>就是起到放置代码字符串命名空间作用的字典。

    >>> from math import sqrt

    >>> scope={}

    >>> exec 'sqrt = 1' in scope

    >>> sqrt(4)

    2.0

    >>> scope['sqrt']

    1

    >>> 

    可以看到潜在的破坏性代码并不会覆盖sqrt函数,原来的函数能正常工作,而通过exec赋值的变量sqrt只在它的作用域内有效。

    注意,如果需要将scope打印出来的话,会看到其中包含很多东西,因为内建的_builtins_字典自动包含所有的内建函数和值:

    >>> len(scope)

    2

    >>> scope.keys()

    ['__builtins__', 'sqrt']

    >>> 



    2.eval

    eval用于’求值‘是类似于exec的内建函数。exec语句会执行一些列python语句,而eval会计算python表达式,并且返回结果值,例如,可以使用下面的代码创建一个python计算器:

    >>> eval(raw_input("Enter an arithmetic expression:"))

    Enter an arithmetic expression:6+1*3

    9

    >>> 


    表达式eval(raw_input(。。。))事实上等同于input(。。。)

    跟exec一样,eval也可以使用命名空间。尽管表达式几乎不像语句那样为变量重新赋值。


    尽管表达式一般不给变量重新赋值,但它们的确可以。所以使用eval语句对付一些不可信任的代码并不比exec更安全。

    >>> scope={}

    >>> scope['x']=2

    >>> scope['y']=3

    >>> eval('x*y',scope)

    6

    >>> 


    exec或者eval调用的作用域也能在另外一个上面使用:

    >>> scope = {}

    >>> exec 'x=2' in scope

    >>> eval ('x*x',scope)

    4

    >>> 


关键字

上一篇: python模块requests的安装

下一篇: Python 简介