python基础教程九 抽象二(函数参数)

1. 值从哪里来

定义函数时,你可能心存疑虑,参数的值是怎么来的呢?
在def语句中,位于函数名后面的变量通常称为形式参数,在调用函数时提供的值称为实参,但在本书不做严格区分。

2. 我能修改参数吗

函数通过参数获得了一些列值,你能对其修改吗?如果这样做,结果将如何?参数不过变量而已,行为与你的预期完全相同。在函数内部给参数赋值对外部没有任何影响。

>>> def try_to_change(n):
...  n='sss'
...
>>> name='dsda'
>>> try_to_change(name)
>>> name
'dsda'

在try_to_chage内,将新值赋给了参数n,但如你所见,这对变量name没有影响。说到底这是一个完全不同的变量。

字符串(以及数和元组)是不可变的,这意味这你不能修改它们(即只能替换为新值)。因此这些类型作为参数项没什么可说的。但如果参数为可变的数据结构(如列表呢)

>>> def chage(n):
...     n[0]='cao'
...
>>> names=['haha','end']
>>> chage(names)
>>> names
['cao', 'end']

在上面的示例中,也在函数内修改了参数,但这个示例与前一个示例存在一个重要不同,前一个示例只是给局部变量赋了新值,而在这个示例中修改了变量关联到的列表。这并不奇怪,这次不用函数,再做一次

>>> names=['abc','bscd']
>>> n=names
>>> n[0]='111'
>>> names
['111', 'bscd']

这样的情况你早就见过。将一个列表赋值给俩个变量,这俩个变量将同时指向这个列表就这么简单。要避免这样的结果,必须创建列表的副本。对序列执行切片操作时,返回的切片是副本。因此,如果你创建覆盖整个列表的切片,得到的将是列表的副本

>>> n=names[:]
>>> n
['111', 'bscd']
>>> names is n
False
>>> n==names
True

现在如果修改n,将不会影响names。

>>> n[0]=222
>>> n
[222, 'bscd']
>>> names
['111', 'bscd']

下面来尝试结合使用这种技巧和函数change。

>>> def change(name):
...     name[0]='111'
...
>>> names
['111', 'bscd']
>>> names[0]='2222'
>>> names
['2222', 'bscd']
>>> change(names[:])
>>> names
['2222', 'bscd']

当然copy方法也是可以的

1. 为何要修改参数

在提高程序的抽象程度方面,使用函数来修改数据结构是一种不错的方式。假设你要编写一个程序,让它存储姓名,并让用户能根据名字,中间名或姓找人。为此,你可能使用一个类似下面的数据结构:

>>> storage['first']={}
>>> storage['middle']={}
>>> storage['last']={}
>>>

数据结构storage是一个字典,包含3个键:first,middle和last。在每个键下面存储了一个字典。这些子字典的键为姓名,值为随便瞎写

>>> me='随便瞎写'
>>> storage['first']['magnus']=me
>>> storage['middle']['lie']=me
>>> storage['last']['lie']=me
>>> storage
{'first': {'magnus': '随便瞎写'}, 'middle': {'lie': '随便瞎写'}, 'last': {'lie': '随便瞎写'}}
>>> storage['first']['magnus']
'随便瞎写'

如果我们这里使用函数代替重复的代码,整体将会整洁很多

>>> def init(data):
...     data['first']={}
...     data['middle']={}
...     data['last']={}


>>> def lookup(data,label,name):
...     return data.get(label,{}).get(name,{})

>>> lookup(s,'first','magnus')
'随便瞎写'
>>> lookup(s,'first','magn')
{}

2. 如果参数是不变的

在有些语言,经常需要给参数赋值并让这种参数修改影响函数外部的变量。在python中,没法直接这样做,只能修改参数对象本身。但如果参数是不可变的呢。
不好意思,没办法。在这种情况下,应从函数返回所有需要的值(如果需要返回多个值,就以元组的方式返回它们)。例如,可以像下面这样编写将变量的值加一的函数。

>>> def inc(x): return x+1
...
>>> foo =10
>>> foo=inc(foo)
>>> foo
11

如果一定要修改参数,可玩点花样,比如将值放在列表当中,如下所示:

>>> def ind(x): x[0]+=1
...
>>> foo=[10]
>>> ind(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'x' is not defined
>>> ind(foo)
>>> foo
[11]

但更清晰的解决方案是返回修改后的值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值