python 装饰器、列表生成式、生成器、迭代器

# 作用域
# 高阶函数
# 闭包

# 闭包(closure)是函数式编程的重要的语法结构。

# 定义:如果在一个内部函数里,对在外部作用域(但不是在全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure).

# 闭包=函数块+定义函数时的环境,inner就是函数块,x就是环境,当然这个环境可以有很多,不止一个简单的x


# def outer():
# x = 1
#
# def inner():
# b = 6
# print(x)
#
# return inner
#
#
# # inner()#报错原因:找不到这个引用变量
# in_func = outer() # 这里其实就是一个变量赋值,inner的引用对象赋值给in_func,类似于a=5,b=a一样
# # 有同学会想直接赋值不行吗:in_func=inner? ,inner不还是找不到吗,对吧
# in_func()



# 装饰器(函数)decrator

# 必须遵守开放封闭原则

#*******************************************
import time


def show_time(func): #装饰器函数
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend %s' % (end_time - start_time))

return wrapper


def foo():
print('hello foo')
time.sleep(3)


foo = show_time(foo)
foo()

#******************************************

import time


def show_time(func): #装饰器函数
def wrapper():
start_time = time.time()
func()
end_time = time.time()
print('spend %s' % (end_time - start_time))

return wrapper


@show_time # foo=show_time(foo)
def foo():
print('hello foo')
time.sleep(3)


@show_time # bar=show_time(bar)
def bar():
print('in the bar')
time.sleep(2)


foo()
print('***********')
bar()

#**************************************


#带参数的装饰器函数

import time


def show_time(func):
def wrapper(a, b):
start_time = time.time()
func(a, b)
end_time = time.time()
print('spend %s' % (end_time - start_time))

return wrapper


@show_time # add=show_time(add)
def add(a, b):
time.sleep(1)
print(a + b)


add(2, 4)

#********************************************


#不定长参数
#***********************************不定长参数
import time

def show_time(func):

def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print('spend %s'% (end_time-start_time))

return wrapper

@show_time #add=show_time(add)
def add(*args, **kwargs):

time.sleep(1)
sum=0
for i in args:
sum += i
print(sum)

add(2,4,8,9)

#*********************************************


#装饰器参数

import time


def time_logger(flag=0):
def show_time(func):
def wrapper(*args, **kwargs):
start_time = time.time()
func(*args, **kwargs)
end_time = time.time()
print('spend %s' % (end_time - start_time))

if flag:
print('将这个操作的时间记录到日志中')

return wrapper

return show_time


@time_logger(3)
def add(*args, **kwargs):
time.sleep(1)
sum = 0
for i in args:
sum += i
print(sum)


add(2, 7, 5)

#
# @time_logger(3) 做了两件事:
# 1time_logger(3):得到闭包函数show_time,里面保存环境变量flag
# 2@show_time addshow_time(add)
# 上面的time_logger是允许带参数的装饰器。它实际上是对原有装饰器的一个函数封装,并返回一个装饰器(一个含有参数的闭包函数)。当我 们使用@time_logger(3)调用的时候,Python能够发现这一层的封装,并把参数传递到装饰器的环境中。





# 列表生成式

# a = [x*2 for x in range(10)] #X先遍历在赋给x*2的结果列表形式顺序不变
#
# print(a) #[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# **********************************************

# def f(n):
# return n**3
# a = [f(x) for x in range(10)]
# print(a) #[0, 1, 8, 27, 64, 125, 216, 343, 512, 729]

# ***********************************************




# 生成器 generator

# s = (x*2 for x in range(10))
#
# print(s) #<generator object <genexpr> at 0x000002560584AC80>
#
# print(s.__next__()) #内部特殊方法一般不建议使用
#
# print(next(s)) #等价于调用s.__next__() py2: s.next()



# 生成器就是一个可迭代对象 Iterable

# for i in s: # s就是一个迭代对象
# print(i)


# 生成器2种创建方式:
# 1 s = (x*2 for x in range(10))
# 2 yield


# def foo():
# print('ok')
# yield 1
# foo() #没有执行,说明foo()就是一个生成器对象
# next(foo()) # 这样才能进去并执行,结果打印:ok

# 什么是可迭代对象:iter

# l = [1,2,3]
# l.__iter__()
# print(l)

# 生成器执行:next() , send()

def bar():
print('ok')
cccc = yield 1
print(cccc)
sss = yield 2
print(sss)

b = bar()
b.send(None) #相当于next(b) 第一次send前如果没有next,只能传一个send(None)
b.send('333')



# 生成器都是迭代器,迭代器不一定是生成器
# list,tuple,dict,string,iterable都是可迭代對象
# 必須滿足2個條件:1.iter方法 2.next方法
# 集合数据类型如listdictstr等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。
# 可以使用isinstance()判断一个对象是否是Iterable对象
# Iterable 迭代對象
# Iterator 迭代器

from collections import Iterator, Iterable

l = [1,2,3,4]
d = iter(l)
print(d)
print(isinstance(l, list))
print(isinstance(l, Iterable))
print(isinstance(l, Iterator))
print(isinstance(d, Iterator))







posted @ 2020-03-23 11:32  chiy  阅读(403)  评论(0编辑  收藏  举报