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 函数之装饰器,迭代器,生成器
装饰器 了解一点:写代码要遵循开发封闭原则,虽然这个原则是面向对象开发,但也适用于函数式编程,简单的来说,就是已经实现的功能代码不允许被修改但 可以被扩展即: 封闭:已实现功能的代码块 开发:对扩张开 ...
随机推荐
- UNIX网络编程——套接字选项(SO_RCVBUF和SO_SNDBUF)
有时候我们需要控制套接字的行为(如修改缓冲区的大小),这个时候我们就要学习套接字选项. int getsockopt(int sockfd,int level,int optname,void *op ...
- eclipse new server Cannot create a server using the selected type 网上有两种办法,其实原理一样
eclipse new server Cannot create a server using the selected type 网上有两种办法,其实原理一样 第一种说法: 还真的找到解决的方法了, ...
- android studio编译慢的问题
1.修改android studio的使用堆内存,根据自己电脑的内存,尽量设置的大一点,点击help->如下图: 2.接下来设置使用离线gradle构建,一开始就是使用了内置的默认路径gradl ...
- 【翻译】如何创建Ext JS暗黑主题之一
原文:How to Create a Dark Ext JS Theme– Part 1 概述 我是不是都要演示我的Spotifinder Ext JS应用程序.它是一个很酷的应用程序,可连接到Las ...
- shell的date
使用方式 : date [-u] [-d datestr] [-s datestr] [--utc] [--universal] [--date=datestr] [--set=datestr] [- ...
- Spring揭秘读书笔记 八 数据访问异常体系
这篇博客 来自spring揭秘一书的第十三章 为什么要有访问异常都有一个体系,这个我们得从DAO模式说起. DAO模式 任何一个系统,不管是一个最简单的小系统,还是大规模的系统,都得跟数据打交道,说白 ...
- 恭喜发财! -- 手把手教你仿造一个qq下拉抢红包 Android自定义view
猴年猴赛雷啊各位,今天没吃药我感觉自己萌萌哒! qq和微信和支付宝红包大战,不知道各位的战绩是多少嘞? 反正我qq抢到的都是气泡.因为太不爽,所以自己写一个下拉抢红包自己玩(自己跟自己玩). 先来看效 ...
- hadoop学习要点
一.HDFS (一)HDFS 概念 (二)HDFS命令行接口 (三)Java 接口 (四)文件读取和文件写入,一致性 (五)集群数据的均衡 (六)存档 (七)NameNode 单点故障问题 (八)大量 ...
- JavaScript进阶(一)抽离公共函数
JS抽离公共函数 问题 在经历了"大量"的项目开发后,发觉越来越多的方法可以被抽离出来作为一个公共方法使用.那么,在js中该思想又该如何实现呢? 解答 例如,以下方法用于实现将标准 ...
- 【一天一道LeetCode】#27. Remove Element
一天一道LeetCode系列 (一)题目 Given an array and a value, remove all instances of that value in place and ret ...