python 学习.docx
《python 学习.docx》由会员分享,可在线阅读,更多相关《python 学习.docx(14页珍藏版)》请在冰豆网上搜索。
python学习
一、字符串和编码
1:
Python提供了ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符
2:
以Unicode表示的str通过encode()方法可以编码为指定的bytes,反过来,要把bytes变为str,就需要用decode()方法
3:
len()函数计算的是str的字符数,如果换成bytes,len()函数就计算字节数
4:
由于Python源代码也是一个文本文件,所以,当你的源代码中包含中文的时候,在保存源代码时,就需要务必指定保存为UTF-8编码。
当Python解释器读取源代码时,为了让它按UTF-8编码读取,我们通常在文件开头写上这两行:
#!
/usr/bin/envpython3
#-*-coding:
utf-8-*-
第一行注释是为了告诉Linux/OSX系统,这是一个Python可执行程序,Windows系统会忽略这个注释;第二行注释是为了告诉Python解释器,按照UTF-8编码读取源代码,否则,你在源代码中写的中文输出可能会有乱码
格式化:
%运算符就是用来格式化字符串的。
在字符串内部,%s表示用字符串替换,%d表示用整数替换,有几个%?
占位符,后面就跟几个变量或者值,顺序要对应好。
常见的占位符有:
%d
整数
%f
浮点数
%s
字符串
%x
十六进制整数
二、使用list和tuple
Python内置的一种数据类型是列表:
list。
list是一种有序的集合,可以随时添加和删除其中的元素。
list是一个可变的有序表,所以,可以往list中追加元素到末尾:
>>>classmates.append('Adam')
>>>classmates
['Michael','Bob','Tracy','Adam']
也可以把元素插入到指定的位置,比如索引号为1的位置:
>>>classmates.insert(1,'Jack')
>>>classmates
['Michael','Jack','Bob','Tracy','Adam']
要删除list末尾的元素,用pop()方法:
>>>classmates.pop()
'Adam'
>>>classmates
['Michael','Jack','Bob','Tracy']
要删除指定位置的元素,用pop(i)方法,其中i是索引位置:
>>>classmates.pop
(1)
'Jack'
>>>classmates
['Michael','Bob','Tracy']
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
>>>classmates[1]='Sarah'
>>>classmates
['Michael','Sarah','Tracy']
list里面的元素的数据类型也可以不同,比如:
>>>L=['Apple',123,True]
list元素也可以是另一个list,比如:
>>>s=['python','java',['asp','php'],'scheme']
>>>len(s)
4
要注意s只有4个元素,其中s[2]又是一个list,如果拆开写就更容易理解了:
>>>p=['asp','php']
>>>s=['python','java',p,'scheme']
要拿到'php'可以写p[1]或者s[2][1],因此s可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
>>>L=[]
>>>len(L)
0
使用list和tuple
阅读:
533721
list
Python内置的一种数据类型是列表:
list。
list是一种有序的集合,可以随时添加和删除其中的元素。
比如,列出班里所有同学的名字,就可以用一个list表示:
>>>classmates=['Michael','Bob','Tracy']
>>>classmates
['Michael','Bob','Tracy']
变量classmates就是一个list。
用len()函数可以获得list元素的个数:
>>>len(classmates)
3
用索引来访问list中每一个位置的元素,记得索引是从0开始的:
>>>classmates[0]
'Michael'
>>>classmates[1]
'Bob'
>>>classmates[2]
'Tracy'
>>>classmates[3]
Traceback(mostrecentcalllast):
File"",line1,in
IndexError:
listindexoutofrange
当索引超出了范围时,Python会报一个IndexError错误,所以,要确保索引不要越界,记得最后一个元素的索引是len(classmates)-1。
如果要取最后一个元素,除了计算索引位置外,还可以用-1做索引,直接获取最后一个元素:
>>>classmates[-1]
'Tracy'
以此类推,可以获取倒数第2个、倒数第3个:
>>>classmates[-2]
'Bob'
>>>classmates[-3]
'Michael'
>>>classmates[-4]
Traceback(mostrecentcalllast):
File"",line1,in
IndexError:
listindexoutofrange
当然,倒数第4个就越界了。
list是一个可变的有序表,所以,可以往list中追加元素到末尾:
>>>classmates.append('Adam')
>>>classmates
['Michael','Bob','Tracy','Adam']
也可以把元素插入到指定的位置,比如索引号为1的位置:
>>>classmates.insert(1,'Jack')
>>>classmates
['Michael','Jack','Bob','Tracy','Adam']
要删除list末尾的元素,用pop()方法:
>>>classmates.pop()
'Adam'
>>>classmates
['Michael','Jack','Bob','Tracy']
要删除指定位置的元素,用pop(i)方法,其中i是索引位置:
>>>classmates.pop
(1)
'Jack'
>>>classmates
['Michael','Bob','Tracy']
要把某个元素替换成别的元素,可以直接赋值给对应的索引位置:
>>>classmates[1]='Sarah'
>>>classmates
['Michael','Sarah','Tracy']
list里面的元素的数据类型也可以不同,比如:
>>>L=['Apple',123,True]
list元素也可以是另一个list,比如:
>>>s=['python','java',['asp','php'],'scheme']
>>>len(s)
4
要注意s只有4个元素,其中s[2]又是一个list,如果拆开写就更容易理解了:
>>>p=['asp','php']
>>>s=['python','java',p,'scheme']
要拿到'php'可以写p[1]或者s[2][1],因此s可以看成是一个二维数组,类似的还有三维、四维……数组,不过很少用到。
如果一个list中一个元素也没有,就是一个空的list,它的长度为0:
>>>L=[]
>>>len(L)
0
tuple
另一种有序列表叫元组:
tuple。
tuple和list非常类似,但是tuple一旦初始化就不能修改,比如同样是列出同学的名字:
>>>classmates=('Michael','Bob','Tracy')
现在,classmates这个tuple不能变了,它也没有append(),insert()这样的方法。
其他获取元素的方法和list是一样的,你可以正常地使用classmates[0],classmates[-1],但不能赋值成另外的元素
但是,要定义一个只有1个元素的tuple,如果你这么定义:
>>>t=
(1)
>>>t
1
定义的不是tuple,是1这个数!
这是因为括号()既可以表示tuple,又可以表示数学公式中的小括号,这就产生了歧义,因此,Python规定,这种情况下,按小括号进行计算,计算结果自然是1。
所以,只有1个元素的tuple定义时必须加一个逗号,,来消除歧义:
>>>t=(1,)
>>>t
(1,)
Python在显示只有1个元素的tuple时,也会加一个逗号,,以免你误解成数学计算意义上的括号
条件判断:
Elseif语句应elif表示。
age=3
ifage>=18:
print('adult')
elifage>=6:
print('teenager')
else:
print('kid')
elif是elseif的缩写
input:
birth=input('birth:
')
ifbirth<2000:
print('00前')
else:
print('00后')
输入1982,结果报错:
Traceback(mostrecentcalllast):
File"",line1,in
TypeError:
unorderabletypes:
str()>int()
这是因为input()返回的数据类型是str,str不能直接和整数比较,必须先把str转换成整数。
Python提供了int()函数来完成这件事情:
s=input('birth:
')
birth=int(s)
ifbirth<2000:
print('00前')
else:
print('00后')
再次运行,就可以得到正确地结果。
但是,如果输入abc呢?
又会得到一个错误信息:
小结
Python的函数具有非常灵活的参数形态,既可以实现简单的调用,又可以传入非常复杂的参数。
默认参数一定要用不可变对象,如果是可变对象,程序运行时会有逻辑错误!
要注意定义可变参数和关键字参数的语法:
*args是可变参数,args接收的是一个tuple;
**kw是关键字参数,kw接收的是一个dict。
以及调用函数时如何传入可变参数和关键字参数的语法:
可变参数既可以直接传入:
func(1,2,3),又可以先组装list或tuple,再通过*args传入:
func(*(1,2,3));
关键字参数既可以直接传入:
func(a=1,b=2),又可以先组装dict,再通过**kw传入:
func(**{'a':
1,'b':
2})。
使用*args和**kw是Python的习惯写法,当然也可以用其他参数名,但最好使用习惯用法。
命名的关键字参数是为了限制调用者可以传入的参数名,同时可以提供默认值。
定义命名的关键字参数在没有可变参数的情况下不要忘了写分隔符*,否则定义的将是位置参数。
递归函数
在函数内部,可以调用其他函数。
如果一个函数在内部调用自身本身,这个函数就是递归函数
递归函数的优点是定义简单,逻辑清晰。
理论上,所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。
使用递归函数需要注意防止栈溢出。
在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。
由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
解决递归调用栈溢出的方法是通过尾递归优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。
尾递归是指,在函数返回的时候,调用自身本身,并且,return语句不能包含表达式。
这样,编译器或者解释器就可以把尾递归做优化,使递归本身无论调用多少次,都只占用一个栈帧,不会出现栈溢出的情况
使用递归函数的优点是逻辑简单清晰,缺点是过深的调用会导致栈溢出。
针对尾递归优化的语言可以通过尾递归防止栈溢出。
尾递归事实上和循环是等价的,没有循环语句的编程语言只能通过尾递归实现循环。
Python标准的解释器没有针对尾递归做优化,任何递归函数都存在栈溢出的问题。
高级特性:
1、切片
L[0:
3]表示,从索引0开始取,直到索引3为止,但不包括索引3。
tuple也是一种list,唯一区别是tuple不可变。
因此,tuple也可以用切片操作,只是操作的结果仍是tuple
tuple也是一种list,唯一区别是tuple不可变。
因此,tuple也可以用切片操作,只是操作的结果仍是tuple:
>>>(0,1,2,3,4,5)[:
3]
(0,1,2)
字符串'xxx'也可以看成是一种list,每个元素就是一个字符。
因此,字符串也可以用切片操作,只是操作结果仍是字符串:
>>>'ABCDEFG'[:
3]
'ABC'
>>>'ABCDEFG'[:
:
2]
'ACEG'
在很多编程语言中,针对字符串提供了很多各种截取函数(例如,substring),其实目的就是对字符串切片。
Python没有针对字符串的截取函数,只需要切片一个操作就可以完成,非常简单。
2、迭代
如果给定一个list或tuple,我们可以通过for循环来遍历这个list或tuple,这种遍历我们称为迭代(Iteration)。
3、列表生成式
列表生成式即ListComprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式
写列表生成式时,把要生成的元素x*x放到前面,后面跟for循环,就可以把list创建出来,十分有用,多写几次,很快就可以熟悉这种语法。
#ex把list中所有字符串变成小写
L=['Hello','World','IBM','Apple']
print([s.lower()forsinL])
生成器
通过列表生成式,我们可以直接创建一个列表。
但是,受到内存限制,列表容量肯定是有限的。
而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?
这样就不必创建完整的list,从而节省大量的空间。
在Python中,这种一边循环一边计算的机制,称为生成器:
generator。
要创建一个generator,有很多种方法。
第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator
a,b=b,a+b
相当于:
t=(b,a+b)#t是一个tuple
a=t[0]
b=t[1]
迭代器:
可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;
一类是generator,包括生成器和带yield的generatorfunction。
这些可以直接作用于for循环的对象统称为可迭代对象:
Iterable。
可以使用isinstance()判断一个对象是否是Iterable对象:
可以被next()函数调用并不断返回下一个值的对象称为迭代器:
Iterator
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。
把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>>isinstance(iter([]),Iterator)
True
>>>isinstance(iter('abc'),Iterator)
True
你可能会问,为什么list、dict、str等数据类型不是Iterator?
这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。
可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。
小结
凡是可作用于for循环的对象都是Iterable类型;
凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;
集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
Python的for循环本质上就是通过不断调用next()函数实现的
函数式编程
未完。
。
待续
Scrapy
Scrapy使用了Twisted异步网络库来处理网络通讯。
整体架构大致如下
Scrapy主要包括了以下组件:
∙引擎(Scrapy)
用来处理整个系统的数据流处理,触发事务(框架核心)
∙调度器(Scheduler)
用来接受引擎发过来的请求,压入队列中,并在引擎再次请求的时候返回.可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列,由它来决定下一个要抓取的网址是什么,同时去除重复的网址
∙下载器(Downloader)
用于下载网页内容,并将网页内容返回给蜘蛛(Scrapy下载器是建立在twisted这个高效的异步模型上的)
∙爬虫(Spiders)
爬虫是主要干活的,用于从特定的网页中提取自己需要的信息,即所谓的实体(Item)。
用户也可以从中提取出链接,让Scrapy继续抓取下一个页面
∙项目管道(Pipeline)
负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。
当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
∙下载器中间件(DownloaderMiddlewares)
位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
∙爬虫中间件(SpiderMiddlewares)
介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
∙调度中间件(SchedulerMiddewares)
介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。