python和golang对比系列(二)

python和golang对比系列(二)–> 参数传递方式

在编程语言深入讨论中,经常被大家提起也是争论最多的讨论之一就是按值(by value)还是按引用传递(by reference, by pointer)

一、golang中的参数传递

在golang中,严格意义上来说,只有一种传递方式,那就是按值传递,即在函数内部修改传入参数的值时函数外部传入值的拷贝,传入时发生了复制行为。无论是变量本身或者是将变量当做指针被传递,都是创建一个副本(值的副本或者是一个指向该变量的指针的副本),T类型的变量和*T类型的变量在当做函数或者方法的参数时会传递它的副本。
如果要想实现和使用按引用传递,则需要将传入的参数设置为指针类型;可以看起来达到按引用传递的效果,实际还是按值传递的。

传递方式数据类型
值传递int、float、bool、string、数组、结构体
引用传递指针、切片、map、管道、接口

1.1 如何选择T*T

在定义函数和方法的时候,作为一位资深的Go开发人员,一定会对函数的参数和返回值定义成T和T深思熟虑,有些情况下可能还会有些苦恼。
那么什么时候才应该把参数定义成类型T,什么情况下定义成类型
T呢。

一般的判断标准是看副本创建的成本和需求。

  1. 不想变量被修改。 如果你不想变量被函数和方法所修改,那么选择类型T。相反,如果想修改原始的变量,则选择*T
  2. 如果变量是一个大的struct或者数组,则副本的创建相对会影响性能,这个时候考虑使用*T,只创建新的指针,这个区别是巨大的
  3. (不针对函数参数,只针对本地变量)对于函数作用域内的参数,如果定义成T,Go编译器尽量将对象分配到栈上,而*T很可能会分配到对象上,这对垃圾回收会有影响

1.2 发生副本创建的情形

  1. 对变量的赋值
  2. slice,map和数组在初始化和按索引设置时
  3. for-range循环
  4. 往channel中send对象时
  5. 函数参数和返回值
  6. 方法Receiver

1.3 不同类型的副本创建

  1. bool,数值和指针
    对象很小,创建副本的开销可以忽略
  2. 数组
    对于大的数组的参数传递和赋值,一定要慎重
  3. map、slice 和 channel
    指向指针类型,指向一个底层的数据结构
  4. 字符串
    大部分情况下你不需要定义成*string。唯一的例外你需要 nil值的时候。"“和nil表示的意义是不一样的,”"表示字段存在,只不过字符串是空值,而nil表示字段不存在。
  5. 函数
    指针类型

二、python中的参数传递

python的函数调用到底是传值还是传引用?

2.1 python的变量内存模型

对于python而言,一切皆对象,python为每个对象分配内存空间,但是并非为每个变量分配内存空间,因为在python中,变量更像是一个标签,就像在现实生活中,一个人可以有多种身份标签,比如:XX的父亲,XX的儿子,XX的工程师,X地志愿者等等,但对应的实体都是同一个人,只占同一份资源。

2.2 python的间接引用机制

类型对象
可变类型列表,字典
不可变类型int、float、字符串、元组

2.3 python传参时可变类型和不可变类型的区别

  1. 在参数传递时,实参将标签复制给了形参,这个时候形参和实参都是指向同一个对象。
  2. 在函数内修改形参:
    2.1 对于不可变类型变量而言:因为不可变类型变量特性,修改变量需要新创建一个对象,形参的标签转而指向新对象,而实参没有变
    2.2 对于可变类型变量而言,因为可变类型变量特性,直接在原对象上修改,因为此时形参和实参都是指向同一个对象,所以,实参指向的对象自然就被修改了。

这种机制存在于整个python环境中,而不仅仅是参数传递中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值