Python从入门到精通,100天就够了!(9)——认识函数


在之前的学习中,如果我们需要算三个数的阶乘,我们需要写重复代码三次来计算,这是非常麻烦的。世界级的编程大师 Martin Fowler先生曾经说过:“ 代码有很多种坏味道,重复是最坏的一种!”。要写出高质量的代码首先要解决的就是重复代码的问题。对于开头讲的代码来说,我们可以将计算阶乘的功能封装到一个称为“函数”的代码块中,在需要计算阶乘的地方,我们只需要“调用函数”就可以了。

定义函数

数学上的函数通常形如y = f(x)或者z = g(x, y)这样的形式,在y = f(x)中,f是函数的名字,x是函数的自变量,y是函数的因变量;而在z = g(x, y)中,g是函数名,xy是函数的自变量,z是函数的因变量。Python中的函数跟这个结构是一致的,每个函数都有自己的名字、自变量和因变量。我们通常把Python中函数的自变量称为函数的参数,而因变量称为函数的返回值。

在Python中我们使用def关键字来定义函数,关键字空格后面写函数名,函数名后的圆括号中写传递给函数的参数,也就是刚才说的自变量,圆括号外紧跟冒号。一个函数要执行的代码块(要做的事情)也是通过缩进的方式来表示的,跟之前分支和循环结构的代码块是一样的。而函数执行完成后我们会通过return关键字来返回函数的执行结果,就是我们刚才说的函数的因变量。举例:



def add(a, b):
	c = a + b
	return c
	
	
# 使用时,直接输入参数即可
print(add(5, 6))    # 11

**注意:**函数整体的的前后需要留白才是比较规范的做法。

函数的参数
函数的默认值

如果函数中没有return语句,那么函数默认返回代表空值的None。另外,在定义函数时,函数也可以没有自变量,但是函数名后面的圆括号是必须有的。Python中还允许函数的参数拥有默认值,如果使用函数时没有传入新参数,则默认使用默认值举例:



# 定义摇色子的函数,n表示色子的个数,默认值为2
import random


def roll_dice(n=2):
    """摇色子返回总的点数"""
    total = 0
    for _ in range(n):  # n = 2
        total += random.randrange(1, 6)
    return total

# 如果没有指定参数,那么n使用默认值2,表示摇两颗色子
print(roll_dice())      # 8
可变参数

我们还可以实现一个对任意多个数求和的add函数,因为Python语言中的函数可以通过星号表达式语法来支持可变参数。所谓可变参数指的是在调用函数时,可以向函数传入0个或任意多个参数。将来我们以团队协作的方式开发商业项目时,很有可能要设计函数给其他人使用,但有的时候我们并不知道函数的调用者会向该函数传入多少个参数,这个时候可变参数就可以派上用场。下面的代码演示了用可变参数实现对任意多个数求和的add函数。

# 用星号表达式来表示args可以接收0个或任意多个参数
def add(*args):
    total = 0
    # 可变参数可以放在for循环中取出每个参数的值
    for val in args:
        total += val
    return total


# 在调用add函数时可以传入0个或任意多个参数
print(add())               # 0
print(add(1))              # 1
print(add(1, 2))           # 3
print(add(1, 2, 3))        # 6
print(add(1, 3, 5, 7, 9))  # 25
全局变量和局部变量

全局变量(没有写在任何函数里面的变量)
局部变量(定义在函数内部的变量)
函数里面的局部变量和全局变量是两个不同的变量,相互没有关系各自不影响。

在Python程序中搜索一个变量是按照 LEGB 顺序进行搜索的:
Local(局部作用域) —> Embeded(嵌套作用域) —> Global(全局作用域)
—> Built-in(内置作用域)
如果在这四个里面都没找到就会报错:NameError: name … not defined

所以我们可以通过global关键字声明使用全局变量或者定义一个局部变量将其放到全局作用域;nonlocal关键字声明使用嵌套作用域的变量(不使用局部变量)。举例:

x = 100
def foo():
    x = 200
    print(x)   # 输出局部变量x的值200
foo()
print(x)       # 输出全局变量x的值100

如果我不想在函数foo中定义局部变量x,想直接使用全局变量x,应该怎么做???
使用global声明!

x = 100
def foo():
    global x
    print(x)   # 输出全局变量x的值100
foo()
print(x)       # 输出全局变量x的值100

如果我不想在函数bar中定义局部变量x,想直接使用嵌套作用域中的x,应该怎么做???

x = 100
def foo():
    x = 200
    x = x + 1
    def bar():
        nonlocal x
        x = 300
        print(f'1.{x}')     # 1.300
    bar()
    print(f'2.{x}')         #2.300
foo()
print(x)                    # 100
用模块管理函数

如果同一个文件中有两个相同的函数,在我们调用时,会很容易出现问题。但是如果项目是团队协作多人开发的时候,团队中可能有多个程序员都定义了名为foo的函数,这种情况下怎么解决命名冲突呢?
答案其实很简单,Python中每个文件就代表了一个模块(module),我们在不同的模块中可以有同名的函数,在使用函数的时候我们通过import关键字导入指定的模块再使用完全限定名的调用方式就可以区分到底要使用的是哪个模块中的foo函数,代码如下所示。
module1.py

def foo():
    print('hello, world!')

module2.py

def foo():
    print('goodbye, world!')

test.py

import module1
import module2

# 用“模块名.函数名”的方式(完全限定名)调用函数,
module1.foo()    # hello, world!
module2.foo()    # goodbye, world!

在导入模块时,还可以使用as关键字对模块进行别名,这样我们可以使用更为简短的完全限定名。

test.py

import module1 as m1
import module2 as m2

m1.foo()    # hello, world!
m2.foo()    # goodbye, world!

上面的代码我们导入了定义函数的模块,我们也可以使用from...import...语法从模块中直接导入需要使用的函数。这个方法同样可以使用as关键词对模块进行别名。
test.py

from module1 import foo as f1
from module2 import foo as f2

f1()    # hello, world!
f2()    # goodbye, world!

函数是功能相对独立且会重复使用的代码的封装。学会使用定义和使用函数,就能够写出更为优质的代码。当然,Python语言的标准库中已经为我们提供了大量的模块和常用的函数,用好这些模块和函数就能够用更少的代码做更多的事情。

请添加图片描述

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值