Python更多控制流工具(二)

4.6. Defining Functions

We can create a function that writes the Fibonacci series to an arbitrary boundary:

我们创建一个斐波那契数列的函数:

>>> def fib(n):    # write Fibonacci series up to n
...     """Print a Fibonacci series up to n."""
...     a, b = 0, 1
...     while a < n:
...         print(a, end=‘ ‘)
...         a, b = b, a+b
...     print()
...
>>> # Now call the function we just defined:
... fib(2000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

The keyword def introduces a function definition. It must be followed by the function name and the parenthesized list of formal parameters. The statements that form the body of the function start at the next line, and must be indented.

关键词def用来定义函数。后面是函数名称,括号中列出参数,并以冒号结束函数头。函数体必须另起一行,并必须缩进:

The first statement of the function body can optionally be a string literal; this string literal is the function’s documentation string, or docstring. (More about docstrings can be found in the section Documentation Strings.) There are tools which use docstrings to automatically produce online or printed documentation, or to let the user interactively browse through code; it’s good practice to include docstrings in code that you write, so make a habit of it.

函数体的一条语句是一条字符串常量;这个字符串常量是函数文档注释(更多介绍文档字符串的请查阅 Documentation Strings)。它的作用相当于C++中的函数注释,但它可以同用户使用代码交互,可以在线咨询。因此在自己的代码中包含文档注释是非常好的习惯。

The execution of a function introduces a new symbol table used for the local variables of the function. More precisely, all variable assignments in a function store the value in the local symbol table; whereas variable references first look in the local symbol table, then in the local symbol tables of enclosing functions, then in the global symbol table, and finally in the table of built-in names. Thus, global variables cannot be directly assigned a value within a function (unless named in a global statement), although they may be referenced.

执行函数时,函数会创建一个符号表用来存储该函数中使用的本地变量。更准确的说,所有在函数中变量的值存储在符号表中;因此,变量引用首先在本地符号表中查找,然后在函数创建的符号表,然后是全局符号表,最后是内置的变量名。因此全局变量不能直接在函数体中赋值((因为全局变量不会去查找函数创建的符号表,因此它会认为没有该符号变量)除非使用global语句)。

The actual parameters (arguments) to a function call are introduced in the local symbol table of the called function when it is called; thus, arguments are passed using call by value (where the value is always an object reference, not the value of the object). [1] When a function calls another function, a new local symbol table is created for that call.

当一个函数被调用时,实参也会被导入到该函数所创建的符号表中。因此,参数是引用传递而不是值传递。当一个函数调用另一个函数时,该函数会为这次调用创建一个新的符号表。

A function definition introduces the function name in the current symbol table. The value of the function name has a type that is recognized by the interpreter as a user-defined function. This value can be assigned to another name which can then also be used as a function. This serves as a general renaming mechanism:

当一个函数调用另一个函数时,会把这个被调用的函数的名字添加到当前的符号表中。函数名字的值也是一个类型,这个类型能被解释器识别出这是一个用户定义的函数。函数名对应的值也能赋给另一个变量。这个变量就相当于C++中的函数指针:

>>> fib
<function fib at 10042ed0>
>>> f = fib
>>> f(100)
0 1 1 2 3 5 8 13 21 34 55 89

Coming from other languages, you might object that fib is not a function but a procedure since it doesn’t return a value. In fact, even functions without a return statement do return a value, albeit a rather boring one. This value is called None (it’s a built-in name). Writing the value None is normally suppressed by the interpreter if it would be the only value written. You can see it if you really want to using print():

来自其他语言的认识,你可能觉得fib不是一个函数而是一个执行程序,因为它没有返回值,实际上,它有一个返回值为None(一个内置名称)。你可以使用print()看到:

>>> fib(0)
>>> print(fib(0))
None

It is simple to write a function that returns a list of the numbers of the Fibonacci series, instead of printing it:

写一个简单的函数返回斐波那契数列的列表很容易:

>>> def fib2(n): # return Fibonacci series up to n
...     """Return a list containing the Fibonacci series up to n."""
...     result = []
...     a, b = 0, 1
...     while a < n:
...         result.append(a)    # see below
...         a, b = b, a+b
...     return result
...
>>> f100 = fib2(100)    # call it
>>> f100                # write the result
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

4.7. More on Defining Functions

It is also possible to define functions with a variable number of arguments. There are three forms, which can be combined.

我们可以定义多种函数参数形式,有一下三种形式:

4.7.1. Default Argument Values

The most useful form is to specify a default value for one or more arguments. This creates a function that can be called with fewer arguments than it is defined to allow. For example:

给参数指定默认值非常有用。这样允许函数调用使用默认的值,例如:

def ask_ok(prompt, retries=4, complaint=‘Yes or no, please!‘):
    while True:
        ok = input(prompt)
        if ok in (‘y‘, ‘ye‘, ‘yes‘):
            return True
        if ok in (‘n‘, ‘no‘, ‘nop‘, ‘nope‘):
            return False
        retries = retries - 1
        if retries < 0:
            raise OSError(‘uncooperative user‘)
        print(complaint)

This function can be called in several ways:

  • giving only the mandatory argument: ask_ok(‘Do you really want to quit?‘)
  • giving one of the optional arguments: ask_ok(‘OK to overwrite the file?‘, 2)
  • or even giving all arguments: ask_ok(‘OK to overwrite the file?‘, 2, ‘Come on, only yes or no!‘)

函数可以有以下几个调用形式:

只给一个参数:ask_ok(‘Do you really want to quit?‘)

给一个可选的参数:ask_ok(‘OK to overwrite the file?‘, 2)

给出所有参数:ask_ok(‘OK to overwrite the file?‘, 2, ‘Come on, only yes or no!‘)

This example also introduces the in keyword. This tests whether or not a sequence contains a certain value.

这个例子也介绍了关键字in。用来测试这个序列是否包含某个确切的值。

The default values are evaluated at the point of function definition in the defining scope, so that

i = 5

def f(arg=i):
    print(arg)

i = 6
f()

将会打印5.

4.7.2. Keyword Arguments

Functions can also be called using keyword arguments of the form kwarg=value. For instance, the following function:

函数可以使用关键字参数,例如下面的函数:

def parrot(voltage, state=‘a stiff‘, action=‘voom‘, type=‘Norwegian Blue‘):
    print("-- This parrot wouldn‘t", action, end=‘ ‘)
    print("if you put", voltage, "volts through it.")
    print("-- Lovely plumage, the", type)
    print("-- It‘s", state, "!")

accepts one required argument (voltage) and three optional arguments (state, action, and type). This function can be called in any of the following ways:

接收一个必须输入的参数(voltage)和三个可选参数(state,action 和 type),这个函数有一下几种调用方式:

parrot(1000)                                          # 1 positional argument
parrot(voltage=1000)                                  # 1 keyword argument
parrot(voltage=1000000, action=‘VOOOOOM‘)             # 2 keyword arguments
parrot(action=‘VOOOOOM‘, voltage=1000000)             # 2 keyword arguments
parrot(‘a million‘, ‘bereft of life‘, ‘jump‘)         # 3 positional arguments
parrot(‘a thousand‘, state=‘pushing up the daisies‘)  # 1 positional, 1 keyword

but all the following calls would be invalid:

但是下面的调用方式不合法:

parrot()                     # required argument missing
parrot(voltage=5.0, ‘dead‘)  # non-keyword argument after a keyword argument
parrot(110, voltage=220)     # duplicate value for the same argument
parrot(actor=‘John Cleese‘)  # unknown keyword argument

In a function call, keyword arguments must follow positional arguments. All the keyword arguments passed must match one of the arguments accepted by the function (e.g. actor is not a valid argument for the parrot function), and their order is not important. This also includes non-optional arguments (e.g. parrot(voltage=1000) is valid too). No argument may receive a value more than once. Here’s an example that fails due to this restriction:

在函数调用中,关键字参数后面必须是关键字参数。所有的关键字参数传递必须匹配其中一个函数可接受的参数,他们的顺序不重要。

When a final formal parameter of the form **name is present, it receives a dictionary (see Mapping Types — dict) containing all keyword arguments except for those corresponding to a formal parameter. This may be combined with a formal parameter of the form *name (described in the next subsection) which receives a tuple containing the positional arguments beyond the formal parameter list. (*name must occur before **name.) For example, if we define a function like this:

当最后一个参数形式是**name。它表示是一个字典类型。*name表示是一个元组类型。元组类型必须放在字典类型前面,同时元组也必须放在形式参数之后。字典类型必须放在最后一个参数。例如:

def cheeseshop(kind, *arguments, **keywords):
    print("-- Do you have any", kind, "?")
    print("-- I‘m sorry, we‘re all out of", kind)
    for arg in arguments:
        print(arg)
    print("-" * 40)
    keys = sorted(keywords.keys())
    for kw in keys:
        print(kw, ":", keywords[kw])

It could be called like this:

可以这样调用:

cheeseshop("Limburger", "It‘s very runny, sir.",
           "It‘s really very, VERY runny, sir.",
           shopkeeper="Michael Palin",
           client="John Cleese",
           sketch="Cheese Shop Sketch")

and of course it would print:

打印结果如下:

-- Do you have any Limburger ?
-- I‘m sorry, we‘re all out of Limburger
It‘s very runny, sir.
It‘s really very, VERY runny, sir.
----------------------------------------
client : John Cleese
shopkeeper : Michael Palin
sketch : Cheese Shop Sketch

Note that the list of keyword argument names is created by sorting the result of the keywords dictionary’s keys() method before printing its contents; if this is not done, the order in which the arguments are printed is undefined.

注意,关键字名字的列表的顺序是关键字字典调用keys()之后的排序结果。如果不排序,那么打印出来是定义的。

4.7.3. Arbitrary Argument Lists

Finally, the least frequently used option is to specify that a function can be called with an arbitrary number of arguments. These arguments will be wrapped up in a tuple (see Tuples and Sequences). Before the variable number of arguments, zero or more normal arguments may occur.

最后,最不经常用的一种函数包括任意数量的参数。这些参数被封装在一个元组中。在任意多个参数前可以有0或多个正规参数。

def write_multiple_items(file, separator, *args):
    file.write(separator.join(args))

Normally, these variadic arguments will be last in the list of formal parameters, because they scoop up all remaining input arguments that are passed to the function. Any formal parameters which occur after the *args parameter are ‘keyword-only’ arguments, meaning that they can only be used as keywords rather than positional arguments.

一般地,这些参数都必须在正常参数之后,任何正常参数出现在*args后面都属于关键字参数,这意味着他们不能作为正规参数使用。

>>> def concat(*args, sep="/"):
...    return sep.join(args)
...
>>> concat("earth", "mars", "venus")
‘earth/mars/venus‘
>>> concat("earth", "mars", "venus", sep=".")
‘earth.mars.venus‘

4.7.4. Unpacking Argument Lists

The reverse situation occurs when the arguments are already in a list or tuple but need to be unpacked for a function call requiring separate positional arguments. For instance, the built-in range() function expects separate start and stop arguments. If they are not available separately, write the function call with the *-operator to unpack the arguments out of a list or tuple:

相反的情况,我们需要用列表或元组作为参数,但是函数需要单独的固定位置的参数,这是我们需要解包。例如,内置函数range()需要单独的start(起始位置)和stop(终止位置)两个参数。如果他们不合适分离,用*操作符解包将参数从列表或元组中提取出来:

>>> list(range(3, 6))            # normal call with separate arguments
[3, 4, 5]
>>> args = [3, 6]
>>> list(range(*args))            # call with arguments unpacked from a list
[3, 4, 5]

In the same fashion, dictionaries can deliver keyword arguments with the **-operator:

同理,字典提取关键字参数使用**操作符:

>>> def parrot(voltage, state=‘a stiff‘, action=‘voom‘):
...     print("-- This parrot wouldn‘t", action, end=‘ ‘)
...     print("if you put", voltage, "volts through it.", end=‘ ‘)
...     print("E‘s", state, "!")
...
>>> d = {"voltage": "four million", "state": "bleedin‘ demised", "action": "VOOM"}
>>> parrot(**d)
-- This parrot wouldn‘t VOOM if you put four million volts through it. E‘s bleedin‘ demised !

4.7.5. Lambda Expressions

Small anonymous functions can be created with the lambda keyword. This function returns the sum of its two arguments: lambda a, b: a+b. Lambda functions can be used wherever function objects are required. They are syntactically restricted to a single expression. Semantically, they are just syntactic sugar for a normal function definition. Like nested function definitions, lambda functions can reference variables from the containing scope:

短小的匿名函数可以用lambda关键字创建。这个函数返回两个参数的和:lambda a,b: a + b。lambda函数可以在任何需要函数对象的地方使用。它在语法上要求只能有单个表达式。从语义上讲,他们只是正常函数的简单包装。类似于嵌套函数定义,lambda函数可以从所包含的范围内引用变量:

>>> def make_incrementor(n):
...     return lambda x: x + n
...
>>> f = make_incrementor(42)
>>> f(0)
42
>>> f(1)
43

The above example uses a lambda expression to return a function. Another use is to pass a small function as an argument:

上面的例子使用lambda表达式返回一个函数对象。另一个用途是将lambda表达式作为参数传递:

>>> pairs = [(1, ‘one‘), (2, ‘two‘), (3, ‘three‘), (4, ‘four‘)]
>>> pairs.sort(key=lambda pair: pair[1])
>>> pairs
[(4, ‘four‘), (1, ‘one‘), (3, ‘three‘), (2, ‘two‘)]

4.7.6. Documentation Strings

Here are some conventions about the content and formatting of documentation strings.

The first line should always be a short, concise summary of the object’s purpose. For brevity, it should not explicitly state the object’s name or type, since these are available by other means (except if the name happens to be a verb describing a function’s operation). This line should begin with a capital letter and end with a period.

If there are more lines in the documentation string, the second line should be blank, visually separating the summary from the rest of the description. The following lines should be one or more paragraphs describing the object’s calling conventions, its side effects, etc.

The Python parser does not strip indentation from multi-line string literals in Python, so tools that process documentation have to strip indentation if desired. This is done using the following convention. The first non-blank line after the first line of the string determines the amount of indentation for the entire documentation string. (We can’t use the first line since it is generally adjacent to the string’s opening quotes so its indentation is not apparent in the string literal.) Whitespace “equivalent” to this indentation is then stripped from the start of all lines of the string. Lines that are indented less should not occur, but if they occur all their leading whitespace should be stripped. Equivalence of whitespace should be tested after expansion of tabs (to 8 spaces, normally).

Here is an example of a multi-line docstring:

>>> def my_function():
...     """Do nothing, but document it.
...
...     No, really, it doesn‘t do anything.
...     """
...     pass
...
>>> print(my_function.__doc__)
Do nothing, but document it.

    No, really, it doesn‘t do anything.

4.8. Intermezzo: Coding Style

  • Use 4-space indentation, and no tabs.

    4 spaces are a good compromise between small indentation (allows greater nesting depth) and large indentation (easier to read). Tabs introduce confusion, and are best left out.

  • 使用4个空格作为缩进。
  • Wrap lines so that they don’t exceed 79 characters.

    This helps users with small displays and makes it possible to have several code files side-by-side on larger displays.

  • Use blank lines to separate functions and classes, and larger blocks of code inside functions.
  • 使用空行分隔函数和类,以及函数内部的大代码块
  • When possible, put comments on a line of their own.
  • Use docstrings.
  • 使用文档注释
  • Use spaces around operators and after commas, but not directly inside bracketing constructs: a = f(1, 2) + g(3, 4).
  • Name your classes and functions consistently; the convention is to use CamelCase for classes and lower_case_with_underscores for functions and methods. Always use self as the name for the first method argument (see A First Look at Classes for more on classes and methods).
  • Don’t use fancy encodings if your code is meant to be used in international environments. Python’s default, UTF-8, or even plain ASCII work best in any case.
  • Likewise, don’t use non-ASCII characters in identifiers if there is only the slightest chance people speaking a different language will read or maintain the code.

  

时间: 2024-11-03 18:11:43

Python更多控制流工具(二)的相关文章

Python更多控制流工具(一)

4.1. if Statements Perhaps the most well-known statement type is the if statement. For example: if语句可能是最常见的控制流语句了,例如: >>> x = int(input("Please enter an integer: ")) Please enter an integer: 42 >>> if x < 0: ... x = 0 ... pr

[转载]Python 包管理工具解惑

原文链接:http://zengrong.net/post/2169.htm Python 包管理工具解惑 python packaging 一.困惑 作为一个 Python 初学者,我在包管理上感到相当疑惑(嗯,是困惑).主要表现在下面几个方面: 这几个包管理工具有什么不同? distutils setuptools distribute disutils2 distlib pip 什么时候该用pip,什么时候该用 setup.py ,它们有关系么? easy_install.ez_setup

Python渗透测试工具合集

Python渗透测试工具合集 如果你热爱漏洞研究.逆向工程或者渗透测试,我强烈推荐你使用 Python 作为编程语言.它包含大量实用的库和工具, 本文会列举其中部分精华. 网络 Scapy, Scapy3k: 发送,嗅探,分析和伪造网络数据包.可用作交互式包处理程序或单独作为一个库. pypcap, Pcapy, pylibpcap: 几个不同 libpcap 捆绑的python库 libdnet: 低级网络路由,包括端口查看和以太网帧的转发 dpkt: 快速,轻量数据包创建和分析,面向基本的

Python 包管理工具解惑

Python 包管理工具解惑 本文链接:http://zengrong.net/post/2169.htm python packaging 一.困惑 作为一个 Python 初学者,我在包管理上感到相当疑惑(嗯,是困惑).主要表现在下面几个方面: 这几个包管理工具有什么不同? distutils setuptools distribute disutils2 distlib pip 什么时候该用pip,什么时候该用 setup.py ,它们有关系么? easy_install.ez_setup

机器学习算法与Python实践之(二)支持向量机(SVM)初级

机器学习算法与Python实践之(二)支持向量机(SVM)初级 机器学习算法与Python实践之(二)支持向量机(SVM)初级 [email protected] http://blog.csdn.net/zouxy09 机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学习算法.恰好遇见这本同样定位的书籍,所以就参考这本书的过程来学习了. 在这一节我们主要是

python环境和工具

1.版本问题 python2.X和python3.X是不兼容,所以选择如果选择了2.X版本,那么为了避免兼容性的问题,在以后使用其他python库或者工具时,也需要选择相对应的版本. 下载地址:https://www.python.org/ 2.开发工具IDLE IDLE是python自身附带使用tkinter创建的图形化的交互式环境. 3.用tkinter编写GUI tkinter是python自带的用于GUI编程的库,是对图形库TK的封装,跨平台. 4.数值计算库NumPy和SciPy Nu

windows安装python包管理工具pip

windows安装python包管理工具pip     pip 是一个Python包管理工具,主要是用于安装 PyPI 上的软件包,可以替代 easy_install 工具. 一.前期准备 首先确认windows机器上面是否已经安装好了python.在cmd中输入python --version和python看看是否有反应 如上面所示,表示已经在windows平台上面搭建好了python环境. 二.下载安装 1.到官网去https://pypi.python.org/pypi/pip#downl

python的构建工具——setup.py文件

一.构建工具setup.py的应用场景 在安装python的相关模块和库时,我们一般使用"pip install  模块名"或者"python setup.py install",前者是在线安装,会安装该包的相关依赖包:后者是下载源码包然后在本地安装,不会安装该包的相关依赖包.所以在安装普通的python包时,利用pip工具相当简单.但是在如下场景下,使用python setup.py install会更适合需求: 在编写相关系统时,python 如何实现连同依赖包

Python静态检查工具

Python是一门动态语言.在给python传参数的时候并没 有严格的类型限制.写python程序的时候,发现错误经常只能在执行的时候发现.有一些 错误由于隐藏的比较深,只有特定逻辑才会触发,往往导致需要花很多时间才能将语法错误慢慢排查出来.其实有一些错误是很明显的,假如能在写程序的时候发现这些错误,就能提高工作效率. 注:习惯了C/C++等编译语言,使用像Python这种动态语言,总有点不放心,特别是搭建比较大的系统的时候.Python静态语法检查工具就出现了. Pyflakes(错误检查利器