python 函数的调用 和执行 小知识

1.符号表

执行一个函数会引入一个用于函数的局部变量的新符号表。

更确切地说,

函数中的所有的赋值都是将值存储在局部符号表;

而变量引用首先查找局部符号表,

然后是上层函数的局部符号表,

然后是全局符号表,

最后是内置名字表。

因此,在函数内部全局变量不能直接赋值(除非在一个global语句中命名),虽然可以引用它们。

2.传值

函数调用的实际参数在函数被调用时引入被调函数的局部符号表;

因此,

参数的传递使用传值调用

(这里的值始终是对象的引用,不是对象的值)。

一个函数调用另一个函数时,

会为该调用创建一个新的局部符号表。

函数定义会在当前符号表内引入函数名。

函数名对应值的类型是解释器可识别的用户自定义函数。

此值可以分配给另一个名称,

然后也可作为函数。

这是通用的重命名机制:

传参:默认值在定义域中的函数定义的时候计算

重要的警告:

默认值只计算一次。

这使得默认值是列表、字典或大部分类的实例时会有所不同。

例如,

下面的函数在后续调用过程中会累积传给它的参数:

def f(a, L=[]):
    L.append(a)
    return L

print f(1)
print f(2)
print f(3)

这将会打印

[1]
[1, 2]
[1, 2, 3]

如果你不想默认值在随后的调用中共享,

可以像这样编写函数:

def f(a, L=None):
    if L is None:
        L = []
    L.append(a)
    return L

当最后一个形参以**name形式出现时,

它接收一个字典(见映射类型 — 字典),

该字典包含了所有未出现在形式参数列表中的关键字参数。

它还可能与*name形式的参数(在下一小节中所述)组合使用,

*name接收一个包含所有没有出现在形式参数列表中的位置参数元组。

(*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]

它可以这样调用:

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

当然它会打印:

-- 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

注意在打印关键字参数之前,

通过对关键字字典 keys() 方法的结果进行排序,

生成了关键字参数名的列表;

如果不这样做,

打印出来的参数的顺序是未定义的。

3.过程和函数的区别

如果你使用过其他语言,你可能会反对说:

fib不是一个函数,而是一个过程(子程序),

因为它并不返回任何值。

事实上,没有return语句的函数也返回一个值,尽管是一个很无聊的值。

此值被称为None(它是一个内置的名称)。

如果 None只是唯一的输出,解释器通常不会打印出来。

如果你真的想看到这个值,可以使用print 语句。

4.参数拆分

参数列表的分拆

当传递的参数已经是一个列表或元组时,

情况与之前相反,

你要分拆这些参数,

因为函数调用要求独立的位置参数。

例如,

内置的range()函数期望单独的start和stop参数。

如果它们不是独立的,

函数调用时使用 *-操作符将参数从列表或元组中分拆开来:

>>>

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

以同样的方式,可以用**-操作符让字典传递关键字参数:

>>>

>>> def parrot(voltage, state=‘a stiff‘, action=‘voom‘):
...     print "-- This parrot wouldn‘t", action,
...     print "if you put", voltage, "volts through it.",
...     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 !

5.lambda匿名小函数

可以使用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

上面的示例使用 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‘)]

6.文档字符串

第一行永远应该是对象用途的简短、精确的总述。为了简单起见,不应该明确的陈述对象的名字或类型,因为这些信息可以从别的途径了解到(除非这个名字碰巧就是描述这个函数操作的动词)。这一行应该以大写字母开头,并以句号结尾。

如果在文档字符串中有更多的行,第二行应该是空白,在视觉上把摘要与剩余的描述分离开来。以下各行应该是一段或多段描述对象的调用约定、 其副作用等。

Python 解释器不会从多行的文档字符串中去除缩进,所以必要的时候处理文档字符串的工具应当自己清除缩进。这通过使用以下约定可以达到。第一行 之后 的第一个非空行字符串确定整个文档字符串的缩进的量。(我们不用第一行是因为它通常紧靠着字符串起始的引号,其缩进格式不明晰。)所有行起始的等于缩进量的空格都将被过滤掉。不应该发生缩进较少的行,但如果他们发生,应去除所有其前导空白。留白的长度应当等于扩展制表符的宽度(正常是 8 个空格)。

这里是一个多行文档字符串的示例:

>>>

>>> 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.
时间: 2024-10-19 12:47:15

python 函数的调用 和执行 小知识的相关文章

Python——函数的调用

调用函数的时候,如果函数的参数数量不对,会报TypeError的错误,比如 TypeError: abs() takes exactly one argument (2 given) abs函数只有一个参数,但给出了两个 参数类型如果不能被函数所接受,也会报错,比如 TypeError: bad operand type for abs(): 'str' str是错误的参数类型 数据类型转换 Python常用的函数还包括数据类型转换 >>> int('123') 123 >>

Python 函数的调用

一.调用过程:1 先找到名字2 根据名字调用代码 二.函数的返回值有几种方式:0->None(默认)1->返回1个值多个->元组 返回值注意:return的返回值没有类型限制 1. 没有return:返回None,等同于return None 2. return 一个值:返回该值 3. return val1,val2,val3:返回(val1,val2,val3) 三.函数调用的三种形式 1 语句形式:foo() 2 表达式形式:3*len('hello') 4 当中另外一个函数的参数

在Julia语言中调用Python函数

在PyCall扩展包中,模仿Python的import语句,提供了一个可以导入Python模块的@pyimport宏.并且,为能在Julia中使用模块内的函数和常量做了封装,以及支持在Julia与Python间的自动类型转换. 同时,它还提供了对Python对象进行底层操作的设施.其中包括能与不透明的Python对象相对应的'PyObjec'类型,以及在Julia语言中对Python函数进行调用且做类型转换的pycall. 安装 在Julia中,只需要使用Pkg.add("PyCall"

深入剖析php执行原理(4):函数的调用

本章开始研究php中函数的调用和执行,先来看函数调用语句是如何被编译的. 我们前面的章节弄明白了函数体会被编译生成哪些zend_op指令,本章会研究函数调用语句会生成哪些zend_op指,等后面的章节再根据这些op指令,来剖析php运行时的细节. 源码依然取自php5.3.29. 函数调用 回顾之前用的php代码示例: <?php function foo($arg1) { print($arg1); } $bar = 'hello php'; foo($bar); 在函数编译一章里已经分析过,

Python函数(函数定义、函数调用)用法详解

Python 中,函数的应用非常广泛,前面章节中我们已经接触过多个函数,比如 input() .print().range().len() 函数等等,这些都是 Python 的内置函数,可以直接使用. 除了可以直接使用的内置函数外,Python 还支持自定义函数,即将一段有规律的.可重复使用的代码定义成函数,从而达到一次编写.多次调用的目的. 比如,在程序中定义了一段代码,这段代码用于实现一个特定的功能.问题来了,如果下次需要实现同样的功能,难道要把前面定义的代码复制一次?如果这样做实在太傻了,

c++与python的互相调用

[编者按]最近一直发Python的资料,是因为Python的脚本扩展性.现在.net的动态语言特性已经很强大了,似乎脚本的作用并不明显.但是对于老式的C++,如果能够结合脚本语言的动态性,引用最近流行的一句话:必可以形成犄角之势!C++调用Python可以通过API,也可以通过Boost库实现,Boost.Python就是对API的包装,方便调用而已. 这是一篇比较老的介绍Boost.Python的文章,权当入门吧.因为文中一些东西现在不对…… Boost.Python是 Boost 中的一个组

python函数基础2

一.匿名函数 1. 匿名函数 python中除了用def关键字来声明函数之外,还有用lambda声明函数,这样的函数叫做匿名函数. 2. 简单函数转为匿名函数 匿名函数语法: lambda 参数:表达式 # 0参数 # 简单函数可以用匿名函数 def test(): return "hello world" a = test() print(a) # hello world # 匿名函数语法: lambda 参数:表达式 test = lambda: "hello world

10分钟学会Python函数基础知识

看完本文大概需要8分钟,看完后,仔细看下代码,认真回一下,函数基本知识就OK了.最好还是把代码敲一下. 一.函数基础 简单地说,一个函数就是一组Python语句的组合,它们可以在程序中运行一次或多次运行.Python中的函数在其他语言中也叫做过程或子例程,那么这些被包装起来的语句通过一个函数名称来调用. 有了函数,我们可以在很大程度上减少复制及粘贴代码的次数了(相信很多人在刚开始时都有这样的体验).我们可以把相同的代码可以提炼出来做成一个函数,在需要的地方只需要调用即可.那么,这样就提高了代码的

Python 3.X 调用多线程C模块,并在C模块中回调python函数的示例

由于最近在做一个C++面向Python的API封装项目,因此需要用到C扩展Python的相关知识.在此进行简要的总结. 此篇示例分为三部分.第一部分展示了如何用C在Windows中进行多线程编程:第二部分将第一部分的示例进行扩展,展示了如何在python中调用多线程的C模块:第三部分扩展了第二部分,增加了在C模块的线程中回调python的演示. 本文所用的环境为:64位Win7 + python 3.4 x86 + vs2010 一.windows下的C语言多线程程序 windows下多线程编程