机器人 救救瓜
Toggle navigation
Home
SCM-tool
Linux
Jenkins
SVN
other
About Me
Archives
Tags
python 笔记之 文档字符串,收集关键字参数,作用域嵌套, 递归,异常
? python ?
2021-03-10 17:07:35
1265
0
0
gua_l
? python ?
### 文档字符串 除了# 注释,有另一种编写注释的方式,就是添加独立的字符串。在有些地方,如def语句后面(以及模块和类的开头,),添加这样的字符串很有用。放在函数开头的字符串称为文档字符串(docstring),将作为函数的一部分存储起来。下面的代码演示了如何给函数添加文档字符串: ``` def square(x): 'Calculates the square of the number x.' return x * x ``` 可以像下面这样访问文档字符串: ``` >>> square.__doc__ 'Calculates the square of the number x.' ``` ### 收集参数 单星号 * (元组) 前面有星号的参数将被放在元组中。 因此星号意味着收集余下的位置参数。如果没有可供收集的参数,params将是一个空元组。 ``` >>> print_params_2('Nothing:') Nothing: () ``` 与赋值时一样,带星号的参数也可放在其他位置(而不是最后),但不同的是,在这种情况下你需要做些额外的工作:使用名称来指定后续参数。单星号不会收集关键字参数。 ``` >>> def in_the_middle(x, *y, z): ... print(x, y, z) ... >>> in_the_middle(1, 2, 3, 4, 5, z=7) 1 (2, 3, 4, 5) 7 ``` 双星号 ** (字典) **要收集关键字参数,可使用两个星号。** ``` >>> def print_params_3(**params): ... print(params) ... >>> print_params_3(x=1, y=2, z=3) {'z': 3, 'x': 1, 'y': 2} ``` 如你所见,这样得到的是一个字典而不是元组。可结合使用这些技术。 ``` def print_params_4(x, y, z=3, *pospar, **keypar): print(x, y, z) print(pospar) print(keypar) ``` 其效果与预期的相同。 ``` >>> print_params_4(1, 2, 3, 5, 6, 7, foo=1, bar=2) 1 2 3 (5, 6, 7) {'foo': 1, 'bar': 2} >>> print_params_4(1, 2) 1 2 3 () {} ``` ### 作用域 **vars()** 作用域 变量到底是什么呢?可将其视为指向值的名称。因此,执行赋值语句x = 1后,名称x指向值1。这几乎与使用字典时一样(字典中的键指向值),只是你使用的是“看不见”的字典。实际上,这种解释已经离真相不远。有一个名为vars的内置函数,它返回这个不可见的字典: ``` >>> x = 1 >>> scope = vars() >>> scope['x'] 1 >>> scope['x'] += 1 >>> x 2 ``` 遮盖和全局变量 **globals()** 读取全局变量的值通常不会有问题,但还是存在出现问题的可能性。如果有一个局部变量或参数与你要访问的全局变量同名,就无法直接访问全局变量,因为它被局部变量遮 住了。如果需要,可使用函数globals来访问全局变量。这个函数类似于vars,返回一个包含全局变量的字典。(locals返回一个包含局部变量的字典。)例如,在前面的示例中,如果有一个名为parameter的全局变量,就无法在函数combine中访问它,因为有一个与之同名的参数。然而,必要时可使用globals()['parameter']来访问它。 ``` >>> def combine(parameter): ... print(parameter + globals()['parameter']) ... >>> parameter = 'berry' >>> combine('Shrub') Shrubberry ``` 重新关联全局变量(使其指向新值)是另一码事。在函数内部给变量赋值时,该变量默认为局部变量,除非你明确地告诉Python它是全局变量。那么如何将这一点告知Python呢? ``` >>> x = 1 >>> def change_global(): ... global x ... x = x + 1 ... >>> change_global() >>> x 2 ``` ### 作用域嵌套 Python函数可以嵌套,即可将一个函数放在另一个函数内,如下所示: ``` def foo(): def bar(): print("Hello, world!") bar() ``` 嵌套通常用处不大,但有一个很突出的用途:使用一个函数来创建另一个函数。这意味着可像下面这样编写函数: ``` def multiplier(factor): def multiplyByFactor(number): return number * factor return multiplyByFactor ``` 在这里,一个函数位于另一个函数中,且外面的函数**返回里面的函数**。也就是返回一个函数,而不是调用它。重要的是,返回的函数能够访问其定义所在的作用域。换而言之,**它携带着自己所在的环境(和相关的局部变量)**!每当外部函数被调用时,都将重新定义内部的函数,而变量factor的值也可能不同。由于Python的嵌套作用域,可在内部函数中访问这个来自外部局部作用域(multiplier)的变量,如下所示: ``` >>> double = multiplier(2) >>> double(5) 10 >>> triple = multiplier(3) >>> triple(3) 9 >>> multiplier(5)(4) 20 ``` 像multiplyByFactor这样存储其所在作用域的函数称为**闭包**。 ### 递归 非无穷**递归函数**将满足以下两个条件: **基线条件**(针对最小的问题):满足这种条件时函数将直接返回一个值。 **递归条件** 包含一个或多个调用,这些调用旨在解决问题的一部分。 ### 异常 try except raise ``` class MuffledCalculator: muffled = False def calc(self, expr): try: return eval(expr) except ZeroDivisionError: ## 捕获后处理或继续引发异常 if self.muffled: print('Division by zero is illegal') else: raise ## 捕获后仍引发异常 ``` 多个except: ``` except ZeroDivisionError: print("The second number can not be Zero.") except ValueError: print("that was not a number.") ``` 等价于用元组表示多个异常 ``` except (ZeroDivisionError,ValueError): print("all error info") ``` 捕获导常对象本身并打印它 ``` try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) print(x / y) except (ZeroDivisionError, TypeError) as e: print(e) ``` except子句也捕获两种异常,但由于你同时显式地捕获了对象本身,因此可将其打印出来,让用户知道发生了什么情况。 捕获所有 ``` except: print('Something wrong happened ...') ``` 优化对异常对象进行检查 ``` except Exception as e ``` 无异常往下 使用else 子句 在有些情况下,在没有出现异常时执行一个代码块很有用。为此,可像条件语句和循环一样,给try/except语句添加一个else子句。 ``` try: print('A simple task') except: print('What? Something went wrong?') else: print('Ah ... It went as planned.') ``` 如果你运行这些代码,输出将如下: ``` A simple task Ah ... It went as planned. ``` 通过使用else子句,可实现循环。 ``` while True: try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) value = x / y print('x / y is', value) except: print('Invalid input. Please try again.') else: break ``` 在这里,仅当没有引发异常时,才会跳出循环(这是由else子句中的break语句实现的)。**换而言之,只要出现错误,程序就会要求用户提供新的输入**。 优化 如果使用except Exception as e, 就可利用8.3.4节介绍的技巧在这个小型除法程序中打印更有用的错误消息。 ``` while True: try: x = int(input('Enter the first number: ')) y = int(input('Enter the second number: ')) value = x / y print('x / y is', value) except Exception as e: print('Invalid input:', e) print('Please try again') else: break ``` finally 不管try 中的语句 是否引发异常,都将执行finally 中的语句 ``` try: 1 / 0 except NameError: print("Unknown variable") else: print("That went well!") finally: print("Cleaning up.") ```
Pre:
python 笔记之 模块
Next:
python 笔记之 python函数的参数是可变的数据结构时需要创建副本
0
likes
1265
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Submit
Sign in
to leave a comment.
No Leanote account?
Sign up now.
0
comments
More...
Table of content
No Leanote account? Sign up now.