第九章 函数基础

一 没有使用函数式编程之前带来的问题

  1. 代码的组织结构不清晰,可读性差
  2. 实现重复的功能时,你只能重复编写实现功能的代码,导致代码冗余,白白耗费精力
  3. 假如某一部分功能需要扩展或更新时,需要找出所有实现此功能的地方,一一修改,无法统一管理,加大了维护难度


二 函数是什么

  1. 函数是对实现某一功能的代码的封装
  2. 函数可以实现代码的复用,从而减少代码的重复编写

Python 中函数的特性:

  1. 函数的参数可以是python 中的任意数据类型,并且参数的数量可以是零个或多多个。

  2. 函数也可以通过关键字 return 返回任何数量的 Python 中的任意数据类型,作为结果



三 函数分类

  • 内置函数

​ 为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。

​ 对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max()

  • 自定义函数

​ 很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某 种功能,以后,在遇到应用场景时,调用自定义的函数即可。



四 函数的定义

1 如何自定义函数?

函数的定义中可能会涉及到如下几点:

语法

def 函数名(参数1,参数2,参数3,...):
    '''注释'''
    函数体
    return 返回的值

# 函数名要能反映函数本身所实现的意义

  • def:表示定义函数的关键字
  • 函数名:函数的名称,日后根据函数名调用函数
  • 函数体:函数中进行一系列的逻辑计算,如:发送邮件、计算出 [11,22,38,888,2]中的最大数等...
  • 参数:为函数体提供数据
  • return:当函数执行完毕后,可以给调用者返回数据。

实例

def f():
    pass

def myfunc():
    's' + 1

2. 函数在定义阶段都干了哪些事?

只检测定义函数所要求的语法,不执行函数体内的代码

也就说,语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在调用执行时才会知道。

def get_result():
    r - 1

get_result()

# 调用函数后会输出如下错误提示结果:
NameError: name 'r' is not defined

get_reuslt = """
    r - 1
"""



五、函数调用

1 函数调用

函数的调用:函数名加小括号
func()

  1. 先找到名字
  2. 根据名字调用代码
def myfunc():
    url = "www.qfedu.com"
# 调用    
myfunc()  

2. 函数使用的原则:必须先定义,才可以调用

定义函数就是在定义“变量”,“变量”必须先定义后,才可以使用。
不定义而直接调用函数,就相当于在使用一个不存在的变量名
# 情景一
def foo():
    print('from foo')
    func()

foo()  # 报错

# 情景二
def func():
    print('from func')
def foo():
    print('from foo')
    func()

foo()  # 正常执行

# 情景三
def foo():
    print('from foo')
    func()

def func():
    print('from func')

foo()  # 可以正常执行吗?

3. 总结:

  • 函数的使用,必须遵循的原则是:先定义,后调用

  • 在使用函数时,我们一定要明确地区分定义阶段和调用阶段

  • 在函数体里面的任何代码都只是定义而已,只有在调用此函数时,这个函数内的代码才会执行。

# 定义阶段
def foo():
    print('from foo')
    func()
def func():
    print('from func')

# 调用阶段
foo()

六、函数返回值 return

  • 不定义,默认返回 None
  • 返回多个值时,每个值用逗号隔开,也就是元组的形式

1. 如何自定义返回值

使用 return 关键字

def foo():
    x = 1
    return x

ret = foo()  # 给你, 这一步相当于下面的一行代码,就是 foo() 执行完毕,
                 #创建了 1 这个对象,之后把变量名  ret  分配给对象  1 
# ret = 1

print(ret)

2. 接收函数的返回值

注意:必须先执行函数,此函数的返回值才会被创建并返回

# 可以使用一个变量来接收一个函数的返回值
ret = foo()

print("foo 函数的返回值是:", ret)

# 也可以把函数的返回值直接作为参数来使用,这时函数 `foo` 会先被执行,
# 之后把其返回值放在其原来的位置,以供 `print` 函数作为参数使用
print("foo 函数的返回值是:", foo())

在函数执行的过程中,当在函数体内遇到了 return关键字,函数就会立刻停止执行,并返回其返回值, return 之后的代码不会被执行。

def func():
    x = 100
    return
    print('ok')   # 不执行

print('qf')       # 执行,因为此代码已不是函数体内的代码了,注意缩进。
func()

定义一个有返回值的函数,并调用此函数

def echo(arg):
    return arg  # 用关键字 return 定义函数的返回

# 调用函数,并用一个变量接收其返回值
ret = echo('yangge')
print(ret)

# 执行 print 的结果
'yangge'

# 当一个函数没有显式的调用 return 时,默认会返回 None
def do_nothing():
     print('ok')

# 下面的方式,会先执行函数体内的代码,之后把函数自身的返回值
# 放在其函数原来的位置,并且作为参数给 print
print(do_nothing())
ok                            # 函数体本身执行的结果
None                          # 函数自身的返回值

# 函数可以返回一个以及多个Python 的任何数据类型的结果    



七、函数的参数

函数的参数是为函数体内的逻辑代码提供数据的。

以下是重点,需要加强练习,理解原理,掌握用法和技巧

函数的参数分为 形参和实参

1. 什么是形参

对于函数来说,形式参数简称形参,是指在定义函数时,定义的一个变量名;

下面的代码中,x、y、z 就是形参

def foo(x, y, z):
    print("第一个参数是", x)
    print("第二个参数是", y)
    print("第三个参数是", z)

2. 什么是实参

对于函数来说,实际参数简称实参。
是指在调用函数时传入的实际的数据,这会被绑定到函数的形参上;
函数调用时,将值绑定到变量名上,函数调用结束,解除绑定,并且实参将不再存在于程序中。

foo(1,2,3)

上面的 1、 2 和 3 都是实参

3. 形参分为:位置参数和默认参数

a. 位置参数

def send_mail(to, title, content):
    send_info = {"user": to,
                 "title": title,
                 "content": content}
    return send_info

形参的位置参数,在调用函数时必须给其传递实参。
但是,在函数内使用与否 ,没有限制。

b. 默认参数

def default_mail(title,  content,  to='xiannv@163.com'):
    send_info = {"user": to,
                 "title": title,
                 "content": content}
    return send_info

默认参数在函数定义的时候,就已经绑定了实际的值了。
调用函数时,可以给其传值,也可以不传。

  • 不传值 就使用定义函数时绑定的值。
  • 传值 就是使用传递的值。

同样,在函数内使用与否 ,没有限制。

4. 实参分为:位置参数和关键字参数

​说的实参实质就是在调用函数时,给位置参数的进行赋值,这个行为通常叫做给函数 传参

​因此,大家要明白,这里的 位置参数关键字参数 是在函数调用的情况下的概念。

a. 位置参数传递参数

给形参的位置参数传参

info = send_mail("xiannv@163.com", 
                 "一生问候", 
                 "告诉你,一想到你,我这张丑脸上就泛起微笑。")

print(info)

还可以这样传参

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

tuple_vec = (1, 0, 1)
dict_vec = {'x': 1, 'y': 0, 'z': 1}

>>> myfunc(*tuple_vec)
1, 0, 1

>>> myfunc(**dict_vec)
1, 0, 1

给默认参数传参

info = default_mail( "一生问候", 
                     """因为你太美好了,
                        我等你等了这么久,
                        才能跟你在一起,
                        我害怕得不得了,
                        生怕自己搞砸了""",
                     "xiannv@163.com", )

print(info)

当使用实参的位置参数传参时,需要考虑到定义函数时的形参的位置。

image

b. 关键字参数传递参数

info = send_mail(content="我爱你,不光是因为你的样子,还因为和你在一起时,我的样子", 
                 title="一生问候",
                 to="jingjing@126.com")

print(info)

使用关键字参数传参时,不必考虑形参的位置。但是需要注意,关键字必须和在定义函数时形参一致。

实参角度的参数结论:

  1. 在调用函数时,给形参的位置参数或形参的默认参数进行赋值时,可以用实参的位置参数进行传参; 此时传递的实参的顺序,必须和形参的位置顺序一一对应

  2. 在调用函数时,给形参的位置参数或形参的默认参数进行赋值时, 也可以使用实参的关键字参数进行传参; 此时,关键字参数之间是不区分位置顺序的

  3. 在调用函数时,形参的默认参数不传参数给它,此时,默认参数的值就是原来定义的值;假如传了参数,就使用传入的参数的值。

5. 万能参数: *args**kwargs

a. 用 * 表达式接收传进来的任意多个未明确定义的位置参数

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

foo(1, 3, 5, 6)

在函数体内接收到的参数会放在元组中

b. 用 ** 表达式接收传进来的任意多个未明确定义的关键字参数

def func(x, y, **kwargs):
    print(kwargs)

func(1, 3, name='shark', age=18)

在函数体内接收到的参数会放在字典中

这么重要,总结一下吧

函数参数从形参角度来说,就是在定义函数时定义的变量名,分为三种:

  1. 位置参数 如: arg1,arg2

所用的参数是有位置的特性的,位置是固定的,传参时的值也是要一一对应的

  1. 默认参数 如:arg = 5
  2. 动态参数 如: args,*kwargs, 可以同时用

==三种形参在定义函数时的顺序如下:==

In [108]: def position_arg(arg1, arg2, *args, k1='v1', **kwargs):
     ...:     pass
     ...:

函数参数从实参角度来说,就是在调用函数时给函数传入的实际的值,分为两种

  1. 位置参数

在传参时,值和定义好的形参有一一对应的关系

  1. 关键字参数

在传参时,利用key = value 的方式传参,没有对位置的要求



八、匿名函数

lambda 是用一条语句来表式的匿名函数,可以用它来代替简单的小函数。

# 与函数有相同的作用域,但是匿名意味着引用计数为0,使用一次就释放,除非让其有名字

# 先看一个简单的普通函数 
In [126]: def f1(arg1,arg2):
     ...:     return arg1 + arg2
     ...:

# 再看 lambda 表达式

# 语法格式:
# lambda 参数:函数体

# 示例:
In [127]: lambda arg1,arg2: arg1 + arg2
Out[127]: <function __main__.<lambda>>

sum_number = lambda arg1,arg2:arg1 + arg2

sum_number(5, 6)

作业

源数据

5497 click_sum:3 percent:100.0%
4826 click_sum:1 percent:0.0%
6522 click_sum:201 percent:51.24%
6367 click_sum:712 percent:1.83%
6368 click_sum:1462 percent:4.79%
5346 click_sum:733 percent:6.68%
3812 click_sum:29 percent:0.0%
4841 click_sum:851 percent:0.0%
5873 click_sum:217 percent:28.57%
6316 click_sum:4 percent:0.0%
6900 click_sum:28 percent:7.14%
7416 click_sum:6 percent:0.0%
6989 click_sum:50 percent:0.0%
6990 click_sum:21 percent:0.0%
4944 click_sum:15 percent:100.0%
6485 click_sum:88 percent:0.0%
7039 click_sum:28 percent:92.86%
2432 click_sum:153 percent:5.88%
6018 click_sum:4 percent:0.0%
6024 click_sum:28 percent:100.0%
1930 click_sum:175 percent:6.29%
2444 click_sum:3725 percent:7.54%
2451 click_sum:3505 percent:0.23%
7060 click_sum:111 percent:51.35%
3989 click_sum:715 percent:41.54%
6039 click_sum:42 percent:0.0%
2457 click_sum:13 percent:46.15%
5530 click_sum:64 percent:0.0%
7582 click_sum:124 percent:0.81%
7071 click_sum:8 percent:0.0%
5537 click_sum:5 percent:100.0%
4763 click_sum:1 percent:100.0%
5540 click_sum:186 percent:0.54%
5033 click_sum:2337 percent:73.47%
4522 click_sum:1668 percent:0.54%
4523 click_sum:62 percent:1.61%
7084 click_sum:432 percent:1.85%
6063 click_sum:247 percent:0.0%
5553 click_sum:68 percent:0.0%
6583 click_sum:13 percent:100.0%
6127 click_sum:22 percent:0.0%
6057 click_sum:6 percent:0.0%
6138 click_sum:15 percent:6.67%
4607 click_sum:10 percent:0.0%
6652 click_sum:8 percent:0.0%
4010 click_sum:1 percent:100.0%
3583 click_sum:2239 percent:36.8%
4446"in_offer_id":107466987-"in_affiliate_id":4631-"result_code":1604
1649"in_offer_id":98399105-"in_affiliate_id":5988-"result_code":1607
800"in_offer_id":106901072-"in_affiliate_id":4666-"result_code":1604
594"in_offer_id":106351217-"in_affiliate_id":7373-"result_code":1604
531"in_offer_id":107466987-"in_affiliate_id":3882-"result_code":1606
393"in_offer_id":108314256-"in_affiliate_id":5411-"result_code":1601
356"in_offer_id":108230131-"in_affiliate_id":5033-"result_code":1601
291"in_offer_id":108230207-"in_affiliate_id":5033-"result_code":1604
284"in_offer_id":108923434-"in_affiliate_id":3583-"result_code":1604
210"in_offer_id":108231457-"in_affiliate_id":5033-"result_code":1800

目标数据模板

7545 click_sum:149 percent:97.32%
4773 click_sum:277 percent:86.28%
5411 click_sum:466 percent:84.55%
2902 click_sum:147 percent:80.95%
5988 click_sum:2041 percent:80.84%
5033 click_sum:2337 percent:73.47%
5580 click_sum:250 percent:55.2%
7115 click_sum:346 percent:54.34%
4666 click_sum:1526 percent:54.26%

要求说明

找到 click_sum 的值大于 100 且 percent 的值大于 30% 的数据,并且
按照 percent 的值 进行由大到小进行排序打印出来

代码

# click_num的值大于100且percent的值大于30,然后从大到到小排序
import traceback

# 读取文件内容
with open('source.txt', 'r') as f:
    # 得到源数据并且成为列表
    content_list = f.read().split('\n')

lines = []

# 循环源数据列表
for line in content_list:
    # 判断是我们要的数据
    if 'click_sum' in line:

        # 拿到我们需要比较的两个数据部分
        # click_sum:149 和 percent:97.32%
        _, click_sum, percent = line.split()

        # 分割得到具体数据
        sum = click_sum.split(':')[-1]
        per = percent.replace('%', '').split(':')[-1]
        try:
            # 类型转换
            sum = int(sum)
            per = float(per)

            # 判断 click_num的值大于100且percent的值大于30 的数据行
            if sum > 100 and per > 30:

                # 把符合条件的数据和需要比对的数据放在一个列表中添加到中列表中
                # # [[54.26, '4666 click_sum:1526 percent:54.26%']]
                lines.append([per, line])
        except Exception as e:
            # 假如有异常就打印出如下信息
            print("获取到的数据不是数字类型的,无法装换比较")
            print(traceback.format_exc())

# print(lines)

# 最终的数据
# [[54.26, '4666 click_sum:1526 percent:54.26%'], [37.57, '6212 click_sum:173 percent:37.57%'], [52.04, '6214 click_sum:294 percent:52.04%'], [40.33, '3671 click_sum:362 percent:40.33%'], [86.28, '4773 click_sum:277 percent:86.28%'], [53.87, '7373 click_sum:1214 percent:53.87%'], [51.24, '6522 click_sum:201 percent:51.24%'], [84.55, '5411 click_sum:466 percent:84.55%'], [40.74, '3882 click_sum:1318 percent:40.74%'], [80.95, '2902 click_sum:147 percent:80.95%'], [80.84, '5988 click_sum:2041 percent:80.84%'], [97.32, '7545 click_sum:149 percent:97.32%'], [51.35, '7060 click_sum:111 percent:51.35%'], [41.54, '3989 click_sum:715 percent:41.54%'], [73.47, '5033 click_sum:2337 percent:73.47%'], [34.17, '7113 click_sum:120 percent:34.17%'], [54.34, '7115 click_sum:346 percent:54.34%'], [55.2, '5580 click_sum:250 percent:55.2%'], [36.8, '3583 click_sum:2239 percent:36.8%']]

# 排序
"""
lambda item: item[0]  是一个匿名函数
利用 [54.26, '4666 click_sum:1526 percent:54.26%'] 的第一元素进行比较

# 给 sort 函数传入参数 reverse=True, 进行有大到下排序 
"""
lines.sort(key=lambda item: item[0], reverse=True)
# print(lines)
# [[97.32, '7545 click_sum:149 percent:97.32%'], [86.28, '4773 click_sum:277 percent:86.28%'], [84.55, '5411 click_sum:466 percent:84.55%'], [80.95, '2902 click_sum:147 percent:80.95%'], [80.84, '5988 click_sum:2041 percent:80.84%'], [73.47, '5033 click_sum:2337 percent:73.47%'], [55.2, '5580 click_sum:250 percent:55.2%'], [54.34, '7115 click_sum:346 percent:54.34%'], [54.26, '4666 click_sum:1526 percent:54.26%'], [53.87, '7373 click_sum:1214 percent:53.87%'], [52.04, '6214 click_sum:294 percent:52.04%'], [51.35, '7060 click_sum:111 percent:51.35%'], [51.24, '6522 click_sum:201 percent:51.24%'], [41.54, '3989 click_sum:715 percent:41.54%'], [40.74, '3882 click_sum:1318 percent:40.74%'], [40.33, '3671 click_sum:362 percent:40.33%'], [37.57, '6212 click_sum:173 percent:37.57%'], [36.8, '3583 click_sum:2239 percent:36.8%'], [34.17, '7113 click_sum:120 percent:34.17%']]

for line in lines:
    print(line[-1])

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容