在编程中,闭包(Closure)是指一种函数对象,它可以访问其自身范围(词法作用域)之外的变量。换句话说,闭包允许函数访问其创建时所在的词法作用域中的变量,即使在函数执行完毕后,这些变量仍然可以被访问。
闭包通常发生在嵌套函数中。一个函数定义在另一个函数的内部,并且内部函数引用了外部函数的变量,这样的结构就形成了闭包。闭包具有以下特点:
词法作用域(Lexical Scope): 闭包允许内部函数访问外部函数的词法作用域中的变量,即使外部函数已经执行完毕。
持久性: 闭包中的变量在外部函数执行完后仍然保持活动状态,因为内部函数引用了这些变量。
下面是一个简单的例子,演示了 JavaScript 中的闭包:
function outerFunction() {
let outerVariable = "I am from the outer function";
// 内部函数形成闭包,可以访问外部函数的变量
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
// 调用外部函数,得到内部函数
let closureFunction = outerFunction();
// 执行内部函数,它可以访问外部函数的变量
closureFunction(); // 输出: I am from the outer function
在这个例子中,innerFunction
是一个闭包,它引用了外部函数 outerFunction
中的 outerVariable
。即使 outerFunction
执行完毕,我们仍然可以通过调用 closureFunction
来访问 outerVariable
。
闭包在许多编程语言中都存在,并且在函数式编程和一些设计模式中经常被使用。在使用闭包时,需要注意内存管理,确保不会造成不必要的内存泄漏。
"""
演示Python的闭包特性
"""
# 简单闭包
# def outer(logo):
#
# def inner(msg):
# print(f"<{logo}>{msg}<{logo}>")
#
# return inner
#
#
# fn1 = outer("黑马程序员")
# fn1("大家好")
# fn1("大家好")
#
# fn2 = outer("传智教育")
# fn2("大家好")
# 使用nonlocal关键字修改外部函数的值
# def outer(num1):
#
# def inner(num2):
# nonlocal num1
# num1 += num2
# print(num1)
#
# return inner
#
# fn = outer(10)
# fn(10)
# fn(10)
# fn(10)
# fn(10)
# 使用闭包实现ATM小案例
def account_create(initial_amount=0):
def atm(num, deposit=True):
nonlocal initial_amount
if deposit:
initial_amount += num
print(f"存款:+{num}, 账户余额:{initial_amount}")
else:
initial_amount -= num
print(f"取款:-{num}, 账户余额:{initial_amount}")
return atm
atm = account_create()
atm(100)
atm(200)
atm(100, deposit=False)
优点,使用闭包可以让我们得到:
缺点:
nonlocal
关键字的作用nonlocal
声明这个外部变量在编程中,装饰器(Decorator)是一种可以用于修改或扩展函数、方法或类行为的特殊语法。装饰器允许在不修改源代码的情况下,动态地添加或修改函数的功能。在许多编程语言中,装饰器通常以 @
符号加上装饰器函数或类的形式使用。
下面是一个简单的 Python 装饰器的例子:
def my_decorator(func):
def wrapper():
print("Something is happening before the function is called.")
func()
print("Something is happening after the function is called.")
return wrapper
@my_decorator
def say_hello():
print("Hello!")
# 调用被装饰的函数
say_hello()
在这个例子中,my_decorator
是一个装饰器函数,它接受一个函数作为参数,并返回一个新的函数 wrapper
。通过使用 @my_decorator
语法,我们将 say_hello
函数传递给装饰器,从而将它装饰起来。当调用 say_hello()
时,实际上是调用了装饰后的 wrapper
函数,从而实现了在函数执行前后添加额外功能的效果。
Python 中还有一些内置的装饰器,例如 @property
、@staticmethod
、@classmethod
等,它们用于定义属性、静态方法和类方法。同时,Python 也支持同时应用多个装饰器,它们按照从上到下的顺序进行嵌套。
装饰器在代码重用和模块化方面提供了一种灵活而强大的机制,它使得我们可以通过简单地添加装饰器来改变函数或类的行为,而不必修改其原始实现。
装饰器其实也是一种闭包, 其功能就是在不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。
"""
演示装饰器的写法
"""
# 装饰器的一般写法(闭包)
# def outer(func):
# def inner():
# print("我睡觉了")
# func()
# print("我起床了")
#
# return inner
#
# def sleep():
# import random
# import time
# print("睡眠中......")
# time.sleep(random.randint(1, 5))
#
# fn = outer(sleep)
# fn()
# 装饰器的快捷写法(语法糖)
def outer(func):
def inner():
print("我睡觉了")
func()
print("我起床了")
return inner
@outer
def sleep():
import random
import time
print("睡眠中......")
time.sleep(random.randint(1, 5))
sleep()
语法糖(Syntactic Sugar)是指一种编程语言的语法特性,它并不提供新的功能,而是用更简洁、更易读的语法形式来表达已有的语法结构。语法糖的目的是提高代码的可读性和易用性,使得开发者能够更加方便地书写和理解代码。
以下是一些编程语言中常见的语法糖例子:
列表推导式(List Comprehensions):
# 传统方式
squares = []
for x in range(10):
squares.append(x**2)
# 使用列表推导式
squares = [x**2 for x in range(10)]
条件表达式(Ternary Operator):
# 传统方式
if x > 0:
y = 1
else:
y = 0
# 使用条件表达式
y = 1 if x > 0 else 0
匿名函数(Lambda Expressions):
# 传统方式
def square(x):
return x**2
# 使用匿名函数
square = lambda x: x**2
解构赋值(Destructuring Assignment):
# 传统方式
x = (1, 2, 3)
a = x[0]
b = x[1]
c = x[2]
# 使用解构赋值
a, b, c = (1, 2, 3)
字符串格式化(String Formatting):
# 传统方式
name = "Alice"
age = 30
message = "Hello, {}! You are {} years old.".format(name, age)
# 使用字符串格式化语法糖
message = f"Hello, {name}! You are {age} years old."
语法糖并不是一种新的语言特性,而是对已有特性的更友好的表达方式。它使得代码更加简洁、清晰,提高了开发效率。然而,使用语法糖时也需要注意不要过度使用,以免影响代码的可读性。