**
Python入门教程**
python是高级语言,跨平台的编程语言。不适合贴近硬件的代码(首选C)、移动开发、游戏开发(首选C和C++)。
python的代码很少,但不需要编译,运行速度慢。
python源码不能加密。
python2.7版和3.3版不兼容。目前部分第三方库还不能再3.3版上运行
NotePad ++
python对缩进要求非常严格,文件开头不能有空格。
Python的注释以#开头,后面的文字直到行尾都算注释。
在Python中,等号=是赋值语句,可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量。这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。和静态语言相比,动态语言更灵活。
如果一个字符串包含很多需要转义的字符,对每一个字符都进行转义会很麻烦。为了避免这种情况,我们可以在字符串前面加个前缀 r ,表示这是一个 raw 字符串,里面的字符就不需要转义了。但是r'...'表示法不能表示多行字符串,也不能表示包含'和 "的字符串。如果要表示多行字符串,可以用'''...'''表示。还可以在多行字符串前面添加 r ,把这个多行字符串也变成一个raw字符串。如果要表示中文,显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突,所以,中国制定了GB2312编码,用来把中文编进去。为了统一所有文字的编码,Unicode应运而生。Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode通常用两个字节表示一个字符,原有的英文编码从单字节变成双字节,只需要把高字节全部填为0就可以。因为Python的诞生比Unicode标准发布的时间还要早,所以最早的Python只支持ASCII编码,普通的字符串'ABC'在Python内部都是ASCII编码的。Python在后来添加了对Unicode的支持,以Unicode表示的字符串用u'...'表示。不加u,中文就不能正常显示。Unicode字符串除了多了一个u之外,与普通字符串没啥区别,转义字符和多行表示法仍然有效。
如果中文字符串在Python环境下遇到 UnicodeDecodeError,这是因为.py文件保存的格式有问题。可以在第一行添加注释
-- coding: utf-8 --目的是告诉Python解释器,用UTF-8编码读取源代码。然后用Notepad++另存为... 并选择UTF-8格式保存。
Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。list是数学意义上的有序集合,也就是说,list中的元素是按照顺序排列的。由于Python是动态语言,所以list中包含的元素并不要求都必须是同一种数据类型。一个元素也没有的list,就是空list。通过索引来获取list中的指定元素,使用索引时,千万注意不要越界。可以用 -1 这个索引来表示最后一个元素,倒数第二用 -2 表示,倒数第三用 -3 表示,倒数第四用 -4 表示。
list添加新元素,第一个办法是用 list 的 append() 方法,把新元素追加到 list 的末尾;第二种方法用list的 insert()方法,它接受两个参数,第一个参数是索引号,第二个参数是待添加的新元素,可以追加到list中的任意位置。同时,可以用pop()方法剔除list中的任意位置的元素,默认无参数剔除最后一个元素,函数返回并自动打印输出被剔除的元素。对list中的某一个索引赋值,就可以直接用新的元素替换掉原来的元素,list包含的元素个数保持不变。
tuple是另一种有序的列表,中文翻译为“ 元组 ”。tuple 和 list 非常类似,但是,tuple一旦创建完毕,就不能修改了。创建tuple和创建list唯一不同之处是用( )替代了[ ]。tuple没有 append()方法,也没有insert()和pop()方法。获取 tuple 元素的方式和 list 是一模一样的,我们可以正常使用 t[0],t[-1]等索引方式访问元素,但是不能赋值成别的元素。tuple和list一样,可以包含 0 个、1个和任意多个元素。包含 0 个元素的 tuple,也就是空tuple,直接用 ()表示。正是因为用()定义单元素的tuple有歧义,所以 Python 规定,单元素 tuple 要多加一个逗号“,”,这样就避免了歧义。多元素 tuple 加不加这个额外的“,”效果是一样的。
若tuple中的元素包含list元素,则该list元素的内容是可以修改的。即tuple是指向不变,不是绝对的内容不变。
Python代码的缩进规则。具有相同缩进的代码被视为代码块。缩进请严格按照Python的习惯写法:4个空格,不要使用Tab,更不要混合Tab和空格,否则很容易造成因为缩进引起的语法错误。
if 语句后接表达式,然后用:表示代码块开始。如果你在Python交互环境下敲代码,还要特别留意缩进,并且退出缩进需要多敲一行回车:。
利用 if ... else ... 语句,我们可以根据条件表达式的值为 True 或者 False ,分别执行 if 代码块或者 else 代码块。注意: else 后面有个“:”。
多个判断条件还可以用 if-elif-else语句,elif 意思就是 else if。
python中的for循环:for name in list/tuple,name是在for循环中定义的变量,可以依次取出list或tuple中的元素,并将其值赋给name。
while循环与C++类似。
循环中break和continue的用法与C++类似。
Python之什么是dict:查找表。花括号 {} 表示这是一个dict,然后按照 key: value, 写出来即可。最后一个 key: value 的逗号可以省略。由于dict也是集合,len() 函数可以计算任意集合的大小。 通过 key 访问 dict 的value,只要 key 存在,dict就返回对应的value。如果key不存在,会直接报错。dict本身同时还提供了一个get方法,可以通过key查找对应的value。
dict的第一个特点是查找速度快,无论dict有10个元素还是10万个元素,查找速度都一样。而list的查找速度随着元素增加而逐渐下降。不过dict的查找速度快不是没有代价的,dict的缺点是占用内存大,还会浪费很多内容,list正好相反,占用内存小,但是查找速度慢。由于dict是按 key 查找,所以,在一个dict中,key不能重复。dict的第二个特点就是存储的key-value序对是没有顺序的!这和list不一样。当我们试图打印这个dict时,打印的顺序不一定是我们创建时的顺序,而且,不同的机器打印的顺序都可能不同,这说明dict内部是无序的,不能用dict存储有序的集合。dict的第三个特点是作为 key 的元素必须不可变,Python的基本类型如字符串、整数、浮点数都是不可变的,都可以作为 key。但是list是可变的,就不能作为 key。不可变这个限制仅作用于key,value是否可变无所谓。最常用的key还是字符串,因为用起来最方便。
dict是可变的,也就是说,我们可以随时往dict中添加新的 key-value。用赋值语句即可,如果 key 已经存在,则赋值会用新的 value 替换掉原来的 value。
由于dict也是一个集合,所以,遍历dict和遍历list类似,都可以通过 for 循环实现。直接使用for循环可以遍历 dict 的 key。由于通过 key 可以获取对应的 value,因此,在循环体内,可以获取到value的值。
dict的作用是建立一组 key 和一组 value 的映射关系,dict的key是不能重复的。有的时候,我们只想要 dict 的 key,不关心 key 对应的 value,目的就是保证这个集合的元素不会重复,这时,set就派上用场了。set 持有一系列元素,这一点和 list 很像,但是set的元素没有重复,而且是无序的,这点和 dict 的 key很像。创建 set 的方式是调用 set() 并传入一个 list,list的元素将作为set的元素。set内部存储的元素是无序的。因为set不能包含重复的元素,所以,当我们传入包含重复元素的 list,set会自动去掉重复的元素。
由于set存储的是无序集合,所以我们没法通过索引来访问。访问 set中的某个元素实际上就是判断一个元素是否在set中。可以用 in 操作符判断。大小写很重要,'Bart' 和 'bart'被认为是两个不同的元素。
set的内部结构和dict很像,唯一区别是不存储value,因此,判断一个元素是否在set中速度很快。set存储的元素和dict的key类似,必须是不变对象,因此,任何可变对象是不能放入set中的。最后,set存储的元素也是没有顺序的。
由于 set 也是一个集合,所以,遍历 set 和遍历 list 类似,都可以通过 for 循环实现。 for 循环在遍历set时,元素的顺序和list的顺序很可能是不同的,而且不同的机器上运行的结果也可能不同。
由于set存储的是一组不重复的无序元素,因此,更新set主要做两件事:一是把新的元素添加到set中,二是把已有元素从set中删除。添加元素时,用set的add()方法。如果添加的元素已经存在于set中,add()不会报错,但是不会加进去了。删除set中的元素时,用set的remove()方法。如果删除的元素不存在set中,remove()会报错。所以用add()可以直接添加,而remove()前需要判断。
函数就是最基本的一种代码抽象的方式。Python不但能非常灵活地定义函数,而且本身内置了很多有用的函数,可以直接调用。可以直接从Python的官方网站查看文档:http://docs.python.org/2/library/functions.html#abs,也可以在交互式命令行通过 help() 查看函数的帮助信息。
如果传入的参数数量不对,会报TypeError的错误。如果传入的参数数量是对的,但参数类型不能被函数所接受,也会报TypeError的错误,并且给出错误信息。Python内置的常用函数还包括数据类型转换函数。
在Python中,定义一个函数要使用 def 语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,函数的返回值用 return 语句返回。函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。如果没有return语句,函数执行完毕后也会返回结果,只是结果为 None。return None可以简写为return。
函数可以返回多个值吗?答案是肯定的。在语法上,返回一个tuple可以省略括号,而多个变量可以同时接收一个tuple,按位置赋给对应的值,所以,Python的函数返回多值其实就是返回一个tuple,但写起来更方便。
在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。递归函数的优点是定义简单,逻辑清晰。理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。使用递归函数需要注意防止栈溢出。在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出。
定义函数的时候,还可以有默认参数。函数的默认参数的作用是简化调用,你只需要把必须的参数传进去。但是在需要的时候,又可以传入额外的参数来覆盖默认参数值。由于函数的参数按从左到右的顺序匹配,所以默认参数只能定义在必需参数的后面。
如果想让一个函数能接受任意个参数,我们就可以定义一个可变参数。可变参数的名字前面有个 * 号,我们可以传入0个、1个或多个参数给可变参数。可变参数也不是很神秘,Python解释器会把传入的一组参数组装成一个tuple传递给可变参数,因此,在函数内部,直接把变量 args 看成一个 tuple 就好了。
取一个list的部分元素是非常常见的操作。Python提供了切片(Slice)操作符,能大大简化这种操作。取前3个元素,用一行代码就可以完成切片:L[0:3]。L[0:3]表示,从索引0开始取,直到索引3为止,但不包括索引3。即索引0,1,2,正好是3个元素。如果第一个索引是0,还可以省略: L[:3]。也可以从索引1开始,取出2个元素出来:L[1:3]。只用一个 : ,表示从头到尾:L[:]。因此,L[:]实际上复制出了一个新list。切片操作还可以指定第三个参数:L[::2],第三个参数表示每N个取一个,上面的 L[::2] 会每两个元素取出一个来,也就是隔一个取一个(从第0个元素开始取)。
对于list,既然Python支持L[-1]取倒数第一个元素,那么它同样支持倒数切片。记住倒数第一个元素的索引是-1。倒序切片包含起始索引,不包含结束索引。
把list换成tuple,切片操作完全相同,只是切片的结果也变成了tuple。
range()函数可以创建一个数列:range(1, 101),结果为[1, 2, 3, ..., 100]。
字符串 'xxx'和 Unicode字符串 u'xxx'也可以看成是一种list,每个元素就是一个字符。因此,字符串也可以用切片操作,只是操作结果仍是字符串。在很多编程语言中,针对字符串提供了很多各种截取函数,其实目的就是对字符串切片。Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。
在Python中,如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们成为迭代(Iteration)。在Python中,迭代是通过 for ... in 来完成的,而很多语言比如C或者Java,迭代list是通过下标完成的。可以看出,Python的for循环抽象程度要高于Java的for循环。因为 Python 的 for循环不仅可以用在list或tuple上,还可以作用在其他任何可迭代对象上。因此,迭代操作就是对于一个集合,无论该集合是有序还是无序,我们用 for 循环总是可以依次取出集合的每一个元素。迭代与按下标访问数组最大的不同是,后者是一种具体的迭代实现方式,而前者只关心迭代结果,根本不关心迭代内部是如何实现的。
Python中,迭代永远是取出元素本身,而非元素的索引。对于有序集合,元素确实是有索引的。有的时候,我们确实想在 for 循环中拿到索引,怎么办?方法是使用 enumerate() 函数。使用 enumerate() 函数,我们可以在for循环中同时绑定索引index和元素name。索引迭代不是真的按索引访问,而是由 enumerate() 函数自动把每个元素变成 (index, element) 这样的tuple,再迭代,就同时获得了索引和元素本身。
zip()函数可以把两个 list 变成一个 list:zip([10, 20, 30], ['A', 'B', 'C']),结果为[(10, 'A'), (20, 'B'), (30, 'C')]
我们已经了解了dict对象本身就是可迭代对象,用 for 循环直接迭代 dict,可以每次拿到dict的一个key。如果我们希望迭代 dict 对象的value,应该怎么做?dict 对象有一个 values() 方法,这个方法把dict转换成一个包含所有value的list,这样,我们迭代的就是 dict的每一个 value。如果仔细阅读Python的文档,还可以发现,dict除了values()方法外,还有一个 itervalues() 方法,用 itervalues() 方法替代 values() 方法,迭代效果完全一样。那这两个方法有何不同之处呢?
- values() 方法实际上把一个 dict 转换成了包含 value 的list。
- 但是 itervalues() 方法不会转换,它会在迭代过程中依次从 dict 中取出 value,所以 itervalues() 方法比 values() 方法节省了生成 list 所需的内存。
- 打印 itervalues() 发现它返回一个 <dictionary-valueiterator> 对象,这说明在Python中,for 循环可作用的迭代对象远不止 list,tuple,str,unicode,dict等,任何可迭代对象都可以作用于for循环,而内部如何迭代我们通常并不用关心。
如果一个对象说自己可迭代,那我们就直接用 for 循环去迭代它,可见,迭代是一种抽象的数据操作,它不对迭代对象内部的数据有任何要求。
我们了解了如何迭代 dict 的key和value,那么,在一个 for 循环中,能否同时迭代 key和value?答案是肯定的。dict 对象的 items() 方法把dict对象转换成了包含tuple的list,我们对这个list进行迭代,可以同时获得key和value。和 values() 有一个 itervalues() 类似, items() 也有一个对应的 iteritems(),iteritems() 不把dict转换成list,而是在迭代过程中不断给出 tuple,所以, iteritems() 不占用额外的内存。
列表生成式则可以用一行语句代替循环生成[1x1, 2x2, 3x3, ..., 10x10]list: [x x for x in range(1, 11)],这种写法就是Python特有的列表生成式。利用列表生成式,可以以非常简洁的代码生成 list。写列表生成式时,把要生成的元素 x x 放到前面,后面跟 for 循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
条件过滤:列表生成式的 for 循环后面还可以加上 if 判断。
for循环可以嵌套,因此,在列表生成式中,也可以用多层 for 循环来生成列表。
range(1, 100, 2) 可以生成list [1, 3, 5, 7, 9,...]。
isinstance(x, str) 可以判断变量 x 是否是字符串。