python 函数名称应用 闭合 迭代器 装饰器

本节无练习

=============================================

 知识点概括:

    1. 函数名的应用(第一类对象)
        函数名的命名规范和变量是一样的.
        函数名其实就是变量名,

        # 可以作为列表中的元素进行存储.
        def func1():
            pass
        def func2():
            pass
        lst = [func1, func2]
        for el in lst:
            el()

        # 可以作为参数传递给函数.
        def func():
            pass
        def proxy(fn):
            fn()
        proxy(func)

        # 可以作为函数的返回值
        def func():
            def inner():
                pass
            return inner
        func()()
    2. 闭包
        闭包:在内层函数中访问外层函数的局部变量
        好处:
            1. 保护你的变量不受外界影响
            2. 可以让变量常驻内存
        写法:
            def outer():
                a = 10
                def inner():
                    print(a)
                return inner
    3. 迭代器
        使用dir来查看该数据包含了那些方法
        用来遍历列表,字符串,元祖....可迭代对象
        可迭代对象: Iterable, 里面有__iter__()可以获取迭代器, 没有__next__()
        迭代器:     Iterator, 里面有__iter__()可以获取迭代器, 还有__next__()

        迭代器特点:
            1. 只能向前.
            2. 惰性机制.
            3. 省内存(生成器)

        for循环的内部机制.
            1. 首先获取到迭代器.
            2. 使用while循环获取数据
            3. it.__next__()来获取数据
            4. 处理异常 try:xxx   except StopIteration:

            it = xx.__iter__()
            while 1:
                try:
                    data = it.__next__()
                    xxxxxx(操作)
                except StopIteration:
                    break
View Code

函数名称的应用

  函数名的命名规范和变量是一样的.

  函数名其实就是变量名.   

  函数名可以做  变量   参数   返回值

引入:

 1 def fun():
 2     print(1)
 3 a=fun   #函数赋值给a
 4 print(a) # <function fun at 0x000002039C392EA0>
 5 
 6 fun()  #只有加小括号的时候才是调用
 7 print(fun)   #没有小括号是地址  查看函数名的地址
 8 
 9 fun=3  #函数也是变量,可以重新赋值  函数名也是一个变量
10 print(fun)   #结果为3

   1) 函数名可以当做变量加入到列表中等.

 1 def func1():
 2     print("我是1")
 3 def func2():
 4     print("我是2")
 5 def func3():
 6     print("我是3")
 7 lst = [func1, func2, func3]  #函数名作为变量
 8 for el in lst:
 9     el()  # 分别执行函数
10 结果: 我是1  我是2   我是3

   2) 函数名可以作为参数传递给函数

def my():
    print('我是my')
def proxy(fn):   #代理模式.装饰器
    print(1)   #在处理之前
    fn()
    print(2)  #在处理之后
proxy(my)  #把函数名作为参数传递给另一个函数

结果:
        1
        我是my
        2

 

def func1():
    print('我是func1')
def func2():
    print('我是func2')
def func(fn,gn):
    print('我是func')
    fn()
    gn()
    print('哈哈哈')
func(func1,func2)
结果: 我是func 我是func1 我是func2 哈哈哈

   3) 函数名可以作为函数的返回值

1 def func():
2     print('我是func')
3     a=10
4     def inner():
5         print('我是inner')
6     return inner
7 ret = func()   #  等于inner
8 ret()   #inner()    执行inner
9 func()()   # inner()   执行inner

闭包

  闭包 : 在内层函数中访问外层函数的局部变量

  特点 : 1. 保护变量不受侵害, (因为全局变量是不稳定的)

       2. 可以让一个变量常驻内存

# 保护变量不受侵害

def outer():
    a=10   #对外界是不开放的
    def inner():
        print(a)  #内层函数方位外层函数(闭包)
    inner()
outer()
def func():  #该函数不会访问outer()中的变量
    a=20
    print('123')

 # 常驻内存

def outer():
    a=10   # 常驻内存, 为了inner执行的时候有值
    def inner():
        print(a)  #内层函数方位外层函数(闭包)
    return inner
fn = outer()
print('jidj')
fn()  #fn调用的时机是不确定的,所以inner中用到的东西也需要常驻内存

   典型的 超简易爬虫  用到闭包

 1 # 非闭包下
 2 from urllib.request import urlopen
 3 s=urlopen('http://www.xiaohua100.cn/index.html').read()
 4 print(s)    #非闭包形式下  每次访问都要通过网络 会有时间延迟  
 5 
 6 # 闭包下
 7 from urllib.request import urlopen
 8 def outer():
 9     s = urlopen('http://www.xiaohua100.cn/index.html').read()  #将地址作为常驻内存
10     def getcontent():
11         return s
12     return getcontent
13 print('爬取内容...')
14 pa = outer()  # 等于getcontent  # 第一次获取地址, 供以后使用
15 print(pa())   #第一次调用有延迟,并将其放入常驻内存中
16 print(pa())   #之后调用很快一瞬间,从常驻内存中获取
17 print(pa())
18 print(pa())

 # 查看是否是闭包

  print( 函数名.__closure__ )    用于查看是否是闭包

 1 def func():
 2     def inner():
 3         print('我是inner')
 4     print(inner.__closure__)   # 不是闭包
 5 # None
 6 
 7 def func1():
 8     a=10
 9     def inner():
10         print(a)
11     print(inner.__closure__)   # 是闭包 因为inner有访问外层函数中的变量
12 func1() # 返回的是地址
13 #(<cell at 0x0000019A6A959468: int object at 0x0000000059FC6D30>,)

迭代器

  特点:

    (1) 只能向前, 不能重复

    (2) 惰性机制

    (3) 节省内存 (体现在生成器中)

 

  1) 使用dir() 来查看该数据包含了那些方法

   用来遍历 列表,字符串,元组......可迭代对象

dir()  #查看  数据类型有什么方法
print(dir(str)) #  dir查看xx类型的数据可以执行哪些方法, __iter__  iterable
print(dir(list)) # __iter__
print(dir(int)) # 没有__iter__
# 所有的带__iter__可以使用for循环的, 可迭代对象

   2) 可迭代对象可以用__iter__() 来获取迭代器

      迭代器里有__next__()

s = "石可心喜欢赵一宁"
it = s.__iter__() # 获取迭代器
print(dir(it)) # 迭代器里有__iter__ 还有__next__    查看迭代器中的方法

结果:
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__',
'__ge__', '__getattribute__', '__gt__', '__hash__', '__init__',
'__init_subclass__', '__iter__', '__le__', '__length_hint__', '__lt__',
'__ne__', '__new__', '__next__', '__reduce__', '__reduce_ex__', '__repr__',
'__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']

  3) 迭代器模拟 for 循环

 1 lst = ['春天','夏天','秋天','冬天']
 2 # for el in lst:   # 常规的for循环
 3 #     print(el)
 4 it = lst.__iter__()   #获取迭代器
 5 while 1:
 6     try:    # 尝试执行
 7         el=it.__next__()  #获取下一个
 8         print(el)
 9     except StopIteration:  #处理错误
10         break

   4) 判断是否为  迭代器 或 迭代对象

    Iterable   迭代对象                 Iterator  迭代器

 1 lst = ['春天','夏天','秋天','冬天']
 2 it = lst.__iter__()  #获取迭代器
 3 
 4 # 偏方
 5 print("__iter__" in dir(it))   #是否迭代器  True
 6 print("__next__" in dir(it))   #是否迭代    True
 7 # 可以通过dir来判断数据是否是可迭代的, 以及数据是否是迭代器
 8 
 9 # 官方方案   首先引入模块
10 from collections import Iterable    # 可迭代对象  
11 from collections import Iterator    # 迭代器
12 
13 print(isinstance(lst, Iterable))   # True
14 print(isinstance(lst, Iterator))   # False   列表非迭代器
15 print(isinstance(it, Iterable))    # True
16 print(isinstance(it, Iterator))    # True

 

lst = ["赵四","花生哥, 越来越皮", "天台见"]
it = lst.__iter__()
# list(参数)把参数进行循环迭代
s = list(it) # 在list中.一定存在for. 一定__next__() 
print(s) # ["赵四","花生哥, 越来越皮", "天台见"]

装饰器

装饰器就是在不对原来函数做改变的情况下,在它的基础之上封装一些功能

典型示例:计算一个函数运行的时间长短

  1、传参的装饰器

import time
 
def show_time(func):
 
    def wrapper(a,b):             # func中的传参要在内部函数中传参,里面的fun才可以用
        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)

  2、不定长参数的装饰器

import time

def waibu(func):
    def neibu(*args, **kwargs):
        start = time.time()
        ret = func(*args, **kwargs)
        end = time.time()
        print(end - start)
        return ret

    return neibu


@waibu
def func(*args **kwargs):
    for i in range(100000000):
        continue
    return "OK"


print(func())     # 1.7812395095825195    # OK

 总结:

  1、装饰器还可以用在 Django  Flask 中的用户验证登录中,验证身份

 

 

装饰器详解

 

posted @ 2018-08-10 16:05  葡萄想柠檬  Views(113)  Comments(0)    收藏  举报
目录代码