# coding:utf-8

#----------------------------------------  print和import的更多信息  --------------------------------


#使用逗号输出

#打印多个表达式也是可行的,只要将它们用逗号隔开就好:

print 'Age:' , 42           #可以看到,每个参数之间都插入了一个空格符。

#Age: 42

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

name = 'Gumby'

salutation = 'Mr.'

greeting = 'Hello,'

print greeting, salutation, name

#Hello, Mr. Gumby

#注意,如果greeting变量里字符串不带逗号:

greeting = 'Hello'

#那么结果中怎么能得到逗号呢?

print greeting, ',', salutation, name       #这样做是不行的,因为语句会在逗号前加入空格。下面是一种解决方案:

#Hello , Mr. Gumby

print greeting + ',', salutation, name

#Hello, Mr. Gumby

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

print 'Hello,',

print 'world!'

#Hello, world!


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

#从模块导入函数时候,通常可以使用

#import somemodule

#或者

#from somemodule import somefunction

#或者

#from somemodule import somefumction, anotherfunction, yetanotherfunction

#或者

#from somemodule import *

#只有确定自己想要从给定的模块导入所有功能是,才应该使用最后一个版本。

#如果两个模块都有open函数,使用如下方法:

#import somemodule

#module1.open(...)

#module2.open(...)

#但还有另外的选择,可以在语句末尾增加一个as子句,在该子句后给出想要使用的别名。

import math as foobar       #整个模块提供别名

print foobar.sqrt(4)

#2.0

from math import sqrt as foobar     #为函数提供别名

print foobar(4)

#2.0

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

#from module1 import open as open1

#from module2 import open as open2


#------------------------------------------  赋值魔法  -----------------------------------------------------


#序列解包

#将多个值得序列解开,然后放到变量的序列中。

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

print values

#(1, 2, 3)

x, y, z = values

print x

#1

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

key, value = scoundrel.popitem()              #随机删除一对键和值,然后删除的键和值作为元组返回,这个元组赋予key和value变量

print key

#girlfriend

print value

#Marion

print scoundrel

#{'name': 'Robin'}

#所解包的序列中的元素数量必须和放置在赋值符号=左边的变量数量完全一致,否则会报错。

#x, y, z = 1, 2             会报错

#x, y, z = 1, 2, 3, 4       会报错


#链式赋值

#链式赋值是将同一个值赋给多个变量的捷径。

x = y = 1

print x

#1

print y

#1

#效果同上

x = 1

x = y

print x

#1

print y

#1

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

x = 1

y = 1


#增量赋值

#对于*,/,% 等标准运算符都适用

#增量赋值可以让代码更加紧凑和简练,很多情况下会更易读。

x = 2

x += 1

print x

#3

x *= 2

print x

#6

#对于其他数据类型也适用。

fnoed = 'foo'

fnoed += 'bar'

print fnoed

#foobar

fnoed *= 2

print fnoed

#foobarfoobar


#----------------------------------------------  条件和条件语句  --------------------------------------------


#这就是布尔变量的作用

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

#False  None  0  ""  ()  []  {}

#其他一切都被解释为真,包括特殊值True

#标准布尔值为0表示假,1表示真

print True == 1

#True

print False == 0

#True

print True + False + 42

#43


#bool转换成布尔值

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

#True

print bool(42)

#True

print bool('')

#False

print bool(0)

#False


#条件执行和if语句

#如果条件(在if和冒号之间的表达式)判定为真,那么后面的语句块就会被执行。如果条件为假,语句块就不会被执行。

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

#if name.endswith('Gumby'):               #如果语句结尾是Gumby

#    print 'Hello, Mr. Gumby'

#执行结果:

#What is your name? Gumby

#Hello, Mr. Gumby


#else子句

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

#if name.endswith('Gumby'):               #如果语句结尾是Gumby

#    print 'Hello, Mr. Gumby'

#else:

#    print 'Hello, stranger'

#执行结果:

#What is your name? abc

#Hello, stranger


#elif子句

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

#num = input('Enter a number: ')        可以使用int(raw_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 zero'

#执行结果:

#Enter a number: 1

#The number is positive

#Enter a number: -1

#The number is negative

#Enter a number: 0

#The number is zero


#嵌套代码块

#if语句里面可以嵌套使用if语句,就像下面这样:

#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'

#执行结果:

#What is your name? Mr. Gumby

#Hello,Mr. Gumby

#What is your name? Mrs. Gumby

#Hello,Mrs. Gumby

#What is your name? Gumby

#Hello, Gumby

#What is your name? abc

#Hello stranger


#更复杂的条件

#比较运算符

# x == y         x 等于 y

# x < y          x 小于 y

# x > y          x 大于 y

# x >= y         x 大于等于 y

# x <= y         x 小于等于 y

# x != y         x 不等于 y

# x is y         x 和 y 是同一个对象

# x is not y     x 和 y 是不同的对象

# x in y         x 是 y 容器(列如,序列)的成员

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

#注意如果偶然遇见x <> y 这样的表达式,它的意思其实就是x != y 不建议使用<>运算符,应该尽量避免使用它。

#在python中比较运算符和赋值运算符一样可以连接的---几个运算符可以连在一起使用,比如:

#0 < age < 100


#相等运算符

#如果想要知道两个东西是否相等,应该使用相等运算符,即两个等号==

print "foo" == "foo"

#True

print "foo" == "bar"   #为何用双等于,一个等于是变量赋值,所以用双等于

#False


#is:同一性运算符

#判断是否一个对象,如果值相同,并不一定是一个对象

x = y = [1, 2, 3]                #同一个对象

z = [1, 2, 3]                    #值相同,但和x y 不是一个对象

print x == y

#True

print x == z                    #值相同,所以True

#True

print x is y                    #是一个对象

#True

print x is z                    #不是一个对象,所以False

#False

#另外一个例子:

x = [1, 2, 3]

y = [2, 4]

print x is not y

del x[2]

y[1] = 1

y.reverse()         #反向排序

print x

#[1, 2]

print y

#[1, 2]

print x == y

#True

print x is y

#False


#in 成员资格运算符

#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".'

#执行结果:

#What is your name? tom

#Your name does not contain the letter "s".

#What is your name? toms

#Your name contains the letter "s".

#字符串和序列比较

#字符串按照字母顺序排列

print "alpha" < "beta"

#True

#大写的话比较会乱,所以先转换小写再比较

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

#True

#其他序列比较,比较的是序列元素

print [1, 2] < [2, 1]

#True

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

#True


#布尔运算符

#多个条件写法:

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

#if number <= 10:

#    if number >= 1:

#        print 'Great!'

#    else:

#        print 'Wrong!'

#else:

#    print 'Wrong!'

#执行结果:

#Enter a number between 1 and 10: 1

#Great!

#Enter a number between 1 and 10: -1

#Wrong!

#Enter a number between 1 and 10: 11

#Wrong!

#这样写没问题,但方法太笨,简单方法:

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

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

# 还有更简单的表达式 1<=number<=10

#    print 'Great!'

#else:

#    print 'Wrong!'

#执行结果:

#Enter a number between 1 and 10: 1

#Great!

#Enter a number between 1 and 10: -1

#Wrong!

#Enter a number between 1 and 10: 11

#Wrong!

#短路逻辑惰性求值

#表达式x and y需要两个变量为真才为真,所以如果x为假,表达式就会立刻返回false,而不管y的值。

#表达式x or y,x为真时,它直接返回x值(True),否则返回y值(True)

#这有什么用?它主要是避免了无用的执行代码,可以作为一种技巧使用。假设用户应该输入名字,但也可以选择什么都不输入,这时可以用默认值'<unknown>'。可以用if语句但可以用更简洁的方式:

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


# assert

#断言,要求程序代码中某些条件必须为真,否则报错退出,不再继续后续代码执行。用来测试调试程序代码的辅助条件。

age = 10

assert 0 < age < 100            #条件为真,不报错

#age = -1

#assert 0 < age < 100            #不为真,报错

#Traceback (most recent call last):

#  File "Z:/CloudStation/***.py", line 96, in <module>

#    assert 0 < age < 100

#AssertionError

#age = -1

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

#条件后面添加字符串,可以用来注释解释错误信息。

#Traceback (most recent call last):

#  File "Z:/CloudStation/***.py", line 96, in <module>

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

#AssertionError: The age must be realistic


#-------------------------------------------  循环  --------------------------------------------------------


#while循环

x = 1

while x <= 100:         #打印1到100

   print x

   x += 1

#name = ''

#while not name:           #如果输入空格也被接受,防止这种情况,可以修改while not name or name.isspace() 或者 while not name.strip()

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

#print 'Hello, %s!' % name


#for循环

#为一个集合每个元素执行一个代码块,比如序列,迭代对象

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

for word in words:

   print word

#this

#is

#an

#ex

#parrot

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

for number in numbers:

   print number

#0

#1

#2

#3

#4

#5

#6

#7

#8

#9

print range(0,10)           #range函数,下限默认为0,不包含上限

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

print range(10)             #默认下限为0

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

#rang函数一次创建整个序列,xrange一次只创建一个数,当需要一个巨大序列时xrange会更高效

for number in range(1,101):   #打印1到100,它比之前的while更简洁。

   print number

#如果能使用for,就尽量不用while


#循环遍历字典元素

#一个简单的for语句就能遍历字典的所有键,就像遍历访问序列一样

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

for key in d:

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

#y corresponds to 2

#x corresponds to 1

#z corresponds to 3

for key, value in d.items():

   print key, 'corresponds to', value

#y corresponds to 2

#x corresponds to 1

#z corresponds to 3


#一些迭代工具

#并行迭代

#程序可以同时迭代两个序列

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

ages = [12, 45, 32, 102]

#如果想要打印名字和对应的年龄:

for i in range(len(names)):

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

#anne is 12 years old

#beth is 45 years old

#george is 32 years old

#damon is 102 years old

#zip函数并行迭代,可以把两个序列"压缩"在一起,然后返回一个元组的列表

print zip(names, ages)

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

#现在可以在循环中解包元组

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

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

#anne is 12 years old

#beth is 45 years old

#george is 32 years old

#damon is 102 years old

#zip函数也可以作用于任意多的序列,它可以作用不等长的序列,最短的序列用完的时候就会停止。

print zip(range(5),xrange(100000))      #不推荐用range替换xrange,range会计算所有的数字,xrange只计算前5个数字

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


#按索引迭代

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

ages = [12, 45, 32, 102]

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

   if 'anne' in name:                                #找到索引进行替换

       index = names.index(name)

       names[index] = '[censored]'

       print names

#['[censored]', 'beth', 'anne', 'damon']

#['[censored]', 'beth', '[censored]', 'damon']

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

ages = [12, 45, 32, 102]

index = 0

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

   if 'anne' in name:                              #更好的方法

       names[index] = '[censored]'

       print names

   index += 1

#['[censored]', 'beth', 'anne', 'damon']

#['[censored]', 'beth', '[censored]', 'damon']

#enumerate函数,可以在提供索引的地方迭代索引--值对

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

ages = [12, 45, 32, 102]

for index, name in enumerate(names):                #更好的方法

   if 'anne' in name:

       names[index] = '[censored]'

       print names

# ['[censored]', 'beth', 'anne', 'damon']

# ['[censored]', 'beth', '[censored]', 'damon']


#翻转和排序迭代

#reversed和sorted。它同列表的reverse和sort方法类似,但作用于任何序列或可迭代对象上,不是原地修改对象,而是返回翻转或排序后的版本:

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

#[3, 3, 4, 6, 8]

print sorted('Hello, world!')

#[' ', '!', ',', 'H', 'd', 'e', 'l', 'l', 'l', 'o', 'o', 'r', 'w']

print list(reversed('Hello, word!'))

#['!', 'd', 'r', 'o', 'w', ' ', ',', 'o', 'l', 'l', 'e', 'H']

print ''.join(reversed('Hello, world!'))

#!dlrow ,olleH


#跳出循环

#break

#结束(跳出)循环可以使用break语句。

from math import sqrt

for n in range(99, 0, -1):          # -1是步长,负数是反向迭代

   root = sqrt(n)

   if root == int(root):

       print n

       break                       #跳出循环

#81

#continue

#continue意思是跳过剩余的循环体,但是不结束循环。当循环体很大而且很复杂的时候,这会很有用。

#for x in seq:

#   if condition1:continue

#   if condition2:continue

#   if condition2:continue

#   do_something()

#   do_something_else()

#   do_anoter_thing()

#   etc()

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

#for x in seq:

#   if not (condition1 or condition2 or condition3):

#       do_something()

#       do_something_else()

#       do_anoter_thing()

#       etc()

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


#while True/break习语

while True:             #无限循环

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

   if not word: break          #满足条件跳出循环

   # 处理word:

   print 'The word was ' + word

#执行结果:

#Please enter a word: first

#The word was first

#Please enter a word: second

#The word was second

#Please enter a word:


#循环中的else子句

#当循环内使用break语句时,通常是因为“找到”了某物或者因为某事“发生”了。在跳出前做一些事情很简单(比如在break上面加入print n),但是有些时候想要在没有跳出之前做些事情。

from math import sqrt

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

   root = sqrt(n)

   if root == int(root):

       print n

       break

else:

   print "Didn't find it"

#Didn't find it


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

#列表推导式是利用其它列表创建新列表的一种方法。

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

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

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

#[0, 9, 36, 81]

print [(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)]

#效果同上的for语句写法

result = []

for x in range(3):

   for y in range(3):

       result.append((x,y))

print result

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

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

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

print [b+'+'+g for b in boys for g in girls if b[0] == g[0]]    #比较第一位相同字母的方式

#['chris+clarice', 'arnold+alice', 'bob+bernic']

#上面例子效果不高,因为它会检查每个可能的配对。

#下面例子创建了一个叫做letterGirls的字典,其中每一项都把单字母作为键,以女孩名字组成列表作为值。在字典建立后,列表推导式循环整个男孩集合,并且查找那些和当前男孩名字首字母相同的女孩集合。

#这样列表推导式就不用尝试所有的男孩女孩的组合,检查首字母是否匹配。

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

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

letterGirls = {}

for girl in girls:

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

   print letterGirls               #打印出来,查看循环情况

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

#{'a': ['alice']}

#{'a': ['alice'], 'b': ['bernic']}

#{'a': ['alice'], 'c': ['clarice'], 'b': ['bernic']}

#['chris+clarice', 'arnold+alice', 'bob+bernic']


#------------------------------------------ 三人行  -----------------------------------------------------


#pass

#什么都没发生,用于代码没写完,暂时顶替

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

#if name == 'Ralph Auldus Mellish':

#    print 'Welcom!'

#elif name == 'Enid':

   #还没完...

#    pass                    #没想到写什么,但可以pass顶替,要不然程序会报错

#elif name == 'Bill Gates':

#    print 'Access Denied'

#del


#删除变量名字,值如果没有python会自动回收

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

robin = scoundrel

print scoundrel

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

print robin

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

scoundrel = None        #当设置scoundrel为None的时候,字典通过robin还是可用

print scoundrel

#None

print robin

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

robin = None           #当robin也设置为None的时候,字典就漂在内存里面,没有任何名字绑定在它上面,没有任何办法可以获取到它。就会被删除回收。也可以用None之外的其他值。同样会被删除回收。

print robin

#None

#另一种方法是del,它会删除对象引用和名字(但不会删除值)

x = 1

y = x

del x           #x和y指向一个值,删除x变量只是名字,所以y的值还在

print y

#1


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

#执行一个字符串的语句时exec

exec "print 'Hello, world!'"

#exec 需要放入到一个命名空间,但这个空间是用户自己的,并不会影响全局空间

from math import sqrt

scope = {}          #增加scope,起到放置代码字符串命名空间作用的字典

exec 'sqrt = 1' in scope

print sqrt(4)       #没有覆盖sqrt函数

#2.0

print scope['sqrt']     #通过exec赋值的变量sqrt只在它的作用域内有效

#1

#eval

#eval(用于求值)是类似于exec的内建函数。exec语句会执行一系列python语句(不返回值),而eval会计算python表达式(以字符串形式书写),并且返回结果值。

#print eval (raw_input("Enter an arithmetic expression: "))

#Enter an arithmetic expression: 6 + 18 * 2

#42

#跟exec一样,eval也可以使用命名空间

scope = {}

scope['x'] = 2

scope['y'] = 3

print eval('x * y', scope)

#6

scope = {}

exec 'x = 2' in scope

print eval('x * x', scope)

#4


#涉及函数

#chr(n)                                     当传入序号n时,返回n所代表的包含一个字符的字符串,(0 <= n < 256)

#eval(source[, globals[, locals]])          将字符串作为表达式计算,并且返回值

#enumerate(seq)                             产生用于迭代的(索引,值)对

#ord(c)                                     返回单字符字符串的int值

#rang([start,] stop[, step])                创建整数的列表

#reversed(seq)                              产生seq中值的反向版本,用于迭代

#sorted(seq[,cmp][,key][,reverse])          返回seq中值排序后的列表

#xrange([start,]stop[,step])                创造xrange对象用于迭代

#zip(seq1,_seq2...)                         创造用于并行迭代的新序列