Python里的闭包和AOP

本文介绍了Python中的闭包和装饰器概念,并通过一个具体的示例展示了如何利用这些特性为函数添加额外的功能,如记录执行时间和参数等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

习惯了写Java和JS代码,突然换成Python还真不习惯,最近在书上看到一段挺有意思的Python代码,才真心感觉到Python长盛不衰的价值。在很多语言里,如果在一个内部函数里,对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。定义在外部函数内的但由内部函数引用或者使用的变量被称为自由变量。闭包的词法变量不属于全局或者局部作用域,而属于一种“流量”的作用域。


先介绍一种语法,Python有种叫函数装饰器的东西,这是一种特殊的函数,因为它接受函数对象为参数,对其进行封装加工并返回。举个简单的例子:

@deco(deco_args)
def foo(): pass

#相当于:foo = deco(deco_args) (foo)

装饰器封装了foo,并返回新版本的foo。这其实就是一种闭包的用法,因为无论在deco函数中定义了那些变量,当调用新版本foo的时候都可以访问到它们,那些变量并不随着deco函数的执行结束返回而销毁,而是继续存活在“流量”空间里等待被激活。如果要问这有什么作用?最容易理解的就是对比Java里的AOP概念,在不改变源代码的情况下,织入切面,添加统一的逻辑:打日志、性能指标记录、统一事务管理等等。而在python里面,AOP居然如此之简单,通过函数装饰器和闭包的特性就可以轻易解决。下面这个例子,就是对闭包强大特性的一个体现:(给方法hello添加执行时间的分析,不改动原方法hello的代码)

#!usr/bin/env python

from time import time

def logged(when):
	def log(f, *args, **kargs):
		print '''Called:
function: %s
args: %r
kargs: %r''' % (f,args,kargs)

	def pre_logged(f):
		def wrapper(*args, **kargs):
			log(f, *args, **kargs)
			return f(*args, **kargs)
		return wrapper

	def post_logged(f):
		def wrapper(*args, **kargs):
			now = time()
			try:
				return f(*args, **kargs)
			finally:
				log(f, *args, **kargs)
				print "time delta: %s" % (time()-now)
		return wrapper

	try:
		return {"pre": pre_logged, "post": post_logged}[when]
	except:
		raise ValueError(e), 'must be "pre" or "post"'

@logged("post")
def hello(name):
	print "Hello, ", name

hello("World")

可以看到只是简单的在hello方法前添加了一个函数装饰器,就可以让hello的调用具有分析执行时间的特性,成功的织入切面!我这的执行结果是:

Hello,  World
Called:
function: <function hello at 0x10755aa28>
args: ('World',)
kargs: {}
time delta: 3.88622283936e-05




### Python与Java的关系 PythonJava虽然属于不同的编程范式技术领域,但在某些方面存在一定的联系。两者都具有高级语言的特点,能够通过中间语言(字节码)执行,并且具备强大的生态系统支持社区[^4]。然而,在具体的用途发展方向上,两者的侧重点有所不同。 --- ### 主要区别 #### 1. **语法特性** - **变量声明** Java是一种静态类型语言,所有的变量都需要显式声明其类型后才能使用;而Python则是一种动态类型语言,无需提前声明变量的类型即可直接赋值并使用[^2]。 - **代码结构** Java依赖大括号 `{}` 来界定代码块范围,而Python则是通过缩进的方式表示代码块层次结构[^2]。 - **语句结束符** 在Java中每条语句需要用分号 `;` 结束,而在Python中通常省略分号。 #### 2. **执行方式** - **编译 vs 解释** Java源文件需要经过编译器转换成字节码后再由JVM虚拟机加载运行;相比之下,Python作为解释型语言可以直接被解释器逐行解析执行[^1]。 - **性能表现** 尽管两种语言最终都会转化为某种形式的中间态并通过优化机制提升速度,但由于底层实现差异较大,因此总体而言Java程序运行起来往往比同等条件下仅基于CPython标准库构建出来的Pure-Python应用更加高效[^3][^4]。 #### 3. **开发模式** - **面向对象程度** 虽然二者均支持完整的OOP(Object-Oriented Programming)模型,但Python允许开发者采取更为灵活自由的方式来编写代码——既可以遵循传统意义上的类定义方法论也可以利用闭包、装饰器等功能组件完成相似目标;反观Java,则强制要求任何非匿名内部类成员函数外部访问权限修饰词(public/private/protected/default),并且不允许单独存在的顶级方法(即必须隶属于某个特定类别之下)[^1]. - **框架生态体系对比分析报告摘要如下所示:** 对于Web服务端搭建工作来说,Spring Framework无疑是当前最为流行也是最成熟稳定的一套解决方案之一,它提供了诸如IoC容器控制反转,AOP切面技术等一系列先进理念帮助工程师们简化日常繁琐事务处理过程从而专注于业务逻辑本身的设计实现之上; Django framework 则凭借简洁明快的学习曲线以及高度模块化的插件扩展能力成为众多初创团队首选的技术栈选项[ ^{3} ]. ```python # Python 示例: 使用Django 创建视图控制器 from django.http import HttpResponse def hello_world(request): return HttpResponse("Hello, world!") ``` ```java // Java 示例: Spring Boot 中配置 RESTful API 接口 @RestController @RequestMapping("/api") public class HelloWorldController { @GetMapping("/hello") public String sayHello() { return "Hello, World!"; } } ``` #### 4. **应用场景偏好** - **科学计算&人工智能领域** 鉴于NumPy,Pandas,TensorFlow,Keras等知名开源项目的广泛采纳情况可以看出PYTHON在此方面的统治地位难以撼动; - **企业级软件工程实践指南建议书中提到过多次关于选择合适工具链的重要性论述指出:当涉及到大规模并发请求处理或者是微服务体系架构设计时,JAVA凭借其卓越的线程管理内存分配策略依旧占据主导地位.[^{4}]** --- ### 总结 综上所述,尽管PythonJava之间存在着诸多显著的不同之处,但从长远来看它们并非绝对对立的竞争关系而是互为补充的存在形态。根据实际项目需求合理选用相应技术手段才是明智之举。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值