false

7.8 磅
0
2

false
false
false

EN-US
ZH-CN
X-NONE


/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-priority:99;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}
table.MsoTableGrid
{mso-style-name:网格型;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-priority:39;
mso-style-unhide:no;
border:solid windowtext 1.0pt;
mso-border-alt:solid windowtext .5pt;
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-border-insideh:.5pt solid windowtext;
mso-border-insidev:.5pt solid windowtext;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.5pt;
mso-bidi-font-size:11.0pt;
font-family:"Calibri","sans-serif";
mso-ascii-font-family:Calibri;
mso-ascii-theme-font:minor-latin;
mso-hansi-font-family:Calibri;
mso-hansi-theme-font:minor-latin;
mso-bidi-font-family:"Times New Roman";
mso-bidi-theme-font:minor-bidi;
mso-font-kerning:1.0pt;}

函数装饰器:

<![if !supportLists]>一.   <![endif]>什么是装饰器:

装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。

这种模式创建了一个装饰类,用来包装原有的类,并在保持类方法签名完整性的前提下,提供了额外的功能。

<![if !supportLists]>二.   <![endif]>为什么要用装饰器:

软件实体应该是可扩展,而不可修改的。也就是说,对扩展是开放的,而对修改是封闭的,具体可以参考:

百度百科: https://baike.baidu.com/item/开放封闭原则/6028662?fr=aladdin

维基百科: https://zh.wikipedia.org/wiki/开闭原则

<![if !supportLists]>三.   <![endif]>要知道的三个概念:

<![if !supportLists]>1.       <![endif]>函数的作用域

<![if !supportLists]>a.       <![endif]>什么叫作用域:

在电脑程序设计中,作用域(scope,或译作有效范围)是名字(name)与实体(entity)的绑定(binding)保持有效的那部分计算机程序。不同的编程语言可能有不同的作用域和名字解析。而同一语言内也可能存在多种作用域,随实体的类型变化而不同。作用域类别影响变量的绑定方式,根据语言使用静态作用域还是动态作用域变量的取值可能会有不同的结果。

出自维基百科: https://zh.wikipedia.org/wiki/作用域

<![if !supportLists]>b.       <![endif]>Python中怎么产生不同的作用域

在Python中,只有模块(module),类(class)以及函数(def、lambda)才会引入新的作用域,其它的代码块(如if、try、for等)是不会引入新的作用域的.

来自: http://www.cnblogs.com/yuanchenqi/articles/5828233.html

<![if !supportLists]>c.       <![endif]>在Python中有几种作用域:

即:L-R-G-B

local: 局部作用域,即函数中定义的变量

enclosing: 嵌套的父级函数的局部作用域,即包含此函数的上级函数的局部作用域,但不是全局的

global:全局变量,就是模块级别定义的变量

builtins: 内置作用域(python内置)

LEGB含义解释:

L-Local(function);函数内的名字空间

E-Enclosing function locals;外部嵌套函数的名字空间(例如closure)

G-Global(module);函数定义所在模块(文件)的名字空间

B-Builtin(Python);Python内置模块的名字空间

LEGB规定了查找一个名称的顺序为:local-->enclosing function locals-->global-->builtin

作者:_Zhao_

链接:http://www.jianshu.com/p/3b72ba5a209c

來源:简书

下面内容来自Python的官方文档:

4.2.2. Resolution of names

A scope defines the visibility of a name within a block. If a local variable is defined in a block, its scope includes that block. If the definition occurs in a function block, the scope extends to any blocks contained within the defining one, unless a contained block introduces a different binding for the name.

When a name is used in a code block, it is resolved using the nearest enclosing scope. The set of all such scopes visible to a code block is called the block’s environment.

When a name is not found at all, a NameError exception is raised. If the current scope is a function scope, and the name refers to a local variable that has not yet been bound to a value at the point where the name is used, an UnboundLocalError exception is raised. UnboundLocalError is a subclass of NameError.

If a name binding operation occurs anywhere within a code block, all uses of the name within the block are treated as references to the current block. This can lead to errors when a name is used within a block before it is bound. This rule is subtle. Python lacks declarations and allows name binding operations to occur anywhere within a code block. The local variables of a code block can be determined by scanning the entire text of the block for name binding operations.

If the global statement occurs within a block, all uses of the name specified in the statement refer to the binding of that name in the top-level namespace. Names are resolved in the top-level namespace by searching the global namespace, i.e. the namespace of the module containing the code block, and the builtins namespace, the namespace of the module builtins. The global namespace is searched first. If the name is not found there, the builtins namespace is searched. The global statement must precede all uses of the name.

The global statement has the same scope as a name binding operation in the same block. If the nearest enclosing scope for a free variable contains a global statement, the free variable is treated as a global.

The nonlocal statement causes corresponding names to refer to previously bound variables in the nearest enclosing function scope. SyntaxError is raised at compile time if the given name does not exist in any enclosing function scope.

The namespace for a module is automatically created the first time a module is imported. The main module for a script is always called __main__.

Class definition blocks and arguments to exec() and eval() are special in the context of name resolution. A class definition is an executable statement that may use and define names. These references follow the normal rules for name resolution with an exception that unbound local variables are looked up in the global namespace. The namespace of the class definition becomes the attribute dictionary of the class. The scope of names defined in a class block is limited to the class block; it does not extend to the code blocks of methods – this includes comprehensions and generator expressions since they are implemented using a function scope. This means that the following will fail:

class A:

a = 42

b = list(a + i for i in range(10))

<![if !supportLists]>2.       <![endif]>一切皆对象,即一个函数可以作为一个参数传入到另外一个函数中

<![if !supportLists]>3.       <![endif]>闭包:

<![if !supportLists]>a.       <![endif]>闭包的定义:

在计算机科学中,闭包(英语:Closure),又称词法闭包(Lexical Closure)或函数闭包(function closures),是引用了自由变量的函数。这个被引用的自由变量将和这个函数一同存在,即使已经离开了创造它的环境也不例外。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。

出自维基百科: https://zh.wikipedia.org/wiki/闭包_(计算机科学)

<![if !supportLists]>b.       <![endif]>简单的理解方式:

闭包=函数块+定义函数时的环境

<![if !supportLists]>c.       <![endif]>举个栗子:

In [15]: def outer():

...:     name ="Tom"

...:     def inner():

...:         return name

...:     return inner

...:

In [16]: ret  = outer()

In [17]: ret

Out[17]: <function __main__.outer.<locals>.inner>

In [18]: ret()

Out[18]: 'Tom'

<![if !vml]>

[endif]>

如图:out()内部空间的name在外部被使用了.嗯,这就是个闭包:

还有疑问可以移步到: http://www.cnblogs.com/yuanchenqi/articles/5830025.html

<![if !supportLists]>四.   <![endif]>函数装饰器

一开始介绍了什么是装饰器,以及为什么要用装饰器,那么怎么去实现一个装饰器,以及装饰器是怎么工作的:

例如.现在有一个函数,现在需要在这个函数上新加一些功能:

<![if !supportMisalignedColumns]><![endif]>

import time

def foo():

print("hello world")

time.sleep(2)

# 现在要输出foo()实际的执行时间可以这样

def show_time():

start=time.time()

foo()

end=time.time()

print(end-start)

# 执行变成了 show_time()

# show_time()

def show_time1(f):

"""将函数作为参数传入"""

start = time.time()

f()

end = time.time()

print(end - start)

show_time1(foo)

def show_time(f):

def inner():

start = time.time()

f()

end=time.time()

print(end-start)

return inner

foo = show_time(foo)

foo()

<![if !vml]>

<![endif]>

# python提供了一种方法

@show_time    #相当于执行了foo = show_time(foo)

def foo():

print("hello world")

time.sleep(2)

foo()

<![if !vml]>

<![endif]>

执行foo()实际上相当于执行的是inner()

这时inner()就是一个闭包

当foo存在参数的时候如何处理:注意看上图,图中foo实际上即使inner

def show_time(f):

def inner(*args,**kwargs):

start = time.time()

f(*args,**kwargs)

end=time.time()

print(end-start)

return inner

@show_time

def foo(a,b):

"""foo有参数的情况"""

print(a*b)

time.sleep(2)

foo("hello",5)

<![if !vml]>

<![endif]>

突然有个想法,装饰器上还可不可以再加装饰器:

答案是可以滴:

import time

def show_time(f):

def inner(*args,**kwargs):

start = time.time()

f(*args,**kwargs)

end=time.time()

print(end-start)

return inner

def test(f):

def inner():

print("test")

f()

return inner

@test

@show_time    #相当于执行了foo = show_time(foo)

def foo():

"""foo有参数的情况"""

print("foo")

time.sleep(2)

foo()

Now 给装饰器加一个参数.

import time

def outer(flag):

def show_time(f):

def inner(*args,**kwargs):

start = time.time()

f(*args,**kwargs)

end=time.time()

print(end - start)

if flag:

print("flag为真")

else:

print("flag为假")

return inner

return show_time

@outer(" ")

def foo():

"""foo有参数的情况"""

print("foo")

time.sleep(2)

foo()

<![if !vml]>

<![endif]>

     

<![if !supportLists]>五.   <![endif]>

关于Python的装饰器的更多相关文章

  1. Python各式装饰器

    Python装饰器,分两部分,一是装饰器本身的定义,一是被装饰器对象的定义. 一.函数式装饰器:装饰器本身是一个函数. 1.装饰函数:被装饰对象是一个函数 [1]装饰器无参数: a.被装饰对象无参数: ...

  2. Python札记 -- 装饰器补充

    本随笔是对Python札记 -- 装饰器的一些补充. 使用装饰器的时候,被装饰函数的一些属性会丢失,比如如下代码: #!/usr/bin/env python def deco(func): def ...

  3. python基础——装饰器

    python基础——装饰器 由于函数也是一个对象,而且函数对象可以被赋值给变量,所以,通过变量也能调用该函数. >>> def now(): ... print('2015-3-25 ...

  4. 【转】详解Python的装饰器

    原文链接:http://python.jobbole.com/86717/ Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现 ...

  5. 两个实用的Python的装饰器

    两个实用的Python的装饰器 超时函数 这个函数的作用在于可以给任意可能会hang住的函数添加超时功能,这个功能在编写外部API调用 .网络爬虫.数据库查询的时候特别有用 timeout装饰器的代码 ...

  6. python 基础——装饰器

    python 的装饰器,其实用到了以下几个语言特点: 1. 一切皆对象 2. 函数可以嵌套定义 3. 闭包,可以延长变量作用域 4. *args 和 **kwargs 可变参数 第1点,一切皆对象,包 ...

  7. 理解Python中的装饰器//这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档

    转自:http://www.cnblogs.com/rollenholt/archive/2012/05/02/2479833.html 这篇文章将python的装饰器来龙去脉说的很清楚,故转过来存档 ...

  8. python基础—装饰器

    python基础-装饰器 定义:一个函数,可以接受一个函数作为参数,对该函数进行一些包装,不改变函数的本身. def foo(): return 123 a=foo(); b=foo; print(a ...

  9. 详解Python的装饰器

    Python中的装饰器是你进入Python大门的一道坎,不管你跨不跨过去它都在那里. 为什么需要装饰器 我们假设你的程序实现了say_hello()和say_goodbye()两个函数. def sa ...

  10. 关于python的装饰器(初解)

    在python中,装饰器(decorator)是一个主要的函数,在工作中,有了装饰器简直如虎添翼,许多公司面试题也会考装饰器,而装饰器的意思又很难让人理解. python中,装饰器是一个帮函数动态增加 ...

随机推荐

  1. 大数据量.csv文件导入SQLServer数据库

    前几天拿到了一个400多M的.csv文件,在电脑上打开要好长时间,打开后里面的数据都是乱码.因此,做了一个先转码再导入数据库的程序.100多万条的数据转码+导入在本地电脑上花了4分钟,感觉效率还可以. ...

  2. C语言-统计数字、字母、特殊字符

    Action() { //统计字符019aBcd8***,4,4,3 int i,z,t; char *str="019aBcd8***"; fun_Count(str,i,z,t ...

  3. CorelDRAW教程:怎样绘制制作箭头流程图?

    箭头流程图主要由矢量图和连接符组成,通过图形之间的顺序阐述的一个过程,应用也是非常广泛,有些软件中会自带流程图,对于CDR这款矢量绘图软件来说,手动制作流程图是简单且高效的.首先CorelDRAW中就 ...

  4. 第十一章 Python之异常处理

    异常 异常时程序运行时发生错误的信号(在程序错误时,则会产生一个异常,若程序没有处理,则会抛出该异常,程序的运行也随之终止) 常见的异常类型AttributeError 试图访问一个对象没有的树形,比 ...

  5. JavaScript中必记英语单词及含义

    reflow[ri'flo]:回流,重构(通过css改变页面的结构,比如一行元素,其中一个元素的高改变了,那么其他元素的位置也都会改变) repaint['ripent]:重绘(只改变页面的样式,比如 ...

  6. 安装Oracle 12c及解决遇到的问题

    一.[INS-30131]执行安装程序验证所需的初始设置失败(原因:无法访问临时位置) 原文链接:https://blog.csdn.net/u013388049/article/details/85 ...

  7. 为什么密信MeSince采用S/MIME加密?

    S/MIME是Secure/Multipurpose Internet Mail Extensions (安全多用途互联网邮件扩展协议)的缩写,是采用PKI技术的用数字证书给邮件主题签名和加密的国标标 ...

  8. php 密码hash加密

    做密码加密,记录一下. password_hash 函数在 PHP 5.5 时被引入. 此函数现在使用的是目前 PHP 所支持的最强大的加密算法 BCrypt .例子: $passwordHash = ...

  9. UVALive-8077 Brick Walls 找规律

    题目链接:https://cn.vjudge.net/problem/UVALive-8077 题意 有一个用砖头磊起来的墙,现在又有一只蚂蚁,想沿着砖缝从起点跑到终点. 问最短路长度. 思路 找规律 ...

  10. df与du查看磁盘空间使用不一致的解决方法

    近一段时间,某台服务器的磁盘空间使用不太正常,与其他的服务器相比,严重超出磁盘空间使用 使用df与du相关命令查看,具体结果如下: du -hFilesystem       Size  Used A ...