热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

python学习整理

Python-copy()与deepcopy()区别—–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来

 —–我们寻常意义的复制就是深复制,即将被复制对象完全再复制一遍作为独立的新个体单独存在。所以改变原有被复制对象不会对已经复制出来的新对象产生影响。 
—–而浅复制并不会产生一个独立的对象单独存在,他只是将原有的数据块打上一个新标签,所以当其中一个标签被改变的时候,数据块就会发生变化,另一个标签也会随之改变。这就和我们寻常意义上的复制有所不同了。

对于简单的 object,用 shallow copy 和 deep copy 没区别

复杂的 object, 如 list 中套着 list 的情况,shallow copy 中的 子list,并未从原 object 真的「独立」出来。也就是说,如果你改变原 object 的子 list 中的一个元素,你的 copy 就会跟着一起变。这跟我们直觉上对「复制」的理解不同。

Python 存储变量的方法跟其他 OOP 语言不同。它与其说是把值赋给变量,不如说是给变量建立了一个到具体值的 reference。

当在 Python 中 a = something 应该理解为给 something 贴上了一个标签 a。当再赋值给 a 的时候,就好象把 a 这个标签从原来的 something 上拿下来,贴到其他对象上,建立新的 reference。

copy对于一个复杂对象的子对象并不会完全复制,什么是复杂对象的子对象呢?就比如序列里的嵌套序列,字典里的嵌套序列等都是复杂对象的子对象。对于子对象,python会把它当作一个公共镜像存储起来,所有对他的复制都被当成一个引用,所以说当其中一个引用将镜像改变了之后另一个引用使用镜像的时候镜像已经被改变了。

deepcopy的时候会将复杂对象的每一层复制一个单独的个体出来。 

上下文管理器(Context Manager)/with关键字

写代码时,我们希望把一些操作放到一个代码块中,这样在代码块中执行时就可以保持在某种运行状态,而当离开该代码块时就执行另一个操作,结束当前状态;所以,简单来说,上下文管理器的目的就是规定对象的使用范围,如果超出范围就采取“处理”。 

首先我们来看一段未使用上下文管理器的代码,看看它在运行过程中会出现什么问题?

#when without using context manager
f = open("hl.txt", "w")
print(f.closed)  #运行到这里,会打印出False,因为没有关闭
f.write("Hello,context manager!")
f.close()
print(f.closed)  #这里才会打印出True,表示文件关闭

如果这段代码根本执行不到f.close()这一句,是不是就出现问题了,假设我们在写入的过程中,磁盘满了,代码就会在写入的那一句出现异常,这样就永远执行不到f.close()这一句,文件就永远不会被关闭,可能你会说我可以用try…finally语句啊,不就解决这个问题了么,但是同样会有问题在里面。 
问题就在于,当我们执行的不是简单的写入操作,而是其他更复杂的操作,如拷贝,同时读和写,这时你会看到try…finally语句根本无法保证代码的美感,简直太糟糕。。所以,上下文管理器就派上用场了,它可以保证不论何时,你的代码都是美观的且安全的。 

使用了上下文管理器的情况:

#when using context manager
with open("hl.txt","w") as f:
    print(f.closed)  #False
    f.write("Hello,context manager!")
print(f.closed)  #True 无需执行f.close()

with关键词总是伴随着上下文管理器出现,as关键词将open(“hl.txt”,”w”)赋给了新的对象f,使得在该代码块中可以对f执行任意操作,代码相当简洁。

自定义上下文管理器

想要作为上下文管理器,还需要做一些工作,即需要实现两个方法:_enter_()和_exit_(); 
_enter_():负责进入代码块的准备工作,进入前被调用; 
_exit_():负责离开代码块的善后工作,离开后被调用;

 因此,一个Python类,只要实现了上述两种方法,就可以说是一个上下文管理器。

class  FileRead(object):

    def __init__(self,filename,read_method=w):
       self.obj = file(filename,read_method)

    def __enter__():
       return self.obj

    def __exit__():
       self.obj.close()



with FileRead(test.txt) as f:
    f.write(s)

yield关键字

用于迭代

Python yield 使用浅析

斐波那契数列

def fab(max): 
    n, a, b = 0, 0, 1 
    while n < max: 
        yield b 
        # print b 
        a, b = b, a + b 
        n = n + 1 

调用:

>>> for n in fab(5): 
...     print n 

简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行 fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。

也可以手动调用 fab(5) 的 next() 方法(因为 fab(5) 是一个 generator 对象,该对象具有 next() 方法)

>>> f = fab(5) 
>>> f.next() 
1 
>>> f.next() 
1 
>>> f.next() 
2 
>>> f.next() 
3 
>>> f.next() 
5 
>>> f.next() 
Traceback (most recent call last): 
 File "", line 1, in  
StopIteration

当函数执行结束时,generator 自动抛出 StopIteration 异常,表示迭代完成。在 for 循环里,无需处理 StopIteration 异常,循环会正常结束。

我们可以得出以下结论:

一个带有 yield 的函数就是一个 generator,它和普通函数不同,生成一个 generator 看起来像函数调用,但不会执行任何函数代码,直到对其调用 next()(在 for 循环中会自动调用 next())才开始执行。虽然执行流程仍按函数的流程执行,但每执行到一个 yield 语句就会中断,并返回一个迭代值,下次执行时从 yield 的下一个语句继续执行。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。

yield 的好处是显而易见的,把一个函数改写为一个 generator 就获得了迭代能力,比起用类的实例保存状态来计算下一个 next() 的值,不仅代码简洁,而且执行流程异常清晰。

在python 3.x中, next()应当替换为__next__()

python学习整理


推荐阅读
  • 利用Cookie实现用户登录状态的持久化
    本文探讨了如何使用Cookie技术在Web应用中实现用户登录状态的持久化,包括Cookie的基本概念、优势及主要操作方法,并通过一个简单的Java Web项目示例展示了具体实现过程。 ... [详细]
  • 本文介绍了一个基本的同步Socket程序,演示了如何实现客户端与服务器之间的简单消息传递。此外,文章还概述了Socket的基本工作流程,并计划在未来探讨同步与异步Socket的区别。 ... [详细]
  • 本文详细介绍了PHP中的几种超全局变量,包括$GLOBAL、$_SERVER、$_POST、$_GET等,并探讨了AJAX的工作原理及其优缺点。通过具体示例,帮助读者更好地理解和应用这些技术。 ... [详细]
  • 使用 ModelAttribute 实现页面数据自动填充
    本文介绍了如何利用 Spring MVC 中的 ModelAttribute 注解,在页面跳转后自动填充表单数据。主要探讨了两种实现方法及其背后的原理。 ... [详细]
  • 使用REM和媒体查询实现响应式布局
    本文介绍如何利用REM单位和媒体查询(Media Queries)来创建适应不同屏幕尺寸的网页布局。通过具体示例,展示在不同屏幕宽度下如何调整页面元素的样式。 ... [详细]
  • 使用IntelliJ IDEA高效开发与运行Shell脚本
    本文介绍了如何利用IntelliJ IDEA中的BashSupport插件来增强Shell脚本的开发体验,包括插件的安装、配置以及脚本的运行方法。 ... [详细]
  • ED Tree HDU4812 点分治+逆元
    这道题非常巧妙!!!我们进行点分治的时候,算出当前子节点的所有子树中的节点,到当前节点节点的儿子节点的距离,如下图意思就是当前节点的红色节点,我们要求出红色节点的儿子节点绿色节点, ... [详细]
  • IIS6批量添加主机头,修改IIS数据库
    首先,找到IIS的数据库。默认是在C:\WINDOWS\system32\inetsrv下的MetaBase.xml文件。如果找不到,请右键右键站点-》所有服务-》将配置保存到一个 ... [详细]
  • 本文深入分析了在使用JavaScript中的Date.UTC()方法初始化Date对象时,getDay()方法返回值与预期不符的原因,并提供了相应的解决方案。 ... [详细]
  • 探索OpenWrt中的LuCI框架
    本文深入探讨了OpenWrt系统中轻量级HTTP服务器uhttpd的工作原理及其配置,重点介绍了LuCI界面的实现机制。 ... [详细]
  • 本文概述了在GNU/Linux系统中,动态库在链接和运行阶段的搜索路径及其指定方法,包括通过编译时参数、环境变量及系统配置文件等方式来控制动态库的查找路径。 ... [详细]
  • 本文详细对比了HashMap和HashTable在多线程环境下的安全性、对null值的支持、性能表现以及方法同步等方面的特点,帮助开发者根据具体需求选择合适的数据结构。 ... [详细]
  • Redis: 高效的键值存储系统
    Redis是一款遵循BSD许可的开源高性能键值存储系统,它不仅支持多种数据类型的存储,还提供了数据持久化和复制等功能,显著区别于其他键值缓存解决方案。 ... [详细]
  • 第1章选择流程控制语句1.1顺序结构的基本使用1.1.1顺序结构概述是程序中最简单最基本的流程控制,没有特定的语法结构,按照代码的先后顺序,依次执行,程序中大多数的代码都是这样执行 ... [详细]
  • SPFA算法详解与应用
    当图中包含负权边时,传统的最短路径算法如Dijkstra不再适用,而Bellman-Ford算法虽然能解决问题,但其时间复杂度过高。SPFA算法作为一种改进的Bellman-Ford算法,能够在多数情况下提供更高效的解决方案。本文将详细介绍SPFA算法的原理、实现步骤及其应用场景。 ... [详细]
author-avatar
mobiledu2502912637
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有