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


Posted in Python onOctober 08, 2018

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

子类型的定义取决于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

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

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。如果你想了解更多相关内容请查看下面相关链接

Python 相关文章推荐
python中map()与zip()操作方法
Feb 27 Python
Python脚本简单实现打开默认浏览器登录人人和打开QQ的方法
Apr 12 Python
初学python的操作难点总结(新手必看篇)
Aug 03 Python
Python实现重建二叉树的三种方法详解
Jun 23 Python
vue.js实现输入框输入值内容实时响应变化示例
Jul 07 Python
Python简单过滤字母和数字的方法小结
Jan 09 Python
python视频按帧截取图片工具
Jul 23 Python
Python 求数组局部最大值的实例
Nov 26 Python
在tensorflow中设置使用某一块GPU、多GPU、CPU的操作
Feb 07 Python
django 数据库返回queryset实现封装为字典
May 19 Python
Python 绘制可视化折线图
Jul 22 Python
Python 实现Mac 屏幕截图详解
Oct 05 Python
详解多线程Django程序耗尽数据库连接的问题
Oct 08 #Python
JSON文件及Python对JSON文件的读写操作
Oct 07 #Python
Python实现登陆文件验证方法
Oct 06 #Python
python对日志进行处理的实例代码
Oct 06 #Python
浅析Python函数式编程
Oct 06 #Python
Python实现iOS自动化打包详解步骤
Oct 03 #Python
Python中GIL的使用详解
Oct 03 #Python
You might like
玛琪朵 Macchiato
2021/03/03 咖啡文化
php实现商城购物车的思路和源码分析
2020/07/23 PHP
不间断滚动JS打包类,基本可以实现所有的滚动效果,太强了
2007/12/08 Javascript
javascript while语句和do while语句的区别分析
2007/12/08 Javascript
javascript 单选框,多选框美化代码
2008/08/01 Javascript
node.js中的http.createClient方法使用说明
2014/12/15 Javascript
js遍历map javaScript遍历map的简单实现
2016/08/26 Javascript
js前端实现多图图片上传预览的两个方法(推荐)
2016/11/18 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
2017/05/01 jQuery
详解Nodejs之静态资源处理
2017/06/05 NodeJs
Angular.js ng-file-upload结合springMVC的使用教程
2017/07/10 Javascript
详解Vue组件实现tips的总结
2017/11/01 Javascript
微信小程序日历/日期选择插件使用方法详解
2018/12/28 Javascript
vue中轮训器的使用
2019/01/27 Javascript
浅谈如何优雅处理JavaScript异步错误
2019/11/12 Javascript
Vue解析带html标签的字符串为dom的实例
2019/11/13 Javascript
Jquery高级应用Deferred对象原理及使用实例
2020/05/28 jQuery
python 装饰器功能以及函数参数使用介绍
2012/01/27 Python
python33 urllib2使用方法细节讲解
2013/12/03 Python
python使用正则搜索字符串或文件中的浮点数代码实例
2014/07/11 Python
闭包在python中的应用之translate和maketrans用法详解
2014/08/27 Python
Sanic框架配置操作分析
2018/07/17 Python
Flask框架模板渲染操作简单示例
2019/07/31 Python
pytorch:torch.mm()和torch.matmul()的使用
2019/12/27 Python
音频处理 windows10下python三方库librosa安装教程
2020/06/20 Python
用canvas实现图片滤镜效果附演示
2013/11/05 HTML / CSS
Marmot土拨鼠官网:美国专业户外运动品牌
2018/01/11 全球购物
Made in Design英国:设计家具、照明、家庭装饰和花园家具
2019/09/24 全球购物
中级会计职业生涯规划范文
2014/01/16 职场文书
机电一体化求职信
2014/03/10 职场文书
业务员自荐信范文
2014/04/20 职场文书
PL350与SW11的比较
2021/04/22 无线电
python读取mnist数据集方法案例详解
2021/09/04 Python
实现一个简单得数据响应系统
2021/11/11 Javascript
win10如何开启ahci模式?win10开启ahci模式详细操作教程
2022/07/23 数码科技
Redis过期数据是否会被立马删除
2022/07/23 Redis