Python Crash Course读书笔记 - 第8章:FUNCTIONS

这章内容较多,开始进入高阶部分。

定义函数

先看一个没有参数的函数:

$ cat bell.py
def bell():
    """ voice of my doorbell"""
    print("Ding Dong!")

bell()
$ python3 bell.py
Ding Dong!

函数的定义以def开始,以:结束。函数体从其下带缩进的行开始,直到遇到没有缩进的行函数体结束。
""""""之间是注释,用于生成文档,这和#不同。

参数定义在()之间,用逗号分割,只要参数名,无需类型。

$ cat echo.py
def echo(msg):
    print(msg)

echo("Hello!")
echo("See you!")
$ python3 echo.py
Hello!
See you!

在函数定义中的参数称为parameters(形参),在函数调用时传入的参数称为arguments(实参)。

传递参数

第一种方式为按照位置传递,最常见。但注意参数顺序不要搞错,否则可能出现逻辑错误。

第二种方式按照形参的关键字传递,定义时并无不同,但调用时如下:

func(parameter1=value1, parameter2=value2, ...)

参数可定义默认值。默认值使此参数变为可选:

def func(parameter1, parameter2=default_value)

例如:

def echo(msg, where='BJ'):
    print(where + ":" + msg)

echo("Hello!")
echo("See you!", 'SH')

带默认值参数的定义只能在非默认值参数定义之后:

$ cat echo.py
def echo(msg='empty', where):
    print(where + ":" + msg)

$ python3 echo.py
  File "echo.py", line 1
    def echo(msg='empty', where):
            ^
SyntaxError: non-default argument follows default argument

有一个通用的默认值就是None,相对于SQL中的Null,例如:

def func(a, b=None, c=None)

然后在函数体中可以结合条件表达式判断:

if b: # 如果b有赋值,如果b非空

看一个测试:

>>> a=not True
>>> a
False
>>> a=not None
>>> a
True
>>> a=not ''
>>> a
True
>>> a=not 'value'
>>> a
False

返回值

返回值通过return返回,在函数定义时没有区别。

$ cat sum.py
def sum(a, b):
    return a + b

print(f"result is: {sum(1, 2)}")
$ python3 sum.py
result is: 3

返回值可返回简单类型,如数值,字符串。也可返回复杂类型,如List,字典,Tuple,Set等。
例如:

$ cat returntest.py
def returntest():
    #return set({1,2,3})
    #return {1,2,3}
    #return 1,2,3
    return {"k1":1, "k2":2, "k3":3}

print(returntest())

输出分别为:

{1, 2, 3}
{1, 2, 3}
(1, 2, 3)
{'k1': 1, 'k2': 2, 'k3': 3}

传递列表

列表作为参数时,传递的是reference,而非value,因此列表在函数中可修改。

$ cat friends.py
def add_friends(friendslist, friendname):
    friendslist.append(friendname)

def del_friends(friendslist, friendname):
    friendslist.remove(friendname)

my_friends = ['tom', 'jerry']
add_friends(my_friends, 'flora')
add_friends(my_friends, 'grace')
del_friends(my_friends, 'jerry')
print(my_friends)
$ python3 friends.py
['tom', 'flora', 'grace']

如果你希望列表不被改变,则可以传递列表的拷贝,例如:

add_friends(my_friends[:], 'flora')
add_friends(my_friends[:], 'grace')
del_friends(my_friends[:], 'jerry')

这里说的List是广义的,传递字典也是by reference:

$ cat dictparam.py
def addobject(dict):
    dict['kn'] = 'vn'

d = {'k1':'v1', 'k2':'v2'}
addobject(d)
print(d)
$ python3 dictparam.py
{'k1': 'v1', 'k2': 'v2', 'kn': 'vn'}

传递不定数量参数

有两种方式,***

第一种方式其实挺常见的,例如C语言中的main( int argc, char *argv[] )
*parameter定义,实际上传递的是tuple(元组),因此在函数体中可以用for...in遍历。
不定数量参数只能定义在参数列表的最后。为不定数量参数指定默认值是错误的,也是不必要的。

$ cat friends.py
def add_friends(friendslist, *friendsname):
    for friend in friendsname:
        friendslist.append(friend)

my_friends = ['tom', 'jerry']
add_friends(my_friends, 'flora', 'grace')
print(my_friends)

$ python3 friends.py
['tom', 'jerry', 'flora', 'grace']

第二种方式用**parameter定义,实际传递的是一系列键值对,如key=value, key=value, ...

$ cat cars.py
def cars(vendor, model, **carinfo):
    carinfo['vendor'] = vendor
    carinfo['model'] = model

    return carinfo

print(cars('BMW', 'SUV'))
print(cars('TOYOTA', 'pickup', color='white', price=1000));

$ python3 cars.py
{'vendor': 'BMW', 'model': 'SUV'}
{'color': 'white', 'price': 1000, 'vendor': 'TOYOTA', 'model': 'pickup'}

在本节Pizza示例中,提到一个单词topping,意为配料,翻译为浇头(或湖南人说的码子)就更好理解了。

在模块中存放函数

函数可重用,使程序变得简洁。
函数可存于单独的文件,称为module,然后通过import引入调用其的文件。

import modulename

调用时使用以下形式:

module_name.function_name()

示例:

$ cat cars_module.py
def cars(vendor, model, **carinfo):
    carinfo['vendor'] = vendor
    carinfo['model'] = model

    return carinfo

$ cat main.py
import cars_module

print(cars_module.cars('BMW', 'SUV'))
print(cars_module.cars('TOYOTA', 'pickup', color='white', price=1000));

$ python3 main.py
{'vendor': 'BMW', 'model': 'SUV'}
{'color': 'white', 'price': 1000, 'vendor': 'TOYOTA', 'model': 'pickup'}

也可以import指定的函数:

from module_name import function_0[, function_1, function_2 ...]

如果import的函数命名与本文件冲突,则可以指定别名:

from module_name import function_0 as alias

module也可指定别名:

import modulename as module_alias

import所有函数:

from module_name import *

这种方式和import module_name有区别,在调用时无需指定module名称和.

$ cat main.py
from cars_module import *

print(cars('BMW', 'SUV'))
print(cars('TOYOTA', 'pickup', color='white', price=1000));

但这种方式是不建议的,特别是比较大的项目,还是建议import指定的函数或模块。

函数的风格

以下都是最佳建议,即约定,不按照做并不会导致错误。

函数名应准确描述其功能,只应包含小写和下划线(_)。
函数必须包括说明,使用docstring格式,也就是"""
参数赋予默认值时,等号两侧不要留空格。例如param=None而非param = None
函数的参数可另起一行,带两个<tab>缩进。
函数与函数间带两个空行。
import语句应放在文件首,除非有注释。

发布了370 篇原创文章 · 获赞 43 · 访问量 55万+

猜你喜欢

转载自blog.csdn.net/stevensxiao/article/details/103998931