python走起之第四话

本节大纲:

一:双层装饰器:
一个函数可以被多层装饰器进行装饰,函数渲染(编译)从下到上,函数执行从上到下。
如下程序:

复制代码
 1 #!/usr/bin/env python
 2 #-*-coding:utf-8-*-
 3 # author:liumeide
 4 
 5 # USERINOF={'islogin':True}
 6 USERINOF={'user_type':'2','islogin':True}
 7 def login(func):
 8     def inner_1(*args,**kwargs):
 9         if USERINOF.get('islogin',None):
10             ret=func()
11             return ret
12         else:
13             print('login first!')
14     return  inner_1
15 def check_user(func):
16     def inner(*args,**kwargs):
17         if USERINOF.get('islogin',None)==True and USERINOF.get('user_type',None)=='2':
18             ret=func()
19             return ret
20         else:
21             print('permission deny!!')
22     return inner
23 @login
24 @check_user
25 def index():
26     print('index')
27 
28 index()
复制代码
 多层装饰器该如何理解呢?

 上面的函数的可以执行顺序可以理解为:

首先:函数login、check_user、index加载到内存。在调用index函数的时候,执行index函数,因为index函数被check_user函数装饰,所以把check_user函数的内的inner函数体重新赋值给index,index函数体被当做
参数传入check_user函数。当满足inner函数的条件的时候被执行,新的函数index函数的函数体inner被login函数的所装饰,也就是说inner函数被重新赋值给inner_1函数。也就是说最后调用执行index()顺序:
先执行inner_1函数体----->在执行inner函数体-->在执行index原先的函数体。
多层装饰器以此类推,同样的原理。三层以上的装饰器很少使用。
二:字符串格式化:
%[(name)][flags][width].[precision]typecode
%号初始化字符串:
顺序传入参数。
执行名称传入参数
保留小数点后几位
当有占位符的时候 需要%%输出%如果没有占位符需要只写一个%在占位符的时候类似一个转义的意思。
1:
1 print('name:%s,age:%s'%('evil','22'))
2 
3 name:evil,age:22
普通字符串的初始化,需要传入的实参和占位符的个数保持一致。
(name):按名字进行取值。

 

 2:可以根据占位的name的key,根据后面的字典对应的value进行传入来进行传入实参。
1 print("Name:%(name)s"%{'name':'ok'})
2 Name:ok
3: flags一般和width宽度来一起配合使用,如果单纯的使用flags并没什么效果。很少使用这个功能。
1 print("qqqq%(name)+s"%{'name':'ok'})
2 qqqqok
2个一起配合使用:+10表示右对齐,字符串ok占用10个字符。右对齐;正数前加正好,负数前加负号
1 print("qqqq%(name)+10s"%{'name':'ok'})
2 qqqq        ok

  -号表示左对齐。左对齐;正数前无符号,负数前加负号;

空格    右对齐;正数前加空格,负数前加负号;

0        右对齐;正数前无符号,负数前加负号;用0填充空白处; 

 .precision   可选,小数点后保留的位数

但是没有居中的功能。

1 print("qqqq%(name)-10sqqq"%{'name':'ok'})
2 qqqqok        qqq
 
print("%+10d" % 10)
       +10


1 print("%-10d" %10)
2 10        

 
1 print("%04d" % 5)
2 0005

1 print("%04d" % -5)
2 -005
1 print("% 4d" % 5)
2    5

 

1 print("%.2f" % 1.225)
2 1.23

 

typecode表示执行传入的字符串类型。有如下:

s,获取传入对象的__str__方法的返回值,并将其格式化到指定位置

r,获取传入对象的__repr__方法的返回值,并将其格式化到指定位置

c,整数:将数字转换成其unicode对应的值,10进制范围为 0 <= i <= 1114111(py27则只支持0-255);字符:将字符添加到指定位置

o,将整数转换成 八  进制表示,并将其格式化到指定位置

x,将整数转换成十六进制表示,并将其格式化到指定位置

d,将整数、浮点数转换成 十 进制表示,并将其格式化到指定位置

e,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(小写e)

E,将整数、浮点数转换成科学计数法,并将其格式化到指定位置(大写E)

f, 将整数、浮点数转换成浮点数表示,并将其格式化到指定位置(默认保留小数点后6位)

F,同上

g,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是e;)

G,自动调整将整数、浮点数转换成 浮点型或科学计数法表示(超过6位数用科学计数法),并将其格式化到指定位置(如果是科学计数则是E;)

  %,当字符串中存在格式化标志时,需要用 %%表示一个百分号

但是没有将整数转换成二进制功能。

1 print('%%%d'%5)
2 %5
1 print('------%c-----%o-------%x'%(65,15,15))
2 ------A-----17-------f

 

format函数初始化字符串:
[[fill]align][sign][#][0][width][,][.precision][type]
1 print('adad{0}adadada{0}dada{1}'.format(1,2))
2 adad1adadada1dada2
1 print('adad{name}adadada{age}'.format(name='OK',age=22))
2 adadOKadadada22

 

居中功能并用a填充宽度为10. 
1 print('adad{name:a^10s}adadada{age}'.format(name='OK',age=22))
2 adadaaaaOKaaaaadadada22
左对齐<
1 print('adad{name:a<10s}adadada{age}'.format(name='OK',age=22))
2 adadOKaaaaaaaaadadada22

 右对齐>

1 print('adad{name:a>10s}adadada{age}'.format(name='OK',age=22))
2 adadaaaaaaaaOKadadada22

 

转化百分比
print('this is {:%}'.format(0.2222))
this is 22.220000%
支持整数转化二进制输出:
1 print("---{0:d}----{0:b}---{0:o}--{1:%}".format(15,0.2))
2 ---15----1111---17--20.000000%
三:生成器和迭代器
具有生成一定条件数据的能力的对象叫做生成器。
具有取数据的能力叫做迭代器。
在进行处理大数据的时候,用生成器会降低内存的消耗,每一次取值生成一次,在下次取值的时候,内存会回收该值,避免了浪费内存。
其中filter函数和map函数返回的对象就是生成器。比如xrange函数返回的对象也是生成器。
复制代码
1 a=[1,2,31,4]
2 f=filter(lambda a:a>3,a)
3 
4 for i in f:
5     print(i)
6 print(f)
7 31
8 4
9 <filter object at 0x004C5B50>
复制代码

 

生成器本身由函数创造的,如何把普通的函数转成生成器呢?
如果函数体内包含关键字yield 时这个函数就是生成器。
复制代码
1 def fun():
2     print(111)
3     yield 1
4 fun()
5 print(fun())
6 <generator object fun at 0x00584780>
复制代码

 在调用函数的fun()时候并不执行函数。只有去取这个对象的时候进行生成。

复制代码
 1 def fun():
 2     yield 1
 3     yield 2
 4     yield 3
 5 fun()
 6 for i in fun():
 7     print('__%s'%i)
 8 print(fun())
 9 __1
10 __2
11 __3
12 <generator object fun at 0x004E4780>
复制代码

 当for循环执行时,执行函数体。第一次的时候,去函数func找yield 对应的值1 赋值给i输出,第二次从第一次的位置下一个的yield的值为2取值并赋值给i,直到取到所有的yield的结束循环。每一次取值生成对应的对象。

上面的函数fun是生成器而生成的结果fun()是迭代器,也就说对象具有可以被迭代,在迭代时候执行next方法取值,只能从前往后取值,

练习:基于生成器生成range功能。
复制代码
 1 def myrange(args):
 2     st=0
 3     while True:
 4         if st >args:
 5             return
 6         yield st
 7         st+=1
 8 ret=myrange(9)
 9 for i in ret:
10     print(i)
11 0
12 1
13 2
14 3
15 4
16 5
17 6
18 7
19 8
20 9
复制代码

 

四:函数递归。执行本身的函数体,当满足一定条件退出,并把最后执行的结果返回给上个函数,如果没有条件限制会无限执行下去。
复制代码
1 def fun(x):
2     x+=1
3     if x>3:
4         return 1
5     return fun(x)
6 t=fun(1)
7 print(t)
8 1
复制代码

 执行3次fun(x)函数。循环执行多次相同的函数体。

 

 

练习:实现累乘功能,比如输入3  实现3*2*1

复制代码
1 def fun(x):
2     if x==1:
3         return 1
4     return x*fun(x-1)
5 print(fun(3))
6 6
复制代码

 

五:模块
分类:内置模块、第三方模块、自定义模块。在python中叫模块其他语言叫类库。
使用模块:先import 导入后使用。
存在方式:.py文件。或者一个文件夹里有多个.py文件组成的一个模块。
自定义模块导入:

目录之间用.表示

如果同一级不通模块导入相同的方法该如何区分呢???

1:通过相对路径来区分

request模块调用上面的2个co模块。如果路径层级不多可以这么写 如果层级过多呢?调用次数过多呢?

复制代码
1 import lib.co
2 import common.co
3 common.co.login()
4 lib.co.login()
5 common OK
6 lib OK
复制代码

 

简单的方法 将导入的模块进行别名操作:

复制代码
1 from lib import  co as f1
2 from  common import  co as f2
3 f1.login()
4 f2.login()
5 lib OK
6 common OK
复制代码

 

下面的方法是我们经常用的。

模块的意义:便于管理代码。不同的功能的代码进行归类。

模块导入的依据:

复制代码
1 import sys
2 print(sys.path)
3 C:\python2\day6
4 C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\python35.zip
5 C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\DLLs
6 C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\lib
7 C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32
8 C:\Users\Administrator\AppData\Local\Programs\Python\Python35-32\lib\site-packages
复制代码

 

sys.path是一个路径的列表。默认python 有限搜索当前py文件的目录依次搜索。所以当我们自定义模块时候可以有2种方式让python 找到我们定义的模块:

1:把自定义模块加入这个列表(append())

2:把自定义的模块加入上面的目录之中。

这样在导入模块的时候不会出现:ImportError: No module named 'xxx'

那怎么找出自己模块所在目录呢?

复制代码
1 import os
2 print(os.path.abspath(__file__))
3 print(os.path.dirname(os.path.abspath(__file__)))
4 print(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5 
6 C:\python2\day6\s2.py
7 C:\python2\day6
8 C:\python2
复制代码

 

根据自己需求将自己的变量导入sys.path即可。

模块的名称:不要和系统的内置模块的名字冲突。

第三方模块:1:pip进行安装

      2:源码进行安装。

安装第三方模块:requests

pip install requests

常用模块介绍:

json模块:

常用函数dums()、dum();loads()、load()

对于加s参数和不加s参数区别:

加s的是直接可以对python 的数据转换成json串(dums())或者直接将json串转换成python能识别的数据类型。而不加s的是将python的数据转换成json串并将json串写入文件中,或者将文件中的json串转换成python的基本数据。

1 data=[1,2,3,4,(1,2,True)]
2 obl=json.dumps(data)
3 with open('data.txt','w') as f1:
4     f1.write(obl)
5 <class 'str'> [1, 2, 3, 4, [1, 2, true]]

 

 

如果需要写入需要操作文件才能写入。

1 data=[1,2,3,4,(1,2,True)]
2 obl=json.dumps(data)
3 t_load=json.loads(obl,encoding='utf8')
4 print(type(t_load),t_load)
5 <class 'list'> [1, 2, 3, 4, [1, 2, True]]

 

在将python基本数据类型进行json转换的时候,会将python的一些数据类型或者相应的值进行转换,比如上面的python的元组转换json时候变为列表。True变为 true。

转换表如下:

跨语言平台常用该模块。该模块可以将python的基本数据类型(列表、字典)转换成字符串----序列化。也可以将字符串形式的python 类型字符创转换成对应的数据类型(列表、字典)--反序列化。

 

复制代码
1 import json
2 list_1=[1,2,3,4,]
3 # json.dump(list_1,open('json.txt','w'))
4 obj=json.load(open('json.txt','r'))
5 print(obj)
6 [1, 2, 3, 4]
复制代码
pickle模块:可以将非python数据类型的数据进行序列化和反序列化。存储方式是二进制。所以要以wb或者rb进行相关的dums和loads
1 import pickle
2 a='aa'
3 pickle.dump(bytes(a,encoding='utf-8'),open('pickle.txt','wb'))

 pickle.dumps()将相应的数据类型转换成字节。如果不指定编码,python解释器会用默认编码进行处理。

1 import pickle
2 data=[1,2,3,4,(1,2,True)]
3 t=pickle.dumps(data)
4 print(t,type(t))
5 b'\x80\x03]q\x00(K\x01K\x02K\x03K\x04K\x01K\x02\x88\x87q\x01e.' <class 'bytes'>

 

复制代码
1 import pickle
2 a='aa'
3 # pickle.dump(bytes(a,encoding='utf-8'),open('pickle.txt','wb'))
4 t=pickle.load(open('pickle.txt','rb'))
5 s=str(t,encoding='utf-8')
6 print(s)
7 aa
复制代码

 

复制代码
import pickle
data=[1,2,3,4,(1,2,True)]
t=pickle.dumps(data)
t_load=pickle.loads(t)
print(t_load,type(t_load))
[1, 2, 3, 4, (1, 2, True)] <class 'list'>
复制代码

 

 在Django中会用到经常用到pickle模块。

requests模块:属于第三方模块需要进行手动安装(pip  install requests)

进入python安装目录:E:\python3.6\Scripts

运行:pip.exe install request

复制代码
import  requests
import json
res=requests.get("http://wthrcdn.etouch.cn/weather_mini?city=北京")
res.encoding='utf-8'
print(type(res))
dict_1=json.loads(res.text)
print(dict_1)
复制代码
posted @ 2016-08-18 17:59  J.M.Guo  阅读(257)  评论(0)    收藏  举报