函数

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的一系列语句,它们向调用者返回一些值。它也可以传递零个或多个参数,这些参数可以用于执行函数体。Python本身提供了一些内置函数。

Python内置函数,可直接调用。函数名是指向一个函数对象的引用,可以把函数名赋给一个变量,相当于给这个函数起了一个“别名”。

例如,abs是返回绝对值的内置函数。

1
2
3
4
x = -1
print("abs(x)的值:",abs(x))
a = abs                  # 变量a指向abs函数
print("a(x)的值:",a(x))   # 所以可通过a调用abs函数

执行以上程序会输出如下结果:

1
2
abs(x)的值: 1
a(x)的值: 1

自定义函数

除了内置函数,我们也可以自己定义函数,实现特定的功能。
自定义函数语法:

1
2
def 函数名(参数):
    函数体

定义函数使用def语句,依次写出函数名、括号、括号中的参数和冒号:,然后,在缩进块中编写函数体,返回值用return语句返回。如果没有return语句,函数执行完毕后会返回结果None。return None可简写为return。

空函数

如果想定义一个什么事也不做的空函数,可以用pass语句:

1
2
def nop():
    pass

调用函数

定义好函数以后,在函数名后面加上括号(),并传递相应的参数即可调用函数。

例如:

1
2
3
4
5
6
7
8
# 定义自己的返回绝对值的函数my_abs。
def my_abs(x):
    if x >= 0:
        return x
    else:
        return -x
a = -1
result = my_abs(a)  #调用自定义函数my_abs

参数

定义函数时,括号内定义的变量就是参数。定义时的参数,叫做形式参数,简称形参,调用函数时传递过来的实际的数值,叫做实际参数,简称实参。在Python的官方文档里面,形参的英文是parameter,实参的英文是argument。注意区别。

1
2
def func(foo, bar=None, **kwargs):
    pass

foo, bar和kwargs是形参。

1
func(42, bar=314, extra=somevar)

42, 314和somevar是实参。

形参分为以下五种参数:
位置或关键字参数(positional-or-keyword)
仅限位置参数(positional-only)
可变位置参数(var-positional)
可变关键字参数(var-keyword)
仅限关键字参数(keyword-only)

位置或关键字参数(positional-or-keyword)

指定一个可以作为 位置参数 传入也可以作为 关键字参数 传入的实参。这是默认的形参类型,

调用my_subtract()函数,你必须传入两个参数,不然会出现语法错误:

例如:

1
2
3
4
5
6
7
8
def my_subtract(x,y):
    return x-y

a = my_subtract(100,200)       # 传递参数100和200,x是100,y是200,此时的参数x和y是位置参数。
b = my_subtract(y=100,x=200)   # 传递参数100和200,x是200,y是100,此时的参数x和y是关键字参数。
print(a)   # -100
print(b)   # 100
c = my_subtract(100)           # 缺少参数,报错

执行以上程序会输出如下结果:

1
2
3
4
5
6
-100
100
Traceback (most recent call last):
  File "/home/main.py", line 8, in <module>
    c = my_subtract(100)
TypeError: my_subtract() missing 1 required positional argument: 'y'

仅限位置参数(positional-only)

指定一个只能按位置传入的参数。Python中没有定义仅限位置形参的语法。但是一些内置函数有仅限位置形参(比如 abs())。

可变位置参数(var-positional)

指定可以提供由一个任意数量的位置参数构成的序列(附加在其他形参已接受的位置参数之后)。这种形参可通过在形参名称前加缀 * 来定义,另一种方式是list或者tuple。

例如:

1
2
3
4
5
6
7
8
def calc(*numbers):
    sum = 0
    for n in numbers:
        sum = sum + n * n
    return sum
calc(1, 2)  # 结果为5
nums = [1, 2, 3]
calc(*nums) # 结果为14

可变关键字参数(var-keyword)

指定可以提供任意数量的关键字参数(附加在其他形参已接受的关键字参数之后)。这种形参可通过在形参名称前加缀 ** 来定义,在函数内部自动组装为一个dict。

例如:

1
2
3
def person(name, age, **kw):
    print('name:', name, 'age:', age, 'other:', kw)
person('Adam', 45, gender='M', job='Engineer') # 结果为name: Adam age: 45 other: {'gender': 'M', 'job': 'Engineer'}

除了**外,调用函数时,通过参数名字指定参数也是关键字参数。例如如下的f(c=3,a=1,b=2)中的a,b,c就是关键字参数。

1
2
3
def f(a,b,c):
    print(a,b,c)
f(c=3,a=1,b=2) # 1 2 3

当关键字参数使用时参数从左至右的关系已不再重要了,因为参数是通过变量名进行传递的,而不是通过其位置。

仅限关键字参数(keyword-only)

指定一个只能通过关键字传入的参数。仅限关键字形参可通过在函数定义的形参列表中包含单个可变位置形参或者在多个可变位置形参之前放一个*来定义,*后面的参数被视为仅限关键字参数。

例如:

1
2
3
def person(name, age, *, city, job):
    print(name, age, city, job)
person('Jack', 24, city='Beijing', job='Engineer’) # 结果为Jack 24 Beijing Engineer

如果函数定义中已经有了一个可变位置参数,后面跟着的仅限关键字参数就不再需要一个特殊分隔符*了:

例如:

1
2
3
def person(name, age, *args, city, job):
    print(name, age, args, city, job)
person('Jack', 24, 'args',city='Beijing', job='Engineer') # 结果为 Jack 24 ('args',) Beijing Engineer

仅限关键字参数必须传入参数名。如果没有,调用将报错。

例如:

1
2
3
4
5
person('Jack', 24, 'args','Beijing', 'Engineer') # 结果如下
Traceback (most recent call last):
  File "main.py", line 4, in <module>
    person('Jack', 24, 'args','Beijing', 'Engineer')
TypeError: person() missing 2 required keyword-only arguments: 'city' and 'job'

仅限关键字参数可以有缺省值,从而简化调用:

1
2
def person(name, age, *, city='Beijing', job):
    print(name, age, city, job)

由于仅限关键字参数city具有默认值,调用时,可不传入city参数:
person('Jack', 24, job='Engineer’) # 结果为Jack 24 Beijing Engineer

参数可以带有默认值

当一个或多个参数具有parameter = expression形式。对于具有默认值的参数,调用时可省略相应的参数,在这种情况下使用参数的默认值。如果参数具有默认值,则直到“*”的所有后续参数也必须具有默认值 - 这是语法限制。

例如:

1
2
3
4
5
6
7
def my_abs(x=100):
    if x >= 0:
        return x
    else:
        return -x

a = my_abs() #虽然没有传递参数,此时使用默认参数100,a结果是100

函数hello参数a,b是位置或关键字参数,其中b带有默认值。

1
2
3
4
5
def hello(a,b="world"):
    c = a + b
    return c

hello("hello","world")  hello("hello")的执行结果是一样的。

带有默认值的参数位置必须是最后。以下函数定义是错误的。

1
2
3
def hello(b="world",a):
    c = a + b
    return c

注意点1 默认值是在函数定义处计算的,下面的例子结果是5

例如:

1
2
3
4
5
6
7
i = 5

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

i = 6
f()  # 输出5,而不是6

注意点2 可变类型作为默认参数时,需要特别注意。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
def add_to(num, target=[]):
    target.append(num)
    return target

a = add_to(1)
b = add_to(2)
c = add_to(3)

print(a)
print(b)
print(c)

print(a is b)
print(b is c)
print(a is c)

执行以上程序会输出如下结果:

1
2
3
4
5
6
[1, 2, 3]
[1, 2, 3]
[1, 2, 3]
True
True
True

a,b,c是同一个列表,这是是列表的可变性在作怪。在Python中当函数被定义时,默认参数只会运算一次,而不是每次被调用时都会重新运算。你应该不要定义可变类型的默认参数。如果要使用的话,你可以这样写这个函数:

例如:

1
2
3
4
5
def add_to(num, target=None):
    if target is None:
        target = []
    target.append(a)
    return target

函数可以用位置或关键字参数、可变位置参数、可变关键字参数和仅限关键字参数,这5种参数都可以组合使用。但是请注意,参数定义的顺序必须是:位置或关键字参数、可变位置参数、仅限关键字参数和可变关键字参数。对于任意函数,都可以通过类似func(*args, **kw)调用。

__call__()特殊方法

函数也是一种对象。任何一个有__call__()特殊方法的对象都被当作是函数。

例如:

1
2
3
4
5
6
7
#声明自定义类SampleMore
class SampleMore(object):
    def __call__(self, a):
        return a + 5

add = SampleMore()   # 函数对象赋值给add变量
print(add(2))        # 调用函数

*args 和 **kwargs

并不是必须写成*args和**kwargs,只是约定俗成。 只有变量前面的*才是必须的. 也可以写成*var 和**vars。

返回函数

python中,函数也可以作为返回值。返回一个函数时,牢记该函数并未执行,返回函数中不要引用任何可能会变化的变量。

例如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
def func(x):
    print("func函数")
    def inner():
        return x * x
    return inner

a = func(10)  # a是函数对象
print(type(a))
result = a()  # 执行函数a
print(type(result))
print(result) # 打印函数执行结果

执行以上程序会输出如下结果:

1
2
3
4
func函数
<class 'function'>
<class 'int'>
100

转载请注明本网址。