当前位置:编程学习 > 网站相关 >>

魔法参数(一)

考完试了,还不错,心里挺欣慰的。好了,继续看学习的内容。
函数使用起来简单,创建的时候也不复杂,但是参数的使用却是比较不可思议了。

值从哪里来?
以前我也在经常想这个问题,这么大的一个程序,值是从哪里传进去的呢。呵呵,现在差不多明白了。就像我经常玩的cf,里面没有出口和入口,总是在一个图里面玩。里面的人物就相当于我们说的参数,他们从哪里来??呵呵,他们原来就是在程序的里面,他就是我们定义的。这个比喻不知算不算很贴切。
参数里面有两种,和c里面的一样,一种是形参,一种是实参。形参没有什么特别的意义,就是代表一个参数,可以随便修改,只要不改变类型就可以,他就是一个标志符号而已。而另外的实参,这个是或许被赋予一定的值的,不可随便修改。他就是一个实际的参数。
我能改变参数吗?
参数改不改变,那都是你自己的事情,参数我们随便的改,但是我们怕的是结果。这里有一句重要的话,在函数里面为参数赋予新值不会改变外部任何变量的值。
>>>def  to_change(n):
    n='hello li'
>>>name='hello wang'
>>>to_change(name)
>>>name
hello wang
虽然name进函数里面转悠了一圈,但是他的值没有改变,还是原来的。
字符串,数字,元组,都是不可变的,没有办法进行修改,只可以用新值来覆盖,这样就可以改变他的值。
>>>def change(n):
    n[0]='hello wang'
>>>name=['hello li','hello shanshan']
>>>change(name)
>>>name
['hello wang','hello shanshan']
这个里面的值竟然改变了。很奇怪吧,就是一个函数里面的定义改变了一点,差别竟然是如此之大。很奇怪。如果我们不使用函数,来做一次看看。
>>>name=['hello li','hello shanshan']
>>>n=name #用来模拟上面例子里面的,change(name),相当于传递参数。
>>>n[0]='hello wang' #改变列表。
>>>name
['hello wang','hello shanshan']
这下就知道为什么了吧。其实挺简单的。
为了防止这种事情发生,最好的办法是创建一个副本,这样,就可以使原来的值不发生变化。例如:
n=name[ : ]
还记得这个东西吗?以前经常说的分片。这样就复制了一个副本。进行上面的操作时候,改变的就是这个副本,原来的值并不会发生改变。

为什么要修改参数?
这里有一个例子。假如要编写一个存储名字,并且可以使用名字,中间名或者姓查找联系人的程序,可以使用下面的数据结构:
storage={}
storage['first']={}
storage['middle']={}
storage['last']={}
这样创建了一个数据结构storage,这个字典里面包含三个键,每个键又是一个字典,storage['first']就是子字典的名字。这样的创建方法好像是第一次见到,要注意,记住。
当要插入一个新的值的时候,可以这么做:
>>>me='wang xiao lei'
>>>storage['first']['wang']=[me]
>>>storage['middle']['xiao']=[me]
>>>storage['last']['lei']=[me]
每个下面都存储了一个以人名组成的列表。这个我没有理解,列表???没有看出来什么是列表。教材说me就是一个列表,怎么回事?标记一下,以后解决。
不管是什么形式,但是我们已经感觉到了像这样子来插入数据,会很累。抽象的要点就是要隐藏更新的时候繁琐的细节,这个过程可以使用函数来实现。
def init(data):
    data['first']={}
    data['middle']={}
    data['last']={}
上面这个是初始化语句放到函数里面,使用时候是这样:
>>>storage={}
>>>init(storage)
>>>storage
{ 'middle':{},'last':{},'first':{} }
呵呵,这下子知道为什么要改变参数了吧?作用已经很明显了,这个storage完全被改变了。
然后在写存储的名字之前,先写一个获得名字的函数:
def lookup(data.label , name):
    return data[label].get(name)
当查询一个名字的时候,可以这样:
>>>lookup(storage.'middle','wang')
下面开始一个大工程了,存储的代码:
def store(data.full_name):
    names=full_name.split()
    if len(names)==2:name.insert(1,'')
    labels='first','middle','last'
for label.name in  zip(labels,names):
    people=lookup(data.label , name)
    if people:
        people.append(full_name)
    else:
        data[label][name]=[full_name]
这个执行步骤如下:
1.使用参数data和full_name进入函数,这两个参数被设置为函数在外部获得的一些值。
2.通过拆分full_name,得到一个叫做names的列表。split这个方法是拆分。
3.如果names的长度为2,只有首名和末名,那么插入一个空字符串在位置1,就是第二个字符位置,相当于在字符串中间作为名字。
4.将字符串‘first’,‘middle’,和‘last’作为元组存储在labels里面
5.使用zip函数将两个应该是列表的label和name合并,进行下面的处理:
一,获得给定标签和名字的列表。
二,将full_name添加到列表里面,或者插入一个新的列表。
下面进行一下测试:
>>>mynames={}
>>>init(mynames)
>>>store(mynames,'wang xiao lei')
>>>lookup(mynames.'middle', 'xiao')
['wang xiao lei']
如果是这样的话,就是差不多的了,然后测试那个两个符号的名字就好了。
这个程序有点长,还要好好看看,仔细理解一下。


摘自 juepei的专栏
补充:Web开发 , Python ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,