【Python】5.函数——面向过程的编程

目录

一、概述

二、函数的定义及调用

1. 为什么要用函数

2. 函数的定义及调用

2.1 定义

2.2 调用

3. 参数传递

3.1 形参与实参

3.2 位置参数

3.3 关键字参数

3.4 默认参数

3.5 可变长参数*args

3.6 可变长参数**kwargs

4. 函数体与变量作用域 

5. 返回值

5.1 单个返回值

5.2 多个返回值——以元组的形式

5.3 可以有多个return 语句,一旦其中一个执行,代表了函数运行的结束

5.4 没有return语句,返回值为None 

6. 几点建议

三、匿名函数

1. 基本形式

2. 常用用法

四、面向过程和面向对象

五、重难点回顾


一、概述

二、函数的定义及调用

1. 为什么要用函数

  1. 提高代码复用性——抽象出来,封装为函数
  2. 将复杂的大问题分解成一系列小问题,分而治之——模块化设计的思想
  3. 利于代码的维护和管理

顺序式 

输入:

# 5的阶乘
n = 5
res = 1
for i in range(1, n+1):
    res *= i
print(res)

# 20的阶乘
n = 20
res = 1
for i in range(1, n+1):
    res *= i
print(res)

输出:

120
2432902008176640000

抽象成函数

输入:

def factoria(n):
    res = 1
    for i in range(1,n+1):
        res *= i
    return res


print(factoria(5))
print(factoria(20))

输出:

120
2432902008176640000

2. 函数的定义及调用

白箱子:输入——处理——输出

三要素:参数、函数体、返回值

2.1 定义

def  函数名(参数):

  函数体

  return 返回值

# 求正方形的面积
def area_of_square(length_of_side):
    square_area = pow(length_of_side, 2)
    return square_area    

2.2 调用

函数名(参数)

输入:

area = area_of_square(5)
area

输出:

 

3. 参数传递

3.1 形参与实参

  • 形参(形式参数):函数定义时的参数,实际上就是变量名
  • 实参(实际参数):函数调用时的参数,实际上就是变量的值

3.2 位置参数

  • 严格按照位置顺序,用实参对形参进行赋值(关联)
  • 一般用在参数比较少的时候

输入:

def function(x, y, z):
    print(x, y, z)
    
    
function(1, 2, 3)    # x = 1; y = 2; z = 3

输出:

1 2 3
  • 实参与形参个数必须一一对应,一个不能多,一个不能少

输入:

function(1, 2)

输出:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-6-2a7da6ff9675> in <module>
----> 1 function(1, 2)

TypeError: function() missing 1 required positional argument: 'z'

输入:

function(1, 2, 3, 4)

输出:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-8-748d3d0335e6> in <module>
----> 1 function(1, 2, 3, 4)

TypeError: function() takes 3 positional arguments but 4 were given

3.3 关键字参数

  • 打破位置限制,直呼其名的进行值的传递(形参=实参)
  • 必须遵守实参与形参数量上一一对应
  • 多用在参数比较多的场合

输入:

def function(x, y, z):
    print(x, y, z)
    
    
function(y=1, z=2, x=3)    # x = 1; y = 2; z = 3

输出:

3 1 2
  • 位置参数可以与关键字参数混合使用
  • 但是,位置参数必须放在关键字参数前面

输入:

function(1, z=2, y=3)

输出:

1 3 2

输入:

function(1, 2, z=3)

输出:

1 2 3
  • 不能为同一个形参重复传值 

输入:

def function(x, y, z):
    print(x, y, z)


function(1, z=2, x=3)

输出:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-12-f385272db011> in <module>
      3 
      4 
----> 5 function(1, z=2, x=3)

TypeError: function() got multiple values for argument 'x'

3.4 默认参数

  • 在定义阶段就给形参赋值——该形参的常用值
  • 默认参数必须放在非默认参数后面
  • 调用函数时,可以不对该形参传值
  • 机器学习库中类的方法里非常常见

输入:

def register(name, age, sex="male"):
    print(name, age, sex)


register("大杰仔", 18)

输出:

大杰仔 18 male
  • 也可以按正常的形参进行传值

输入:

register("林志玲", 38, "female")

输出:

林志玲 38 female
  • 默认参数应该设置为不可变类型(数字、字符串、元组)

输入:

def function(ls=[]):
    print(id(ls))
    ls.append(1)
    print(id(ls))
    print(ls)


function()

输出:

1759752744328
1759752744328
[1]

输入:

function()

输出:

1759752744328
1759752744328
[1, 1]

列表虽然地址未变,但是内容已经发生了变化,调用时根据地址追踪到内容。

输入:

function()

输出:

1759752744328
1759752744328
[1, 1, 1]

输入:

def function(ls="Python"):
    print(id(ls))
    ls += "3.7"
    print(id(ls))
    print(ls)
    
    
function()

输出:

1759701700656
1759754352240
Python3.7

ls 和 ls+“3.7”之后的地址发生了变化,调用时根据地址:1759701700656追踪到的是”Python”,所以不会出现和列表一样的记忆功能。

输入:

function()

输出:

1759701700656
1759754353328
Python3.7

输入:

function()

输出:

1759701700656
1759754354352
Python3.7
  • 让参数变成可选的

输入:

def name(first_name, last_name, middle_name=None):
    if middle_name:
        return first_name+middle_name+last_name
    else:
        return first_name+last_name
    
    
print(name("大","仔"))
print(name("大", "仔", "杰"))

输出:

大仔
大杰仔

3.5 可变长参数*args

  • 不知道会传过来多少参数 *args
  • 该形参必须放在参数列表的最后

输入:

def foo(x, y, z, *args):
    print(x, y ,z)
    print(args)
    
    
foo(1, 2, 3, 4, 5, 6)    # 多余的参数,打包传递给args

输出:

1 2 3
(4, 5, 6)
  • 实参打散

输入:

def foo(x, y, z, *args):
    print(x, y ,z)
    print(args)

    
foo(1, 2, 3, [4, 5, 6])    

输出:

1 2 3
([4, 5, 6],)

输入:

foo(1, 2, 3, *[4, 5, 6])   # 打散的是列表、字符串、元组或集合

“*”将列表、字符串、元组或集合打散。

输出:

1 2 3
(4, 5, 6)

3.6 可变长参数**kwargs

输入:

def foo(x, y, z, **kwargs):
    print(x, y ,z)
    print(kwargs)
    
    
foo(1, 2, 3, a=4, b=5, c=6)    #  多余的参数,以字典的形式打包传递给kwargs

多余参数以字典的形式打包传递给kwargs

输出:

1 2 3
{'a': 4, 'b': 5, 'c': 6}

4. 函数体与变量作用域 

  • 函数体就是一段只在函数被调用时,才会执行的代码,代码构成与其他代码并无不同
  • 局部变量——仅在函数体内定义和发挥作用

输入:

def multipy(x, y):
    z = x*y
    return z   


multipy(2, 9)
print(z)            # 函数执行完毕,局部变量z已经被释放掉了

输出:

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-29-9a7fd4c4c0a9> in <module>
      5 
      6 multipy(2, 9)
----> 7 print(z)            # 函数执行完毕,局部变量z已经被释放掉了

NameError: name 'z' is not defined
  • 全局变量——外部定义的都是全局变量
  • 全局变量可以在函数体内直接被使用

输入:

n = 3
ls = [0]
def multipy(x, y):
    z = n*x*y
    ls.append(z)
    return z   


print(multipy(2, 9))
ls

函数调用完成后,z会被释放掉。

输出:

54
[0, 54]
  • 通过global 在函数体内定义全局变量 

输入:

def multipy(x, y):
    global z
    z = x*y
    return z 


print(multipy(2, 9))
print(z)

z在函数调用后不会被释放掉。

输出:

18
18

5. 返回值

5.1 单个返回值

输入:

def foo(x):
    return x**2


res = foo(10)
res

输出:

100

5.2 多个返回值——以元组的形式

输入:

def foo(x):
    return 1, x, x**2, x**3    # 逗号分开,打包返回


print(foo(3))

输出:

(1, 3, 9, 27)

输入:

a, b , c, d = foo(3)       # 解包赋值
print(a)
print(b)
print(c)
print(d)

输出:

1
3
9
27

5.3 可以有多个return 语句,一旦其中一个执行,代表了函数运行的结束

输入:

def is_holiday(day):
    if day in ["Sunday", "Saturday"]:
        return "Is holiday"
    else:
        return "Not holiday"
    print("啦啦啦德玛西亚,啦啦啦啦")       # 你丫根本没机会运行。。。
    
    
print(is_holiday("Sunday"))
print(is_holiday("Monday"))

输出:

Is holiday
Not holiday

5.4 没有return语句,返回值为None 

输入:

def foo():
    print("我是孙悟空")

res = foo()
print(res)

输出:

我是孙悟空
None

6. 几点建议

1、函数及其参数的命名参照变量的命名

  • 字母小写及下划线组合
  • 有实际意义

2、应包含简要阐述函数功能的注释,注释紧跟函数定义后面

def foo():
    # 这个函数的作用是为了给大家瞅一瞅,你瞅啥,瞅你咋地。。。。
    pass

3、函数定义前后各空两行

def f1():
    pass

                 # 空出两行,以示清白
def f2():
    pass


def f3(x=3):    # 默认参数赋值等号两侧不需加空格
    pass


# ...

4、默认参数赋值等号两侧不需加空格

三、匿名函数

1. 基本形式

lambda 变量: 函数体

2. 常用用法

在参数列表中最适合使用匿名函数,尤其是与key = 搭配

  • 排序sort() sorted()

输入:

ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
ls.sort()
ls

输出:

[(76, 94), (79, 100), (85, 85), (86, 71), (93, 88)]

输入:

ls.sort(key = lambda x: x[1])
ls

输出:

[(86, 71), (85, 85), (93, 88), (76, 94), (79, 100)]

输入:

ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
temp = sorted(ls, key = lambda x: x[0]+x[1], reverse=True)
temp

输出:

[(93, 88), (79, 100), (85, 85), (76, 94), (86, 71)]
  • max() min()

输入:

ls = [(93, 88), (79, 100), (86, 71), (85, 85), (76, 94)]
n = max(ls, key = lambda x: x[1])
n

输出:

(79, 100)

输入:

n = min(ls, key = lambda x: x[1])
n

输出:

(86, 71)

四、面向过程和面向对象

面向过程——以过程为中心的编程思想,以“什么正在发生”为主要目标进行编程。 冰冷的,程序化的

面向对象——将现实世界的事物抽象成对象,更关注“谁在受影响”,更加贴近现实。  有血有肉,拟人(物)化的

  • 以公共汽车为例

“面向过程”:汽车启动是一个事件,汽车到站是另一个事件。。。。

在编程序的时候我们关心的是某一个事件,而不是汽车本身。

我们分别对启动和到站编写程序。

"面向对象":构造“汽车”这个对象。

对象包含动力、服役时间、生产厂家等等一系列的“属性”;

也包含加油、启动、加速、刹车、拐弯、鸣喇叭、到站、维修等一系列的“方法”。

通过对象的行为表达相应的事件

五、重难点回顾

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值