python函数与装饰器
一、名字空间与作用域
1.名字空间
名字空间:赋值语句创建了约束,用来存储约束的dict被称为名字空间
赋值语句的行为:1.分别在堆和栈中创建obj与name
2.将obj与name进行绑定
注:具有赋值行为的语句均可以称为赋值语句,如class A(),def a(),import a等
名字空间的划分:local、global、builtin(用来存储module层次的约束)
2.名字空间的可见性
a = 1
def func():
print a #UnbundlocalError
a = 2
print a #
作用域:约束的作用域仅仅由源程序的文本决定,而不是在运行时动态决定的。因此,python具有静态作用域。
作用域与名字空间的关系:作用域在静态时已决定了名字空间中的name,但name所对应的obj在动态时决定。
注:1、变量能否访问由是否处于同一作用域决定(编译时处理),访问所得值在运行时确定。
2、由一个赋值语句引用的名字在这个赋值语句所在的作用域里是可见的,与代码顺序无关。
3.嵌套规则
LGB:由赋值语句引进的名字在这个赋值语句的内部嵌套的作用域内都是可见的,除非内部作用域中有相同的名字将其屏蔽。
LEGB:
a = 1
def func():
a = 2
def l():
print a
return l
f = func()
f() #输出结果为2
闭包:a = 2,def l均处于func内的同一作用域中,执行f = func()时会将其进行捆绑,并将捆绑后的结果返回。这个捆绑起来的整体即为闭包。
二、函数
1.函数对象的实现 ———— PyFuncionObject
PyFuncionObject:python运行时动态产生,即执行def语句时创建。在PyFunctionObject中储存着函数运行时所需的动态信息。
注:每调用一次函数就会创建一个PyFunc,因为函数调用时具有不同的上下文环境。
2.函数实现上的分离
def func():
a = 1
def f():
print a
return f
func()()
对于def f(),在虚拟机中其声明与实现是分离的。声明是在func函数名字空间中的一条约束,而函数体则是一个绑定了上下文信息的PyFunc
函数的参数传递机制:根据参数对象为可变对象还是不可变对象来表现为值传递还是地址传递。
参数种类:参数种类多达5种。分别为必选参数、默认参数、可变参数、命名关键字参数和关键字参数,在参数列表中的位置也需要如此。对于任意函数,都可以通过类似func(*args, **kw)的形式调用它。
三、装饰器
1、原理:
最内嵌套作用域规则(LGB)
2、实现:
最简单的装饰器
def f(func):
def g():
print 'g..'
func()
return g @f
def a():
print 'a'
带参数的装饰器
#-*- encoding: utf8 -*- from functools import wraps
import logging def logged(level,name=None,message=None): def decorate(func):
logname = name if name else func.__module__
log = logging.getLogger(logname)
logmsg = message if message else func.__name__ @wraps(func)
def wrapper(*args,**kwargs):
print args
print kwargs
log.log(level,logmsg)
return func(*args,**kwargs)
return wrapper
return decorate @logged(logging.DEBUG)
def add(x,y):
return x + y @logged(logging.CRITICAL,'example')
def spam():
print 'spam' add(3,4) ==> logged(logging.DEBUG)(add)(3,4)
#将函数对象作为参数传进修饰器函数中
#被装饰的函数只是作为参数 在装饰器函数中只返回函数对象使用add()(3,4) 调用也可以
#函数wrapper以外的内容只会在定义被装饰的函数时执行一次,仅wrapper函数内的内容才会随着被装饰的函数的调用而执行。即定义被装饰函数时就已执行logged(logging.DEBUG)(add),以后的每次调用只会执行(3,4)部分 '''
注:1.装饰器函数logged接收装饰器参数,提供闭包时的变量环境装饰器内的函数decorate接收被装饰的函数的对象wrapper函数通过*args,**kwargs接收被装饰函数的参数
2.一层函数一个return,最终返回最底层函数的对象
3.构建了一个两层的闭包环境。内层闭包环境可以访问外层闭包环境,外层闭包环境不可以访问内层
4.通过使用wraps装饰器,可以保证func的元数据不变
'''
注:1、闭包用于绑定运行时环境。
2、装饰器用于对函数重新进行封装,在函数执行前后添加操作。
python函数与装饰器的更多相关文章
- Python函数06/装饰器
Python函数06/装饰器 目录 Python函数06/装饰器 内容大纲 1.装饰器 1.1 开放封闭原则 1.2 装饰器 2.今日练习 内容大纲 1.装饰器 1.装饰器 1.1 开放封闭原则 扩展 ...
- python——函数之装饰器
1 问题 实际生活中,我们很难一次性就把一个函数代码写得完美无缺.当我们需要对以前的函数添加新功能时,我们应该怎么做? 2 问题解决思路 (1)可以直接修改原来的函数,在函数内直接修改.当我们对多个函 ...
- python函数、装饰器、迭代器、生成器
目录: 函数补充进阶 函数对象 函数的嵌套 名称空间与作用域 闭包函数 函数之装饰器 函数之迭代器 函数之生成器 内置函数 一.函数补充进阶 1.函数对象: 函数是第一类对象,即函数可以当作数据传递 ...
- Python 函数之装饰器
1.函数 #### 第一波 #### def foo(): print 'foo' foo #表示是函数 foo() #表示执行foo函数 #### 第二波 #### def foo(): print ...
- python函数闭包-装饰器-03
可调用对象 callable() # 可调用的(这个东西加括号可以执行特定的功能,类和函数) 可调用对象即 callable(对象) 返回为 True 的对象 x = 1 print(cal ...
- Python函数的装饰器修复技术(@wraps)
@wraps 函数的装饰器修复技术,可使被装饰的函数在增加了新功能的前提下,不改变原函数名称,还继续使用原函数的注释内容: 方便了上下文环境中不去更改原来使用的函数地方的函数名: 使用方法: from ...
- Python函数的装饰器修复技术(@wraps)
@wraps 函数的装饰器修复技术,可使被装饰的函数在增加了新功能的前提下,不改变原函数名称,还继续使用原函数的注释内容: 方便了上下文环境中不去更改原来使用的函数地方的函数名: 使用方法 from ...
- Python函数加工厂-装饰器
引言: 函数和装饰器好比程序界的加工厂: 1.函数一般可用来加工一种或者多种数据类型的数据:字符串.数字.列表.字典等 举一个简单例子:已知半径求面积 def s(r): s = 3.14 * r * ...
- Python函数的装饰器
函数的装饰器. 1. 装饰器 开闭原则: 对功能的扩展开放 对代码的修改是封闭 通用装饰器语法: def wrapper(fn): def inner(*args, **kwargs): # 聚合 & ...
- python 函数之装饰器,迭代器,生成器
装饰器 了解一点:写代码要遵循开发封闭原则,虽然这个原则是面向对象开发,但也适用于函数式编程,简单的来说,就是已经实现的功能代码不允许被修改但 可以被扩展即: 封闭:已实现功能的代码块 开发:对扩张开 ...
随机推荐
- tomcat服务器虚拟目录的映射方式
lWEB应用程序指供浏览器问的程序,通常也简称为web应用 l l一个web应用由多个静态web资源和动态web资源组成,如: •html.css.js文件 •jsp文件.servlet程序.支持ja ...
- 【一天一道LeetCode】#121. Best Time to Buy and Sell Stock
# 一天一道LeetCode 本系列文章已全部上传至我的github,地址:ZeeCoder's Github 欢迎大家关注我的新浪微博,我的新浪微博 欢迎转载,转载请注明出处 (一)题目 Say ...
- 解决 RtlCreateActivationContext() failed 0xc000000d
gtest 示例的Debug版启动报错: Debug输出如下: 'sample1_unittest.exe': Loaded 'D:\LibSrc\gtest_1.7.0_build\Debug\sa ...
- [asp.net]登录协同工作平台安全解决方案
[摘要]公司领导说登录验证的安全性如何保证,建议采用UKEY验证类似网银解决,调用第三方YT公司产品. 解决方案: 前端页面: <embed id="s_simnew61" ...
- Dynamics CRM OData 查询超过50条记录的数据(Retrieving More than 50 records using OData)
在通过ODdata方式获取CRM数据时,默认查询出来的results只有50条数据,可以通过JSON返回的Object中的"_next"属性作为URL循环获取直到该属性为空 示例代 ...
- 03_TortoiseGit冲突和补丁演示,补丁冲突
1 下载TortoiseGit,下载地址: http://tortoisegit.soft32.com/free-download/ 2 创建一个GIT仓库 3 创建克隆,创建两个用于克隆的仓库 ...
- 【linux学习笔记】在ubuntu下使用QT Cmake支持C++11
今天在ubuntu下使用QT来进行C++编程,选择了Cmake,当用到initializer_list的时候提示不支持C++11,现提供一下解决方案: 错误提示: error: This file r ...
- SpriteBuilder中的粒子系统属性
一个粒子发射器可以有2种模式,放射状和重力的(radial or gravity) 放射状模式允许你去使用发射器创建粒子旋涡状环绕在指定位置的效果. 当启用重力效果,你可以使得粒子在任何方向任意飞行, ...
- jQuery的ajax使用
一:jQuery.ajax语法基础 jQuery.ajax([options]) 概述:通过 HTTP 请求加载远程数据. jQuery 底层 AJAX 实现.简单易用的高层实现见 $.get, $. ...
- SpriteBuilder中频繁的切换场景层的解决办法
注意,不像SettingsLayer,CCScrollView实例并没有从场景中删除和重新加载像代码所示的那样. 你只是简单的改变其可视(visible)状态on和off. 改变可视状态比加载CCB或 ...