Python中的函数式编程:不可变的数据结构

作者:Moshe Zadka 时间:2023-09-05 07:16:35 

让我们首先考虑正方形和长方形。如果我们认为在接口方面,忽略了实现细节,方块是否是矩形的子类型?

子类型的定义取决于Liskov代换原理。为了成为一个子类型,它必须能够完成超级类型所做的一切。

如何定义矩形的接口?


zope.interface import Interface
class IRectangleInterface:
get_length:
"""Squares can do that"""
get_width:
"""Squares can do that"""
set_dimensions length width:
"""Uh oh"""

如果这是定义,则方块不能是矩形的子类型;它们不能响应set_dimensions方法,如果长度和宽度不同。

另一种方法是选择制作矩形。不变.


class IRectangleInterface:
get_length:
"""Squares can do that"""
get_width:
"""Squares can do that"""
with_dimensions length width:
"""Returns a new rectangle"""

现在,一个正方形可以是一个矩形。它可以返回一个新的矩形(通常不是正方形)with_dimensions被称为,但它不会停止成为一个正方形。

这似乎是一个学术问题-直到我们考虑到,从某种意义上说,正方形和长方形是它们两边的容器。在我们理解了这个例子之后,更实际的情况是使用更传统的容器。例如,考虑随机访问数组.

我们有ISquare和IRectangle,和ISquare是IRectangle.

我们希望在随机访问数组中放置矩形:


class IArrayOfRectanglesInterface:
get_element i:
"""Returns Rectangle"""
set_element i rectangle:
"""'rectangle' can be any IRectangle"""

我们也想把正方形放在一个随机存取数组中:


class IArrayOfSquareInterface:
get_element i:
"""Returns Square"""
set_element i square:
"""'square' can be any ISquare"""

即使ISquare是IRectangle,任何数组都不能实现这两者。IArrayOfSquare和IArrayOfRectangle.

为什么不行?假设bucket实现两者。


>>> rectangle make_rectangle
>>> bucket.set_element rectangle # This is allowed by IArrayOfRectangle
>>> thing bucket.get_element # That has to be a square by IArrayOfSquare
>>> assert thing.height thing.width
Traceback most recent call last:
File "<stdin>" line module
AssertionError

两者都不能实现,这意味着两者都不是另一种类型的子类型,尽管ISquare是IRectangle。问题是set_element方法:如果我们有一个只读数组,IArrayOfSquare的子类型IArrayOfRectangle.

可变性,都是可变的。IRectangle接口和可变IArrayOf接口使得对类型和子类型的思考变得更加困难-而放弃的能力意味着我们期望类型之间的直观关系实际上仍然有效。

突变也可以非局部效果。当两个地方之间的共享对象被一个突变时,就会发生这种情况。典型的例子是一个线程与另一个线程交互一个共享对象,但是即使在一个单线程程序中,在相距很远的地方之间共享也很容易。考虑到在Python中,大多数对象都可以从许多地方访问:作为一个模块全局,或者在堆栈跟踪中,或者作为一个类属性。

如果我们不能限制共享,我们可能会考虑限制可变。

下面是一个不可变的矩形,它利用AutoS库:


attr.frozen
class Rectangeobject:
length attr.
width attr.
classmethod
with_dimensionscls length width:
return clslength width

这里是一个正方形:


attr.frozen
class Squareobject:
side attr.
classmethod
with_dimensionscls length width:
return Rectanglelength width

使用frozen参数,我们可以很容易地创建一个不可变的类。所有艰苦的写作工作__setitem__正确的做法是别人做的,对我们来说是完全看不见的。

修改对象仍然是容易的,改变它们几乎是不可能的


too_long Rectangle
reasonable attr.evolvetoo_long length

可靠的包装允许我们有不可变的容器


# Vector of integers
a = pyrsistent.v(1, 2, 3)
# Not a vector of integers
b = a.set(1, "hello")

当b不是整数的向量,任何东西都不会停止。a从成为一个。

万一a一百万个元素长了吗?是b要复制999 999份吗?Pyrsistent附带“大O”性能保证:所有操作都采用O(log n)时间到了。它还附带了一个可选的C扩展,以提高性能超越大O。

为了修改嵌套对象,它附带了“转换器”的概念:


blog pyrsistent.
title"My blog"
linkspyrsistent."github" "twitter"
postspyrsistent.
pyrsistent.title"no updates"
content"I'm busy"
pyrsistent.title"still no updates"
content"still busy"
new_blog blog.transform"posts" "content"
"pretty busy"

new_blog将成为不可变的等价物。


'links': 'github' 'twitter'
'posts': 'content': "I'm busy"
'title': 'no updates'
'content': 'pretty busy'
'title': 'still no updates'
'title': 'My blog'

但blog还是一样的。这意味着任何引用旧对象的人都没有受到影响:转换只有本土化效果。

当分享猖獗时,这是有用的。例如,考虑默认参数:


silly_suma b extrav :
extra extra.extenda b
return extra

在这篇文章中,我们了解了为什么不变性对于思考我们的代码是有用的,以及如何在没有昂贵的性能代价的情况下实现它。

来源:https://opensource.com/article/18/10/functional-programming-python-immutable-data-structures

标签:python,函数式编程,数据结构
0
投稿

猜你喜欢

  • 浅谈数据库日期类型字段设计应该如何选择

    2024-01-21 13:55:21
  • Vue项目如何设置反向代理和cookie设置问题

    2023-07-02 16:39:03
  • python机器学习之决策树分类详解

    2023-04-28 14:31:05
  • python3.6.3安装图文教程 TensorFlow安装配置方法

    2021-06-25 19:20:42
  • Mysql InnoDB删除数据后释放磁盘空间的方法

    2024-01-21 00:36:49
  • 深入浅析Python 中 is 语法带来的误解

    2021-08-23 14:18:17
  • 网站LOGO设计规范的思考--1.设计基础

    2007-10-14 10:55:00
  • 监控 url fragment变化的js代码

    2023-08-25 10:20:58
  • Python用HBuilder创建交流社区APP

    2023-08-27 13:22:19
  • 主流浏览器性能比较

    2009-10-19 14:34:00
  • Orcas中C#语言的新特性:自动属性,对象初始化器,和集合初始化器

    2007-09-23 12:43:00
  • PyGame贪吃蛇的实现代码示例

    2021-04-27 12:09:33
  • Golang学习笔记之安装Go1.15版本(win/linux/macos/docker安装)

    2024-05-13 10:41:23
  • 对PyTorch中inplace字段的全面理解

    2022-11-15 13:52:24
  • sqlserver2005自动创建数据表和自动添加某个字段索引

    2024-01-26 19:37:17
  • 现代Python编程的四个关键点你知道几个

    2023-11-22 02:17:42
  • Python设计模式之MVC模式简单示例

    2023-02-24 16:58:33
  • 恢复.mdf 数据库步骤

    2024-01-16 00:17:35
  • python中set()函数简介及实例解析

    2022-05-15 17:12:24
  • JavaScript在ASP页面中实现掩码文本框效果代码

    2013-06-01 19:57:23
  • asp之家 网络编程 m.aspxhome.com