Python学习笔记(函数)

 
Python学习笔记(函数)

常见问题

  1. 局部名字静态检测
    Python探测局部作用域的时候:是在python编译代码时检测,而不是通过他们在运行时的赋值。
    正常的情况下,没在函数中复制的名字将在包含它的模块中查找:
    >>> x=99
    >>> def selector():
    ...     print x
    ... 
    >>> selector()
    99
    但是:
    >>> def selector():
    ...     print x
    ...     x=100
    ... 
    >>> selector()
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 2, in selector
    UnboundLocalError: local variable 'x' referenced before assignment
    会得到未定义名字的错误。
    当 交互式输入或从一个模块中导入时,python读取并编译这段代码,当编译时python查看x的赋值,并决定在函数中任何地方x都将是个局部名字。到后 来函数真的运行,print执行时,赋值还没有发生,python会说你正在使用一个未定义的名字。根据他的名字规则,应该是局部的x在赋值前被使用了。
    解决办法:
    如果你想打印全局x,你应该在global语句中声明:(这意味着该赋值也改变全局x,而不是局部x)
    >>> def selector():
    ...     global x
    ...     print x
    ...     x=88
    ... 
    >>> selector()
    99
    如果你想打印出全局赋值,在设定一个局部的,导入包含它的模块并用限定得到这个全局的版本:
    >>> x=99
    >>> def selector():
    ...     import __main__
    ...     print __main__.x
    ...     x=88
    ...     print x
    ... 
    >>> selector()
    99
    88
    限定(.x部分)从一个名字空间对象中得到一个值。交互环境的名字空间是一个叫做__main__的模块。
  2. 嵌套函数可以嵌套作用域(在新版本中和老版本中不同)
    >>> def outer(x):
    ...     def inner(i):       
    ...         print i,
    ...         if i: inner(i-1)
    ...     inner(x)
    ... 
    >>> outer(3)
    3 2 1 0
  3. 使用默认值保存引用
    >>> def outer(x):
    ...     def inner(i,self=inner):
    ...         print i,
    ...         if i:self(i-1)
    ...     inner(x)
    ... 
    >>> outer(3)
    Traceback (most recent call last):
    File "<stdin>", line 1, in ?
    File "<stdin>", line 2, in outer
    UnboundLocalError: local variable 'inner' referenced before assignment
    解决原则:最简单的方式总是最正确的方式
    >>> def inner(i):
    ...     print i,
    ...     if i:inner(i-1)
    ... 
    >>> def outer(x):
    ...     inner(x)
    ... 
    >>> outer(3)
    3 2 1 0
  4. 默认的可变对象
    >>> def saver(x=[]):
    ...     x.append(1)
    ...     print x
    ... 
    >>> saver([2])
    [2, 1]
    >>> saver()
    [1]
    >>> saver()
    [1, 1]
    >>> saver()
    [1, 1, 1]
    问题是,这里只有一个列表对象——def执行时生成的一个。在每一次函数被调用时,你不会得到新的列表对象,而是原列表对象的增长。
    解决办法:如果那不是你想要的行为,简单的移动默认值到函数体中。只要代码里的值在每一次函数运行时都执行,你每次将得到一个新的对象:
    >>> def saver(x=None):
    ...     if x is None:
    ...         x=[]
    ...     x.append(1)
    ...     print x
    ... 
    >>> saver([2])
    [2, 1]
    >>> saver()
    [1]
    >>> saver()
    [1]
    >>> saver()
    [1]
    上 面的if语句几乎可以被赋值x=x or []代替,因为python的or将返回他的操作对象中的一个:如果没有参数被传递,x默认为None,所以or在右侧返回一个生成的空列表。但这不完全 一样,当传递的是空列表时,函数将扩展并返回一个新生成的列表,而不是向前面的版本那样扩展并返回一个被传递的列表(表达式变成[] or [],这将计算出新的列表)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值