Python函数参数与返回值

        相信大家对一些编程语言的函数并不陌生,函数式编程的目的一是将程序中反复使用执行的代码封装到一个代码块中并命名,下次使用时不需要再重新书写,直接通过函数名调用执行就可以了,二是将冗长的代码分成一个个函数并赋予对应的功能,增强代码的可读性,但是在这篇文章中我们不谈函数怎么书写,而是更进一步,谈一下函数的进阶。

        1.我们知道很多函数在使用时需要传递参数,那么函数的参数究竟是传递的是什么呢,是他的值吗?接下来我们通过代码来看一下:
        

# 定义一个函数,功能是输出传入的参数的值和地址
def print_data(data):
    print(data, id(data))

# 定义一个字符串对象
name = '杰弟'
# 输出该字符串对象的值和内存地址
print(name, id(name))
# 调用函数
print_data(name)



# >>杰弟 2155157956048
# >>杰弟 2155157956048

                通过代码可以看出,传递的参数data的内存地址和字符串对象指向的内存地址相同,因此我们可以知道函数传递参数实际上传递的是内存地址而不是值

                实际上如果你有看过我上一期的文章就会知道,实际上 name 是一个字符串对象的引用,指向 “杰弟” 这个字符串对象的内存地址,也就是说你把 name 当作参数传递给函数实际上是传递了一个内存地址(传入name,而name指向内存地址)

                那么我们为什么要关注这个点呢,实际上,在python中参数传递内存地址有两个好处,第一个无需多言,就是节省空间,不需要再额外拷贝一份,不需要再开辟空间,第二个,如果在函数内修改可变类型的内容,那么会对传入的可变类型参数本身造成修改,我们举个例子:

# 创建列表对象
lis = [-1, -1, -1, -1, -1]


# 创建函数在列表中添加对象

def lis_append(li):
    li.append(-1)

# 调用函数
lis_append(lis)

# 输出列表lis
print(lis)


# >> [-1, -1, -1, -1, -1, -1]

        我们可以发现原来的列表在函数运行后居然发生了变化,我们来分析一下:

# 创建列表对象
lis = [-1, -1, -1, -1, -1]


# 创建函数在列表中添加对象

def lis_append(li):   # 这里传递的其实是列表 lis 对象的地址,并把传入的地址赋值给 li
    li.append(-1)     # li.append()实际上是在原来的列表 lis 的地址空间增加了一个元素 -1

# 调用函数
lis_append(lis)

# 输出列表lis
print(lis)

                总结:只要传入的是一个可变类型的地址,我们又对这个地址空间内的元素进行了操作,那么原来的可变类型内部元素就会发生改变,其实这里python和其他很多编程语言不同,很多其他编程语言在传递参数之前会将参数拷贝一份再将“复印件”当作参数传递给函数,但是python不是这样,它是直接将‘原件’的内存地址传递给函数。

                那么如何解决这个问题呢,很简单,我们可以在传递之前将原来要传入的值‘拷贝’一份再将“复印件”的地址当作参数传入函数,比如:
 

import copy

lis = [-1, -1, -1, -1, -1]

lis_copy = copy.deepcopy(lis)  # 拷贝lis列表,lis_copy指向‘复印件’对象的地址


def lis_append(li):
    li.append(-1)


lis_append(lis_copy)
print(lis)

# >> [-1, -1, -1, -1, -1]

                现在我们注意到原列表 lis 中的值就不会发生变化了。

        2.讲完了传参我们来讲讲返回值,实际上还是一样的道理,根据“万物皆对象”的原则我们知道,返回值也应该是个对象,所以返回的也应该是一个内存地址,但是为了证明这种观点,附上代码:

lis = [-1, -1, -1, -1, -1]  # 创建一个列表


def return_lis(li):  # 创建一个函数,返回他的参数
    return li


lis_1 = return_lis(lis)  # 将函数的返回值赋值给lis_1(实际上是让lis_1指向返回的这个地址)

if lis is lis_1:  # 如果两个列表地址相同
    print("两个列表地址相同。")  # 输出信息




# >>两个列表地址相同。

                根据输出我们可以知道函数的返回值是一个地址且与传入参数的地址相同,这里可能有同学有疑问,is 关键字我们之前可能没有见过,实际上 is 跟 == 差不多,但是 == 比较的是值是否相同(内存地址可能不同), is 比较的是内存地址是否相同(值一定相同)

       

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值