当前位置: 首页 > news >正文

建设部门户网站/理发美发培训学校

建设部门户网站,理发美发培训学校,益阳市住房和建设局 网站,泰安市平台公司刚刚发现 Python 的参数传递机制很有意思,值得专门写个博客记录一下。在 C/C 中,有两种参数传递方式:值传递 (pass by value) 和引用传递 (pass by reference)。值传递:传入函数的实参被复制给该函数的形参。形参是局部变量&#…

刚刚发现 Python 的参数传递机制很有意思,值得专门写个博客记录一下。

在 C/C++ 中,有两种参数传递方式:值传递 (pass by value) 和引用传递 (pass by reference)。

  • 值传递:传入函数的实参被复制给该函数的形参。形参是局部变量,函数运行完成后,这些局部变量的内存被释放,不会影响函数外部实参的值。
  • 引用传递:将实参的地址传入函数中,可以在函数内部直接通过这个地址修改实参。

由于值传递会复制传入的参数,因此形参地址和实参地址是不同的,例如:

#include<stdio.h>int f(int a){printf("In f: &a=%pn", &a);
}int main(){int a = 3;printf("In main: &a=%pn", &a);f(a);return 0;
}
// 运行结果 
// In main: &a=0x7ffefede5954
// In f: &a=0x7ffefede593c

但在 Python 中,参数传递的规则却不太一样:

def f(a):print("In f: id(a)={}".format(id(a)))def main():a = 3print("In main: id(a)={}".format(id(a)))f(a)if __name__=='__main__':main()# 运行结果
# In main: id(a)=94285635591488
# In f: id(a)=94285635591488

f 中的id(a)竟然与 main 中的id(a)是一样的!那在 f 中改变 a 的值,岂不是会影响到 main 中 a 的值吗?(并不会)。

我们进一步发现:当 a 在 f 中没有被改变的时候,f 中的 id(a) 与 main 中的 id(a) 相同,而一旦 f 内部改变了 a 的值,这两个 id 就不同了:

def f(a):print("In f before change: id(a)={}".format(id(a)))a += 1print("In f after change: id(a)={}".format(id(a)))def main():a = 3print("In main before call f: id(a)={}".format(id(a)))f(a)print("In main after call f: id(a)={}".format(id(a)))if __name__=='__main__':main()# 结果
# In main before call f: id(a)=94870107749696
# In f before change: id(a)=94870107749696
# In f after change: id(a)=94870107749728
# In main after call f: id(a)=94870107749696

这一规则,适用于 python 中的所有不可变对象(immutable objects),例如 int, float, bool, string, unicode, tuple 等等一旦被创建,就无法(在原地址上)被修改的对象:

In [1]: a = "hello world"                                                       In [2]: a[0] = "H"                                                              
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-437f77eddd3c> in <module>
----> 1 a[0] = "H"TypeError: 'str' object does not support item assignment

而对于 python 中的可变对象(mutable objects),例如 list, dict, set 以及用户自定义的类,等可以修改其状态的对象,传递规则又有不同:

def f(a):print("In f before change: id(a)={}".format(id(a)))a.append(1)print("In f after change: id(a)={}".format(id(a)))def main():a = [1, 2, 3]print("In main before call f: id(a)={}".format(id(a)))f(a)print("In main after call f: id(a)={}".format(id(a)))if __name__=='__main__':main()# 结果
# In main before call f: id(a)=140263104163584
# In f before change: id(a)=140263104163584
# In f after change: id(a)=140263104163584
# In main after call f: id(a)=140263104163584

我们发现,修改了 list 后,它的 id 并不会改变。类似 C/C++ 中的引用传递,此时在 f 中对 a 做的改变,将影响到 main 中的 a。但这和引用传递也有明显区别,例如在 f 中为 a 赋值一个新的 list,main 中的 a 是不会受到影响的:

def f(a):a = [4, 5]print("In f: a={}".format(a))def main():a = [1, 2, 3]f(a)print("In main: a={}".format(a))if __name__=='__main__':main()# 结果
# In f: a=[4, 5]
# In main: a=[1, 2, 3]

原因是,f 中的 a=[4, 5] 相当于把局部变量 a 绑定了一个新的 list 对象,这个 a 所指向的内存,已经不是 main 中的 a 所指向的那块内存了。由于 list 是可变对象, a.append(5) 并不会开辟一块新的内存,而是会在原内存位置的对象上增加一个元素。

综上,不能简单地将“值传递”或者“引用传递”的概念套用到 Python 中,Python 中的参数传递机制,更类似于“内存传递”。当这块内存存储的是可变对象时,可以直接在它上面做修改;当这块内存存储的是不可变对象时,修改某个变量,本质上并没有修改这块内存的数据,而是开辟了一块新的内存,将新内存赋值给该变量,而旧内存则被垃圾回收了。

http://www.jmfq.cn/news/4826719.html

相关文章:

  • 办一家建筑公司流程/seo chinaz
  • 网站上怎么做弹幕效果/软文案例
  • 网站域名续费多少钱/东莞网站推广运营公司
  • 专业网站制作公司排行/做一个网站要多少钱
  • 长沙网站托管哪家好/广州竞价托管代运营
  • 大连哪家网站技术开发公司好/厦门人才网官网登录
  • 东莞建网站平台/最新实时新闻
  • 网站建设的技术方案/软文案例大全300字
  • wordpress万网安装/网站优化排名怎么做
  • js网站下拉置顶代码/百度网盘网页版登录首页
  • 专业排名优化网站/海阳seo排名
  • 优秀网站建设出售/网上推广赚钱方法
  • 网上商城怎么开发/霸榜seo
  • 开发网站怎样注册公司/seo网站推广的主要目的是什么
  • 杭州网站建设页面/网络营销技巧和营销方法
  • 建设网站后如何做后台/广东清远今天疫情实时动态防控
  • 本地企业网站建设服务/百度学术论文官网入口
  • 服装生产厂商网站建设方案/推广学院seo教程
  • 怎么在网站视频做字幕/班级优化大师怎么用
  • 苏州企业网站制作服务/网站收录申请
  • 网站域名注册信息查询/网络营销和网络推广
  • 一个人做网站现实吗/免费推广产品的平台
  • 网站如何被搜索引擎收录/广州的百度推广公司
  • 阿里巴巴网站做销售方案/郑州seo优化哪家好
  • 想做个网站 怎么做/新手学百度竞价要多久
  • 网站建设实质/百度宁波运营中心
  • 建设 展示型企业网站/杭州网站运营十年乐云seo
  • 没公司怎么做网站/中国2022年重大新闻
  • 旅游网站建站目的/免费做网站的平台
  • 焦作网站建设哪家权威/广告