装饰器

在代码动态运行期间增加功能的方式,称为装饰器。本质上,decorator就是一个返回函数的高阶函数,也可以说高阶函数+嵌套函数=》装饰器。

def timer(func): #timer(test1)  func=test1
    def deco(*args,**kwargs):
        start_time = time.time()
        func(*args,**kwargs)  # run test1
        stop_time = time.time()
        print('the func run time is %s'%(start_time-stop_time))
    return deco
@timer  #test1 = timer(test1)
def test1():
    time.sleep(3)
    print('in the test1')


@timer  #test2 = timer(test2) = deco test2(name)=deco(name)
def test2(name,age):
    print('test2:',name,age)
test1()
test2('yeqin',22)

 如上,timer为一个装饰器,所以接受一个函数作为参数,并且返回一个函数,同时借用Python的@语法,把decorator置于函数的定义处。比如上述代码timer装饰test1()和test2.

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。

创建一个generator,方法一只要把一个列表生成式的[]改成(),就创建了一个generator,如下:

g = (x*x for x in range(10))
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
print(next(g))

我们讲过,generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。
但是我们一般不使用next方法,太麻烦了,正确的方法是使用for循环,因为generator也是可迭代对象:
for n in g:  #使用for循环打印g中的元素
    print(n)
练习:斐波那契数列
def fib(max):
    n,a,b = 0,0,1
    while n < max:
        # print(b)
        yield b
        a,b = b,a+b
        n = n+1
        return '---done---'
# f =  fib(10)
g = fib(6)

generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator。generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。

def odd():
    print('step1')
    yield 1
    print('step2')
    yield(3)
    print('step3')
    yield(5)
o = odd()
print(next(o))
print("----------")
print(next(o))

调用该generator时,首先要生成一个generator对象,然后用next()函数不断获得下一个返回值:

step1
1
----------
step2
3
step3
5

执行3次yield后,已经没有yield可以执行了,所以,第4次调用next(o)就会报错。

注意:1、生成器只有在调用时才会生成相应的数据;

           2、只记住当前位置;

           3、只有一个——next()——方法。

迭代器

可以直接作用于for循环的对象统称为迭代对象:Iterable。可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。迭代器和迭代对象均可以用isinstance()判断一个对象是否为相应的数。

print('Iterable?[1,2,3]:',isinstance([1,2,3],Iterable))
print('Iterable?\'abc\':',isinstance('abc',Iterable))
print('Iterable?123:',isinstance(123,Iterable) )
print('Iterable?g():',isinstance(g(),Iterable))

print('Iterator?[1,2,3]:',isinstance([1,2,3],Iterator))
print('Iterator?\'abc\':',isinstance('abc',Iterator))
print('Iterator?123:',isinstance(123,Iterator) )
print('Iterator?g():',isinstance(g(),Iterator))

注意:

凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的。

内置方法

print(all([1,-5,3]))  #元素全为非0才为真  true
print(any([1,0,3])) #任意为真,则为真 true
print(bin(8)) #十进制转二进制
print(bool(-1)) #判断真假 true
a = bytes('abcdef',encoding = 'utf-8')
print(a.capitalize(),a) #bytes字符串转为二进制形式,不可修改
b = bytearray('abcdef',encoding = 'utf-8') #改二进制字符串
print(b[1])
b[1] = 50
print(b)
def hello(): #判断是否可调用
pass
print(callable(hello)) #true
print(chr(97)) #返回ASCII对应表 a
print(ord('d')) #ASCII返回对应数字
code = '''
for i in range(10):
print(i)
'''
exec(code) #可直接运行代码
print(dir(dict())) #dict生成默认字典,dir查询方法
x = 1
print(eval('x+1')) #eval()运行python表达式 2
calc = lambda n:print(n) #匿名函数
print(calc(5))
calc2 =lambda n:3 if n<4 else n #进行三元运算
print(calc2(5))
#filter()过滤
res = filter(lambda n:n>5,range(10))
for i in res:
print(i) #5,6,7,8,9,
#map()一个时函数,一个数Iterable,map将传入的函数一次作用于序列的每个元素,并把结果作为新的Iterable
res = map(lambda n:n*n,range(10))
for i in res:
print(i)
print(hex(255)) #把一个数转为16进制
print(oct(8)) #转八进制
print(pow(2,5)) #返回2的5次方
print(round(1.31678,2)) #保留两位小数
a = [1,2,3,4]
b =['a','b','c','d']
for i in zip(a,b): #融合a和b
print(i)

序列化与反序列化
序列化:把变量从内存中变成可存储或者传输的过程称为序列化。
反序列化:把变量内容和从序列化的对象重新读入内存
json 序列化
import json
 
  dict = {'name':'Alex', 'age':33, 'address':'中国'}
  print('未序列化前的数据类型为:', type(dict))
  print('为序列化前的数据:', dict)
  #对dict进行序列化的处理
  dict_xu = json.dumps(dict,ensure_ascii=False)    #添加ensure_ascii=False进行序列化
  print('序列化后的数据类型为:', type(dict_xu))
  print('序列化后的数据为:', dict_xu)
  #对dict_xu进行反序列化处理
  dict_fan = json.loads(dict_xu)
  print('反序列化后的数据类型为:', type(dict_fan))
  print('反序列化后的数据为: ', dict_fan)
  ----------------------------------------------------------------------
 未序列化前的数据类型为: <class 'dict'>
 未序列化前的数据: {'name': 'Alex', 'age': 33, 'address': '中国'}
 序列化后的数据类型为: <class 'str'>
 序列化后的数据为: {"name": "Alex", "age": 33, "address": "中国"}
 反序列化后的数据类型为: <class 'dict'>
 反序列化后的数据为:  {'name': 'Alex', 'age': 33, 'address': '中国'}

注意:在序列化时,中文汉字总是被转换为unicode码,在dumps函数添加参数ensure_ascii=False即可解决问题。

pickle序列化与json功能类似,用法相同。不同的是,json更适合夸语言,可以处理字符串,基本数据类型;pickle为python专有,更适合用于处理复杂;类型的序列化。

 

 

 

 
posted on 2018-07-30 11:05  飞下落葉  阅读(204)  评论(0编辑  收藏  举报