【Python 随笔】函数

【Python 随笔】函数

定义一个函数

你可以定义一个由自己想要功能的函数,以下是简单的规则:

  • 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号()。
  • 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
  • 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
  • 函数内容以冒号起始,并且缩进。
  • return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的 return 相当于返回 None。

下面是语法格式:

def functionname(parameters):
   "函数_文档字符串"
   function_suite
   return [expression]

下面是一个简单的例子:

def fib(n):
    """Print a Fibonacci series up to n."""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a+b
    print()


fib(2000)

参数默认值

最有用的形式是对一个或多个参数指定一个默认值。这样创建的函数,允许更少的参数调用,比如:

def ask_ok(prompt, retries=4, reminder='Please try again!'):
    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 ValueError('invalid user response')
        print(reminder)

这个函数可以通过几种方式调用:

  • 只给出必需的参数: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!')

值得注意的是:函数的默认值是在函数定义的过程计算的,并且只会计算一次;所以下面代码只会打印 5。

i = 5

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

i = 6
f()

由于默认值只会计算(执行)一次,所以默认值为可变对象(列表、字典以及大多数类实例)时要重点注意。

比如,下面函数中的L默认值是一个可变的空列表,在后续对该列表操作时,都会直接改变该列表。

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

重点注意:Python 中有可变序列和不可变序列,当作参数传递时与上面的两个例子一样。


关键字参数

函数的定义和默认参数定义一样,下面是一个例子:

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, "!")

主要的区别就是传参方式不同,下面都是被允许的方式:

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

其实也就是使用 变量名加值 的方式进行传递,下面是不被运行的情况:

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

值得注意的是:不能对同一个参数多次赋值,并且当一个参数带有默认值,后面的所有参数都必须有默认值,否则运行时报错。


参数名前面带有型号

这个功能非常好,很灵活。

def doubleStar(*double):
    print("数据类型:%s" % type(double), double)


doubleStar(10)

# 运行结果
数据类型:<class 'tuple'> (10,)

也就是说参数名前面带有一个星,就表示元组。当然也可以通过以下方式直接传递一个元组:

doubleStar(*(10, 20))

# 运行结果
数据类型:<class 'tuple'> (10, 20)

注意:在参数前面加了一个星号,这就表示直接传递一个元组进去。

还有一个使用方法就是传递字典,参数名前面加两颗星:

def doubleStar(**double):
    print("数据类型:%s" % type(double), double)


doubleStar(key = 1, key2 = 2)

# 运行结果
数据类型:<class 'dict'> {'key': 1, 'key2': 2}

这种传参方式和关键字参数一样,但是千万不要搞混了。下面展示了直接传递字典:

doubleStar(**{'key': 1, 'key2': 2})

# 运行结果
数据类型:<class 'dict'> {'key': 1, 'key2': 2}

值得注意的是:

  1. 带有两颗星号的参数名,必须放在带有一颗星号的参数名后面。
  2. 一般情况下,带有星号的参数名,在调用函数时这些可变参数参数都是可选的,所以形式参数最好放在前面。
    正确格式:def cheeseshop(kind, *arguments, **keywords)
    但是如果函数定义成:def cheeseshop(*arguments, kind="\"),则参数 kind 可以当作关键字参数使用。
    总之 Python 对参数的使用花样还是挺多的,剩下的就需要自己去摸索了。

return 语句

return语句[表达式]退出函数,选择性地向调用方返回一个表达式。不带参数值的 return 语句返回 None。之前的例子都没有示范如何返回数值,下例便告诉你怎么做:

# 可写函数说明
def sum( arg1, arg2 ):
   # 返回2个参数的和."
   total = arg1 + arg2
   print "函数内 : ", total
   return total
 
# 调用sum函数
total = sum( 10, 20 )

# 运行结果
函数内 :  30

变量引用顺序

每个函数在执行的时候都会引入一个新的本地符号表用来存放函数参数和局部变量以及封闭函数的信息。

Python 引用变量的顺序为:本地符号表->封闭函数的本地符号表->全局符号表->内置名称表。

所谓的封闭函数就是在一个函数中嵌套了另一个函数,这个外层的函数就叫做封闭函数;你可以把它理解为一个包裹,包裹了其它函数。下面是个例子:

def receiving_function(f): # 这个就是封闭函数
    f()

def parent_function():
    y = 10

    def child_function(): # 这个就是嵌套函数
        print(y)

    receiving_function(child_function)

下图中左边表示带有封闭函数的变量获取顺序,有图表示了没有封闭函数时变量获取顺序。


参考资料

python函数参数前面单星号(*)和双星号(**)的区别

定义函数

Python 函数

posted @ 2021-01-11 22:32  用户TT  阅读(101)  评论(0)    收藏  举报