来自 系统操作 2019-10-04 05:18 的文章
当前位置: 六合联盟网 > 系统操作 > 正文

python装饰器实例大详解,python装饰器大详解

一.作用域

一.作用域

在python中,功效域分为两种:全局效能域和一部分功效域。

 大局功能域是概念在文件级别的变量,函数名。而一部分功效域,则是概念函数内部。

 关于成效域,咱们要驾驭两点:

    a.在大局不能够访谈到有个别定义的变量

    b.在有些能够访谈到全局定义的变量,可是不可能修改全局定义的变量(当然有一点点子能够修改)

 上边我们来探视上面实例:

x = 1
def funx():
    x = 10
    print(x)  # 打印出10

funx()
print(x) # 打印出1

  如若有个别未有概念变量x,那么函数内部会从内往外最先查找x,若无找到,就能够报错

x = 1
def funx():
    print(x)  

funx()
print(x) # 打印出1

x = 1
def funx():
    def func1():
        print(x)  
    func1()

funx()
print(x) # 打印出1

 

  因而,关于成效域的难题,只须求记住两点就行:

    全局变量能够被文件任哪儿方引用,但修改只可以在大局举行操作;纵然部分没有找到所需的变量,就可现在外进行搜寻,未有找到就能够报错。

在python中,成效域分为三种:全局成效域和部分效用域。

二.尖端函数

笔者们知道,函数名其实便是指向一段内部存款和储蓄器空间的地址,既然是地方,那么我们能够使用这种性子来。

 全局效能域是概念在文件级其余变量,函数名。而有个别作用域,则是概念函数内部。

a函数名能够当做一个值

图片 1图片 2

def delete(ps):
    import os
    filename = ps[-1]
    delelemetns = ps[1]
    with open(filename, encoding='utf-8') as f_read,
        open('tmp.txt', 'w', encoding='utf-8') as f_write:
        for line in iter(f_read.readline, ''):
            if line != 'n':  # 处理非空行
                if delelemetns in line:
                    line = line.replace(delelemetns,'')
                f_write.write(line)
    os.remove(filename)
    os.rename('tmp.txt',filename)


def add(ps):
    filename = ps[-1]
    addelemetns = ps[1]
    with open(filename, 'a', encoding='utf-8') as fp:
        fp.write("n", addelemetns)

def modify(ps):
    import os
    filename = ps[-1]
    modify_elemetns = ps[1]
    with open(filename, encoding='utf-8') as f_read, 
            open('tmp.txt', 'w', encoding='utf-8') as f_write:
        for line in iter(f_read.readline, ''):
            if line != 'n':  # 处理非空行
                if modify_elemetns in line:
                    line = line.replace(modify_elemetns, '')
                f_write.write(line)
    os.remove(filename)
    os.rename('tmp.txt', filename)


def search(cmd):
    filename = cmd[-1]
    pattern = cmd[1]
    with open(filename, 'r', encoding="utf-8") as f:
        for line in f:
            if pattern in line:
                print(line, end="")
        else:
            print("没有找到")

dic_func ={'delete': delete, 'add': add, 'modify': modify, 'search': search}

while True:
    inp = input("请输入您要进行的操作:").strip()
    if not inp:
        continue
    cmd_1 = inp.split()
    cmd = cmd_1[0]
    if cmd in dic_func:
        dic_func[cmd](cmd_1)
    else:
        print("Error")

将函数作为字典值,达成公文数据的增加和删除查改操作

关于功用域,我们要通晓两点:

b.函数名可以看成重返值

def outer():
    def inner():
        pass
    return inner

s = outer()
print(s)

######输出结果为#######
<function outer.<locals>.inner at 0x000000D22D8AB8C8>

    a.在大局不可能访问到有的定义的变量

c.函数名能够当做三个参数

def index():
    print("index func")

def outer(index):
    s = index
    s()

outer(index)

######输出结果#########

index func

为此满意上边五个原则中的一个,都足以叫做高端函数.

 

    b.在局地能够访谈到全局定义的变量,可是不可能修改全局定义的变量(当然有办法能够修改)

三.闭包函数

  闭包函数必须满足多个规范:1.函数之中定义的函数 2.饱含对外表成效域而非全局功能域的引用

  下边通过有个别实例来表达闭包函数:

实例一:以下仅仅在函数内部定义了一个函数,但不用闭包函数.

def outer():
    def inner():
        print("inner func excuted")
    inner()  # 调用执行inner()函数
    print("outer func excuted")
outer()  # 调用执行outer函数

####输出结果为##########
inner func excuted
outer func excuted

实例二:以下在函数内部定义了二个函数,而且还引述了三个外部变量x,那么那些是闭包函数么?答案:不是

x = 1
def outer():

    def inner():
        print("x=%s" %x)  # 引用了一个非inner函数内部的变量
        print("inner func excuted")
    inner()  # 执行inner函数
    print("outer func excuted")

outer()
#####输出结果########
x=1
inner func excuted
outer func excuted

在回头来拜会对闭包函数的概念,是否两条都满足?聪明的你,一定发掘不知足第二条.对,这里的变量x,是属于全局变量,而非外界功效于域的变量。再来看看上边例子:

def outer():
    x = 1
    def inner():
        print("x=%s" %x)
        print("inner func excuted")
    inner()
    print("outer func excuted")

outer()

#####输出结果#########
x=1
inner func excuted
outer func excuted

无人不知,下面实例满意闭包函数的法则。未来,你应有精晓,作为二个闭包函数,必需得知足上述的五个条件,缺一不可。可是,日常境况下,大家都会给闭包函数再次来到二个值.这里先不说为啥.在接下去的内容中,你拜谒到这几个重回值的用途.

def outer():
    x = 1
    def inner():
        print("x=%s" %x)
        print("inner func excuted")
    print("outer func excuted")
    return inner  # 返回内部函数名

outer()

这段时间大家来抽象的概念一下闭包函数。它是函数和与其连带的援引蒙受组合而成的实体。在促成深约束时,须求创立一个能显式表示援引情形的事物,并将它与连锁的子程序捆绑在同步,那样捆绑起成为闭包。在上头实例中,大家可以开采,闭包函数,它必需含有自个儿的函数以及三个表面变量能力确实称得上是一个闭包函数。如果未有贰个外表变量与其绑定,那么這个函数不可能算得上是闭包函数。

  那么怎么掌握三个闭包函数有几个外表引用变量呢?看看下边代码.

def outer():
    x = 1
    y = 2

    def inner():
        print("x= %s" %x)
        print("y= %s" %y)

    print(inner.__closure__)
    return inner

outer()

######输出结果#######
(<cell at 0x000000DF9EA965B8: int object at 0x000000006FC2B440>, <cell at 0x000000DF9EA965E8: int object at 0x000000006FC2B460>)

结果申明,在inner内部,引用了四个外表局地变量。假若引用的是非局地变量,那么这里出口的为None.

  闭包函数的特色:1.自带效用域 2.延迟总结

  那么闭包函数有如何效力吗?大家清楚的敞亮,闭包函数在概念时,一定会绑定二个外界意况。這个全体能力算的上是一个闭包函数,那么我们得以选择那些绑定性子,来达成有些特殊的效果。

实例三:依据传入的UEscortL,来下载页面源码

from urllib.request import urlopen

def index(url)
    def get()
        return urlopen(url).read()
    return get

python = index("http://www.python.org") # 返回的是get函数的地址
print(python()) # 执行get函数《并且将返回的结果打印出来
baidu = index("http://www.baidu.com")
print(baidu())

有人能够会说,这些不满意闭包函数的条件啊!笔者尚未援用非全局的表面变量啊。其实并不是那样,给,大家事先说过,只要在函数内部的变量都属于函数。那么笔者在index(url),这一个url也属于函数内部,只可是大家简要一步而已,所以地点十一分函数也是闭包函数。

 下边大家来拜候下边实例:

四.装饰器

 有了上述基础,对于装饰器就好驾驭了.

  装饰器:外界函数字传送入被装饰函数名,内部函数重回装饰函数名。

  特点:1.不修改被点缀函数的调用方式2.不改换棉被服装饰函数的源代码

x = 1
def funx():
  x = 10
  print(x) # 打印出10
funx()
print(x) # 打印出1

a.无参装饰器

  有如下实例,我们需求总计一下代码推行的时间。

import time, random

def index():
    time.sleep(random.randrange(1, 5))
    print("welcome to index page")

依靠装饰器的特色,大家不可能对index()进行别的修改,何况调用方式也无法变。那时候,大家就足以采取装饰器来产生如上成效.

图片 3图片 4

import time, random


def outer(func):  # 将index的地址传递给func
    def inner():
        start_time = time.time()
        func()   # fun = index  即func保存了外部index函数的地址
        end_time = time.time()
        print("运行时间为%s"%(end_time - start_time))
    return inner  # 返回inner的地址


def index():
    time.sleep(random.randrange(1, 5))
    print("welcome to index page")

index = outer(index)  # 这里返回的是inner的地址,并重新赋值给index

index()

装饰器完结计时

只是,有个别意况,棉被服装饰的函数须要传递参数进去,有个别函数又没有须求参数,那么怎么样来拍卖这种变参数函数呢?上面来造访有参数装饰器的应用景况.

  借使部分未有概念变量x,那么函数内部会从内往外最先查找x,若无找到,就能够报错

b.有参装饰器

def outer(func):  # 将index的地址传递给func
    def inner(*args, **kwargs):
        start_time = time.time()
        func(*args, **kwargs)   # fun = index  即func保存了外部index函数的地址
        end_time = time.time()
        print("运行时间为%s"%(end_time - start_time))
    return inner  # 返回inner的地址

上边包车型地铁话说某些任何意况的实例。

   假诺被点缀的函数有重回值

def timmer(func):
    def wrapper(*args,**kwargs):
        start_time = time.time()
        res=func(*args,**kwargs) #res来接收home函数的返回值
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
        return res  
    return wrapper

def home(name):
    time.sleep(random.randrange(1,3))
    print('welecome to %s HOME page' %name)
    return 123123123123123123123123123123123123123123

那边补充有个别,出席大家要推行被点缀后的函数,那么应该是之类调用格局:

  home = timmer(home)  # 等式侧面再次回到的是wrapper的内部存储器地址,再将其赋值给home,这里的home不在是原先的的不得了函数,而是被点缀以往的函数了。

  像home = timmer(home)这样的写法,python给大家提供了二个简便的点子------语法糖@.

  以后我们再要在棉被服装饰的函数在此以前写上@timmer,它的作用就和home = timmer(home)是一致的。

  假使二个函数被多个装饰器装饰,那么施行各种是何等的。

图片 5图片 6

import time
import random

def timmer(func):
    def wrapper():
        start_time = time.time()
        func()
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
    return wrapper
def auth(func):
    def deco():
        name=input('name: ')
        password=input('password: ')
        if name == 'egon' and password == '123':
            print('login successful')
            func() #wrapper()
        else:
            print('login err')
    return deco

@auth   # index = auth(timmer(index))                 
@timmer # index = timmer(index)
def index():

    time.sleep(3)
    print('welecome to index page')



index()

View Code

  试验结果评释,多少个装饰器装饰三个函数,其实施种种是从下往上。

  关于装饰器,还应该有一点高级用法,有意思味的能够友善商量商量。

 

x = 1
def funx():
  print(x) 
funx()
print(x) # 打印出1
x = 1
def funx():
  def func1():
    print(x) 
  func1()
funx()
print(x) # 打印出1

  因而,关于作用域的难题,只须要牢记两点就行:

    全局变量能够被文件任哪个地方方援引,但修改只好在全局实行操作;要是有的未有找到所需的变量,就能够后外打开寻觅,未有找到就能够报错。

二.尖端函数

大家精通,函数名其实正是指向一段内存空间的地址,既然是地方,那么我们得以采用这种特征来。

def delete(ps):
  import os
  filename = ps[-1]
  delelemetns = ps[1]
  with open(filename, encoding='utf-8') as f_read,
    open('tmp.txt', 'w', encoding='utf-8') as f_write:
    for line in iter(f_read.readline, ''):
      if line != 'n': # 处理非空行
        if delelemetns in line:
          line = line.replace(delelemetns,'')
        f_write.write(line)
  os.remove(filename)
  os.rename('tmp.txt',filename)
def add(ps):
  filename = ps[-1]
  addelemetns = ps[1]
  with open(filename, 'a', encoding='utf-8') as fp:
    fp.write("n", addelemetns)
def modify(ps):
  import os
  filename = ps[-1]
  modify_elemetns = ps[1]
  with open(filename, encoding='utf-8') as f_read, 
      open('tmp.txt', 'w', encoding='utf-8') as f_write:
    for line in iter(f_read.readline, ''):
      if line != 'n': # 处理非空行
        if modify_elemetns in line:
          line = line.replace(modify_elemetns, '')
        f_write.write(line)
  os.remove(filename)
  os.rename('tmp.txt', filename)
def search(cmd):
  filename = cmd[-1]
  pattern = cmd[1]
  with open(filename, 'r', encoding="utf-8") as f:
    for line in f:
      if pattern in line:
        print(line, end="")
    else:
      print("没有找到")
dic_func ={'delete': delete, 'add': add, 'modify': modify, 'search': search}
while True:
  inp = input("请输入您要进行的操作:").strip()
  if not inp:
    continue
  cmd_1 = inp.split()
  cmd = cmd_1[0]
  if cmd in dic_func:
    dic_func[cmd](cmd_1)
  else:
    print("Error")

 将函数作为字典值,完结公文数据的增加和删除查改操作

b.函数名能够用作再次来到值

def outer():
  def inner():
    pass
  return inner
s = outer()
print(s)
######输出结果为#######
<function outer.<locals>.inner at 0x000000D22D8AB8C8>

c.函数名能够充任贰个参数

def index():
  print("index func")
def outer(index):
  s = index
  s()
outer(index)
######输出结果#########
index func

进而满意上边四个规范中的三个,都足以叫做高等函数.

三.闭包函数

  闭包函数必需满意三个规范:1.函数内部定义的函数 2.含有对外表功用域而非全局功能域的引用

  下边通过某些实例来表达闭包函数:

实例一:以下仅仅在函数内部定义了三个函数,但不用闭包函数.

def outer():
  def inner():
    print("inner func excuted")
  inner() # 调用执行inner()函数
  print("outer func excuted")
outer() # 调用执行outer函数
####输出结果为##########
inner func excuted
outer func excuted

实例二:以下在函数内部定义了二个函数,而且还引述了一个外界变量x,那么那几个是闭包函数么?答案:不是

x = 1
def outer():
  def inner():
    print("x=%s" %x) # 引用了一个非inner函数内部的变量
    print("inner func excuted")
  inner() # 执行inner函数
  print("outer func excuted")
outer()
#####输出结果########
x=1
inner func excuted
outer func excuted

在回头来探视对闭包函数的定义,是或不是两条都满足?聪明的您,一定开掘不满意第二条.对,这里的变量x,是属于全局变量,而非外部效用于域的变量。再来看看下边例子:

def outer():
  x = 1
  def inner():
    print("x=%s" %x)
    print("inner func excuted")
  inner()
  print("outer func excuted")
outer()
#####输出结果#########
x=1
inner func excuted
outer func excuted

妇孺皆知,上边实例满足闭包函数的标准。以后,你应有精通,作为贰个闭包函数,必须得知足上述的七个标准,缺一不可。可是,平日意况下,我们都会给闭包函数再次来到三个值.这里先不说为什么.在接下去的源委中,你拜访到这几个重回值的用途.

def outer():
  x = 1
  def inner():
    print("x=%s" %x)
    print("inner func excuted")
  print("outer func excuted")
  return inner # 返回内部函数名
outer()

这两天大家来抽象的概念一下闭包函数。它是函数和与其相关的援用情状组合而成的实业。在贯彻深约束时,需求创立二个能显式表示引用意况的事物,并将它与连锁的子程序捆绑在一齐,那样捆绑起成为闭包。在下面实例中,大家得以窥见,闭包函数,它必得含有本人的函数以及三个外界变量才具真的称得上是三个闭包函数。如果未有二个外表变量与其绑定,那么這个函数无法算得上是闭包函数。

  那么怎么掌握一个闭包函数有些许个外表援引变量呢?看看下边代码.

def outer():
  x = 1
  y = 2
  def inner():
    print("x= %s" %x)
    print("y= %s" %y)
  print(inner.__closure__)
  return inner
outer()
######输出结果#######
(<cell at 0x000000DF9EA965B8: int object at 0x000000006FC2B440>, <cell at 0x000000DF9EA965E8: int object at 0x000000006FC2B460>)

结果注解,在inner内部,援引了多个外表局地变量。如果引用的黑白局地变量,那么这里出口的为None.

  闭包函数的性状:1.自带功效域 2.延迟计算

  那么闭包函数有何意义吧?大家领略的精通,闭包函数在概念时,一定会绑定五个外界景况。這个全体本事算的上是二个闭包函数,那么我们可以动用那个绑定性子,来实现某个特殊的功力。

实例三:依据传入的UENCOREL,来下载页面源码

from urllib.request import urlopen
def index(url)
  def get()
    return urlopen(url).read()
  return get
python = index("http://www.python.org") # 返回的是get函数的地址
print(python()) # 执行get函数《并且将返回的结果打印出来
baidu = index("http://www.baidu.com")
print(baidu())

有人能够会说,这几个不满意闭包函数的标准啊!小编从未援引非全局的表面变量啊。其实并不是那样,给,大家事先说过,只要在函数内部的变量都属于函数。那么自身在index(url),这些url也属于函数内部,只可是我们大约一步而已,所以地方十二分函数也是闭包函数。

四.装饰器

 有了上述基础,对于装饰器就好理解了.

  装饰器:外界函数字传送入棉被服装饰函数名,内部函数再次来到装饰函数名。

  特点:1.不改换被点缀函数的调用情势 2.不修改棉被服装饰函数的源代码

a.无参装饰器

  有如下实例,大家供给总结一下代码试行的岁月。

import time, random
def index():
  time.sleep(random.randrange(1, 5))
  print("welcome to index page")

听新闻说装饰器的性状,大家不可能对index()进行任何改造,何况调用格局也不可能变。那时候,我们就可以利用装饰器来成功如上效率.

import time, random
def outer(func): # 将index的地址传递给func
  def inner():
    start_time = time.time()
    func()  # fun = index 即func保存了外部index函数的地址
    end_time = time.time()
    print("运行时间为%s"%(end_time - start_time))
  return inner # 返回inner的地址
def index():
  time.sleep(random.randrange(1, 5))
  print("welcome to index page")
index = outer(index) # 这里返回的是inner的地址,并重新赋值给index
index()

而是,有个别景况,被点缀的函数必要传递参数进去,某些函数又无需参数,那么怎么着来管理这种变参数函数呢?上边来探视有参数装饰器的利用意况.

b.有参装饰器

def outer(func): # 将index的地址传递给func
  def inner(*args, **kwargs):
    start_time = time.time()
    func(*args, **kwargs)  # fun = index 即func保存了外部index函数的地址
    end_time = time.time()
    print("运行时间为%s"%(end_time - start_time))
  return inner # 返回inner的地址

下边包车型客车话说一些任何景况的实例。

   借使被点缀的函数有重返值

def timmer(func):
  def wrapper(*args,**kwargs):
    start_time = time.time()
    res=func(*args,**kwargs) #res来接收home函数的返回值
    stop_time=time.time()
    print('run time is %s' %(stop_time-start_time))
    return res 
  return wrapper
def home(name):
  time.sleep(random.randrange(1,3))
  print('welecome to %s HOME page' %name)
  return 123123123123123123123123123123123123123123

此地补充某个,参与我们要施行被点缀后的函数,那么应该是之类调用情势:

  home = timmer(home)  # 等式侧面再次回到的是wrapper的内存地址,再将其赋值给home,这里的home不在是原先的的不得了函数,而是被点缀以往的函数了。

  像home = timmer(home)那样的写法,python给我们提供了贰个简便的法子------语法糖@.

  今后大家再要在棉被服装饰的函数此前写上@timmer,它的效用就和home = timmer(home)是一模二样的。

  若是一个函数被四个装饰器装饰,那么施行各样是怎么的。

import time
import random
def timmer(func):
  def wrapper():
    start_time = time.time()
    func()
    stop_time=time.time()
    print('run time is %s' %(stop_time-start_time))
  return wrapper
def auth(func):
  def deco():
    name=input('name: ')
    password=input('password: ')
    if name == 'egon' and password == '123':
      print('login successful')
      func() #wrapper()
    else:
      print('login err')
  return deco
@auth  # index = auth(timmer(index))         
@timmer # index = timmer(index)
def index():
  time.sleep(3)
  print('welecome to index page')
index()

  实验结果注解,四个装饰器装饰三个函数,其实践各种是从下往上。

本文由六合联盟网发布于系统操作,转载请注明出处:python装饰器实例大详解,python装饰器大详解

关键词: