Python面向对象--函数闭包说起

闭包:嵌套定义在非全局作用域里面的函数,能够记住它被定义时所处的封闭命名空间;
在一个函数内容定义一个函数,在内部的函数可以携带外部函数的信息;这样可以使得函数的组合运用更加的灵活;

我们看一个例子:
def line_conf(a, b):
    # 在函数内部定义了一个函数
    def line(x):
        return a*x+b # 返回值是一个值
    return line #返回值是一个函数

# 测试一下,我们发现这个line_conf可以包装出很多新的函数
    line1 = line_conf(1,1) # 1*x+1
    print(line1)           #<function line_conf.<locals>.line at 0x000002A784E1F400>
    print(line1(5))        # 6

    line2 = line_conf(4,5) # 4*x+5
    print(line2)           # <function line_conf.<locals>.line at 0x000002A784E25400>
    print(line2(5))        # 25

这便是Python函数的闭包特性,使得Python的函数功能非常强大!

我们再来看一个例子,进一步来说明Python 闭包的强大及其带来的Python另一个重要的特性:装饰器

# 用面向对象来写一个简单的坐标处理类
class Coordinate(object):
    
    def __init__(self, x, y):# 构造方法
        self.x = x
        self.y = y
    
    def __repr__(self): # 打印方法,当print时,以一定的格式输出
        return "x: " + str(self.x) + ", y: "+ str(self.y)
 
def add(a, b):
    return Coordinate(a.x+b.x, a.y+b.y)
def sub(a, b):
    return Coordinate(a.x-b.x, a.y-b.y)

# 测试一下代码

    one = Coordinate(100,200)
    two = Coordinate(300,200)
    print(add(one, two))  # 400, 400
    print(sub(one, two))  # -200, 0

这很好理解。

但是,随着新的需求产生,我们可能需要将原来的函数进一步的扩充和增强。

而在软件开发种,有一个很重要的思想:不改变或者尽可能少改变源码,而更多的通过扩充代码,来完成代码功能的增强

比如上面的例子,来了新的需求:要求其坐标不能小于0,否则需要置0

面对这样的问题怎么办?我们来看下解决方案:

# 用面向对象来写一个简单的坐标处理类
class Coordinate(object):
    
    def __init__(self, x, y):# 构造方法
        self.x = x
        self.y = y
    
    def __repr__(self): # 打印方法,当print时,以一定的格式输出
        return "x: " + str(self.x) + ", y: "+ str(self.y)

# 新的需求:坐标不能小于0,否则需要置0

# !!!用一个闭包来扩充原函数的逻辑!!!
def wrapper(func):
    def check(a, b):
        # 在函数调用之前检查参数
        if a.x < 0 or a.y < 0:
            a = Coordinate(a.x if a.x > 0 else 0,
                           a.y if a.y > 0 else 0)
        if b.x < 0 or b.y < 0:
            b = Coordinate(b.x if b.x > 0 else 0,
                           b.y if b.y > 0 else 0)
        ret = func(a,b)
        # 在函数调用之后检查参数
        if ret.x < 0 or ret.y < 0:
            ret = Coordinate(ret.x if ret.x > 0 else 0,
                           ret.y if ret.y > 0 else 0)
        return ret # 这样ret返回的结果一定不会出现负坐标
    return check

@wrapper   # 用装饰器来装饰一下,没有对原逻辑的修改
def add(a, b):
    return Coordinate(a.x+b.x, a.y+b.y)
@wrapper   # 用装饰器来装饰一下,没有对原逻辑的修改
def sub(a, b):
    return Coordinate(a.x-b.x, a.y-b.y)

    one = Coordinate(100,200)
    two = Coordinate(300,200)
    print(add(one, two))  # 400, 400
    print(sub(one, two))  # 0, 0  # 这里的坐标置0

#写代码时,比较好的模式是:可以扩充,但是不要更改已经写好的逻辑!

注意:这个例子中原有的代码没有改变,而功能得以增强。这就是Python中的装饰器,

而也正是我们后面要提的面向对象设计模式中装饰器模式的一种Python实现。

在下一节中,我们可以看一下,在没有语言机制支持时,如何来实现这种设计模式。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值