关于python传参引发的一些思考

2023-11-20

人总有不会的,遇到一些问题深究下去必定有所收获

这个问题是在我写python爬虫项目的时候的疑问,可能是我太菜了(以前没学透彻),也可能是上学期学Java的时候按值传递的特点给搞混了,因为当时在用多线程的生产者消费者问题处理资源队列,参考别人代码的时候突然蒙了一下,但后来查了查资料发现原来是下面的原因,值得记录一下坑点,顺便当复习,对语言有个更深入的理解也挺好的

前置的一些知识
  1. 在python里面一切皆为对象,而这个对象分成两种类型,第一种是可变的,另外一种是不可变的。

  2. 按值传递:会在堆中建立一个新的副本,以后操作只对副本操作,对原来主函数里面的值不影响。

    按引用传递:会在堆中建立一个地址的引用,也就是参数的地址,一旦改变这个值就会把主函数里面的变量也会改变。

做一些验证

这里我以参考的代码里面的一部分进行验证,这里用类去类比一下函数,一样的效果,通过id参数打印一下地址

class Consumer(object):
    def __init__(self,page_queue,*args,**kwargs):
        super(Consumer, self).__init__(*args,**kwargs)
        self.page_queue = page_queue
        print(id(self.page_queue))
        
def main():
	page_queue = 1
	print(id(page_queue))
	c = Consumer(page_queue)
    
if __name__ == '__main__':
    main()

输出结果是这样的

140722209422880
140722209422880

可以发现两处的地址是一样的,可以脑补一下图应该是这样的,好像是引用传值,到底是不是这样的呢?

AO7U9f.png

再来一段代码验证

class Consumer(object):
    def __init__(self,page_queue,*args,**kwargs):
        super(Consumer, self).__init__(*args,**kwargs)
        self.page_queue = page_queue
        print(id(self.page_queue))
        self.page_queue += 1
        print(id(self.page_queue))
        print(id(page_queue),page_queue)
        
def main():
	page_queue = 1
	print(id(page_queue))
	c = Consumer(page_queue)

    
if __name__ == '__main__':
    main()       

结果是这个样子的

140722209422880
140722209422880
140722209422912
140722209422880 1

可以发现,以本来引用的常规思路去看的话,这样的操作应该会对同一个地址的东西修改了才对,你会发现,他重新开辟了一个新的空间去容纳新的值,原来传进去的参数没有存在任何影响,脑补一下这个图,现在变成了这样,跟平常的引用是不是有点不一样。

AOHK5q.png

再来看这样一段代码,以队列为例,然后对传进的队列做修改,再观察一下地址内容的改变,查看其是否为空

# -*- coding: utf-8 -*-
# Author:0verWatch

from queue import Queue

class Consumer(object):
    def __init__(self,page_queue,*args,**kwargs):
        super(Consumer, self).__init__(*args,**kwargs)
        self.page_queue = page_queue
        self.page_queue.put(1)   #增加一个值
        print(id(self.page_queue))
        print(id(page_queue),page_queue.empty())

def main():
    page_queue = Queue(100)
    print(id(page_queue))
    print(page_queue.empty())
    c = Consumer(page_queue)

if __name__ == '__main__':
    main()

输出的结果是这个样子的

1519902231520
True
1519902231520
1519902231520 False

可以发现值变化了,地址却没发生变化,明显的引用传参的例子

自己的小结

这里就可以对照一下上面为什么说python对象有两种类型,一种是可变的,另外一种是不可变的,因为在python这个语言中,对于不可变对象的传参例如(tuple,数字,字符)他们一旦发生改变,就会重新在堆里面分配你一块空间,去给变化的值,这也在宏观上给人一种按值传递的错觉,但是这样的机制也优化了python的运行,对于可变的对象的传参例如(list,dict,还有上面提及到的queue类)相当于通过按引用来传递对象。

写代码的时候才发现自己有多菜2333333,大佬们请忽略

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

关于python传参引发的一些思考 的相关文章

  • Python3+Kivy+Plyer 推送通知图标问题

    我在使用 Android 的简单通知测试应用程序时遇到了一个奇怪的错误 错误 python AttributeError type object notification org notificator R drawable has no
  • 在 python 的 Visual Studio 工具中按下 ctrl+F5 后,控制台窗口立即关闭

    我已经安装了 Visual Studio 的 Python 工具 但在控制台窗口中看不到输出 就像我在 Visual Studio 中运行 C 控制台应用程序时按以下快捷键时看到的输出一样 F5 开始调试程序并关闭 C 和 Python 中
  • 在 python 2 和 3 的spyder之间切换

    根据我在文档中了解到的内容 它指出您只需使用命令提示符创建一个新变量即可轻松在 2 个 python 环境之间切换 如果我已经安装了 python 2 7 则 conda create n python34 python 3 4 anaco
  • OpenCV 错误:使用 COLOR_BGR2GRAY 函数时断言失败

    我在使用 opencv 时遇到了一个奇怪的问题 我在 jupyter 笔记本中工作时没有任何问题 但在尝试运行此 Sublime 时却出现问题 错误是 OpenCV错误 cvtColor中断言失败 深度 CV 8U 深度 CV 16U 深度
  • 如何用xlrd读取公式

    我正在尝试做一个解析器 它读取几个 Excel 文件 我通常需要位于行底部的值 您可以在其中找到所有上部元素的总和 因此 单元格值实际上是 sum 或 A5 0 5 可以说 对于使用 Excel 打开此文件的用户来说 它看起来像一个数字 这
  • 使用 Python 抓取维基百科数据

    我正在尝试从以下内容中检索 3 列 NFL 球队 球员姓名 大学球队 维基百科页面 http en wikipedia org wiki 2008 NFL draft 我是 python 新手 一直在尝试使用 beautifulsoup 来
  • 我有一个 Employee 类,我想返回“姓名”列表

    我有一个 Employee 类 我想返回 姓名 列表 雇员 py class Employee object def init self id name members None self id id self name name self
  • 以编程方式将列名称添加到 numpy ndarray

    我正在尝试将列名称添加到 numpy ndarray 然后按名称选择列 但这不起作用 我无法判断问题是在添加名称时出现 还是在稍后尝试调用它们时出现 这是我的代码 data np genfromtxt csv file delimiter
  • 熊猫记忆

    我有冗长的计算 我重复了很多次 因此 我想使用记忆 诸如jug http packages python org Jug and joblib http packages python org joblib memory html 与Pan
  • 如何将同步函数包装在异步协程中?

    我在用着aiohttp https github com aio libs aiohttp构建一个 API 服务器 将 TCP 请求发送到单独的服务器 发送 TCP 请求的模块是同步的 对于我来说是一个黑匣子 所以我的问题是这些请求阻塞了整
  • 如何解码 dtype=numpy.string_ 的 numpy 数组?

    我需要使用 Python 3 解码按以下方式编码的字符串 gt gt gt s numpy asarray numpy string hello nworld gt gt gt s array b hello nworld dtype S1
  • 如何在 Keras 中使用部分输入进行训练,其余部分用于损失函数

    我是 Keras 新手 正在尝试实现神经网络机器学习模型 输入张量看起来像 X1 X2 和输出 Y 注意 X1 和 X2 是相关的 在模型中 只有 X1 将用于训练 但 X1 和 X2 都将传递给损失函数 该损失函数是 X1 X2 y pr
  • 将具有不同大小的行的数据加载到 Numpy 数组中

    假设我有一个包含如下数据的文本文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 如何将它加载到 numpy 数组中 使其看起来像这样 1 2 3 4 5 0 6 7 8 0 0 0 9 1
  • 如何将reportlab与Google应用程序引擎一起使用

    我无法在谷歌应用程序引擎下正确导入reportlab 根据以下guide http blog notdot net 2010 04 Generating PDFs on App Engine Python and introducing M
  • 与函数复合 UniqueConstraint

    一个快速的 SQLAlchemy 问题 我有一个 文档 类 其属性为 数字 和 日期 我需要确保没有重复的号码同年 是 有没有办法对 数字 年份 日期 进行UniqueConstraint 我应该使用唯一索引吗 我如何声明功能部分 SQLA
  • python csv按列转换为字典

    是否可以将 csv 文件中的数据读取到字典中 使得列的第一行是键 同一列的其余行构成列表的值 例如 我有一个 csv 文件 strings numbers colors string1 1 blue string2 2 red string
  • DRF:以编程方式从 TextChoices 字段获取默认选择

    我们的网站是 Vue 前端 DRF 后端 在一个serializer validate 方法 我需要以编程方式确定哪个选项TextChoices类已被指定为模型字段的默认值 TextChoices 类 缩写示例 class PaymentM
  • SpaCy 中的自定义句子边界检测

    我正在尝试在 spaCy 中编写一个自定义句子分段器 它将整个文档作为单个句子返回 我编写了一个自定义管道组件 它使用以下代码来执行此操作here https github com explosion spaCy issues 1850 但
  • 获取运行云功能的运行时服务帐户

    有没有办法以编程方式从云功能获取运行时服务帐户的电子邮件 我知道我可以 猜测 默认的 App Engine 帐户 因为它始终是 appspot gserviceaccount com 但这不是我想要的 我本来期待有一些环境变量 https
  • Python - 打印漂亮的 XML 为空标签文本创建开始和结束标签

    我正在编写一个 python 应用程序 它创建一个 ElementTree XML 然后使用 minidom 的 toprettyxml 将其写入文件 final tree minidom parseString ET tostring r

随机推荐

  • Source insight 4.0 暗色主题,模仿Atom one-darkv配色方案

    我是在MAC OS 10 12下使用crossover安装的 在wine环境下装4 0有个无法解决的bug是toolbar非常的宽 所以我取消了 反正用快捷键可以代替 关于wine安装之后界面模糊的问题请参考我这个帖子http blog c
  • 【UGUI】2D头顶血条制作

    前言 近期因为需要制作玩家和敌人头顶的2D血条 查找了很多博客 发现很多都拘束于Canvas的渲染模式必须要设定为ScreenSpace Overlay 还有应该是版本原因 我的是unity2019 1 11f1 用RecttTransfo
  • json字符串,本地存储讲解localstorage 和 sessionstorage及cookie,模板字符串初识

    这里写目录标题 json字符串 json格式的使用方法 对象的深拷贝狭义实现 localstorage 和 sessionstorage的区别 cookie 封装cookie函数 模板字符串初识 json字符串 abc123truelkgs
  • ElasticSearch基础(7.0+版本)

    一 ElasticSearch的用法 ES是基于Lucene开发的分布式高性能全文检索系统 支持分布式存储 水平扩展 主要能力是 存储 搜索 分析 我目前接触过的主要有两种用法 作为二级索引提高查询效率和基于关键词的全文检索 Lucene
  • 深入ftrace kprobe原理解析

    Linux krpobe调试技术是内核开发者专门为了编译跟踪内核函数执行状态所涉及的一种轻量级内核调试技术 利用kprobe技术 内核开发人员可以在内核的绝大多数指定函数中动态插入探测点来收集所需的调试状态信息而基本不影响内核原有的执行流程
  • 埋点的作用,如何埋点

    通过ThreadLocal和HandlerInterceptor实现java后台业务埋点日志功能 后端开发 埋点日志怎么做 流沙飞雪的博客 CSDN博客 埋点是什么 有什么作用 前端如何埋点 网页埋点 一只小可乐吖的博客 CSDN博客 用户
  • C#系列-继承

    00解释 1 命名空间 可以认为类是属于命名空间的 如果在当前项目中没有这个类的命名空间 需要我们手动的导入这个类所在的 命名空间 1 用鼠标去点 2 alt shift F10 3 记住命名空间 手动的去引用 2 在一个项目中引用另一个项
  • Qt快捷键(常用+非常详细)

    常用高频快捷键 Ctrl 多行注释 取消多行注释 Ctrl B 编译工程 Ctrl R 运行工程 Ctrl Alt up 向上箭头 当前行向上复制 Ctrl Alt down 向下箭头 当前行向下复制 Ctrl Shift up 向上箭头
  • ElasticSearch-快速入门(一)

    ES简介 全文搜索属于最常见的需求 开源的Elasticsearch 是目前全文搜索引擎的首选 它可以快速地储存 搜索和分析海量数据 维基百科 Stack Overflow Github 都采用它 Elastic 的底层是开源库Lucene
  • 每日作业20200525 - 图片相似度 ( 比较两个数组相似程度 )

    题目 图片相似度 输入两个由0和1构成的 3 3的矩形 如果两个矩形同坐标的值相同 则为像素点相同 相似度为两个矩形 相同像素点 总像素点 100 求图片相似度 样例输入 1 0 1 0 0 1 1 1 0 1 1 0 0 0 1 0 0
  • 行走的代码生成器:chatGPT要让谷歌和程序员“下岗”了

    就在本周 OpenAI 又发布了一个全新的聊天机器人模型 ChatGPT 作为 GPT 3 5 系列的主力模型之一 图片来源 OpenAI 更重要的是它是完全免费公开的 所以一经发布大家立刻就玩开了 很快 网友们就被 ChatGPT 的能力
  • vue 资料合集

    div class show content p UI组件 br a href https github com ElemeFE element target blank element a 11612 饿了么出品的Vue2的web UI工
  • virtualbox 网络地址转换(NAT)

    因为个人在工作的时候条件比较充足 基本上不需要用到 virtualbox 或者 vmware 等这些虚拟软件 一个是因为他们占用本机的资源挺大的 电脑配置稍微低点就很难受了 所以说的条件充足是因为我多了一台电脑 这台就被我当作练习使用 用的
  • SpringBoot中实现文件的上传和下载

    文件上传 实现策略 将文件上传到指定路径 并将文件的路径信息存储到数据库中 文件上传前台
  • IDEA如何进行debug调试

    IDEA如何进行debug调试 第一步 设断点 打开debug 第二步 使用Debug调试的功能键 程序调试 相信是所有程序员必经之路 因为程序写出来是不可能没有错误的 当然除了非常简单的一些程序之外 相信大家肯定使用过不同的编译软件 都有
  • Vs2019 社区版 内网登录

    问题概述 1 Vistual Studio Community 是免费版 但需要登陆授权 2 由于办公使用的是内网 也是使用离线下载方法安装的 因此无法联网登陆 解决方法 1 外网打开Vistual Studio Community 201
  • 第二十一章 webpack5原理loader概述

    简介 loader其实是一个函数 用来帮助 webpack 将不同类型的文件转换为 webpack 可识别的模块 loader的分类以及执行顺序 1 分类 pre 前置loader normal 普通loader inline 内联load
  • 编译型语言和解释型语言各自的特点和区别,Python的解释器

    编译型语言和解释型语言各自的特点和区别 Python的解释器 编译型语言 将源代码通过编译器编译生成可执行文件 机器指令 再由机器运行机器码 解释型语言 通过解释器逐行解释每一句源代码 打个比方 编译型相当于用中英文词典 翻译器 将一本英文
  • Vue如何封装组件

    要封装一个 Vue 组件 可以按照以下步骤进行操作 创建一个新的 Vue 单文件组件 vue 文件 并命名为你的组件名 例如 MyComponent vue 在组件文件中 使用
  • 关于python传参引发的一些思考

    人总有不会的 遇到一些问题深究下去必定有所收获 这个问题是在我写python爬虫项目的时候的疑问 可能是我太菜了 以前没学透彻 也可能是上学期学Java的时候按值传递的特点给搞混了 因为当时在用多线程的生产者消费者问题处理资源队列 参考别人