高阶函数

一、名称空间和作用域

可以简单理解为存放变量名和变量值之间绑定关系的地方。

1. 名称空间

在 Python 中有各种各样的名称空间:

  • 全局名称空间:每个程序的主要部分定义了全局的变量名和变量值的对应关系,这样就叫做全局名称空间
  • 局部名称空间:在函数的运行中定义的临时的空间叫做局部名称空间,只可以被这个函数所有。函数运行结束后,这个局部的名称空间就会销毁。
  • 内置名称空间:内置名称空间中存放了python解释器为我们提供的名字:input,print,str,list,tuple...它们都是我们熟悉的,拿过来就可以用的方法。

三种名称空间之间的加载顺序

python3 test.py

# 1、python解释器先启动,因而首先加载的是:内置名称空间
# 2、执行test.py文件,然后以文件为基础,加载全局名称空间
# 3、在执行文件的过程中如果调用函数,则临时产生局部名称空间

名字的查找顺

局部使用:局部名称空间——>全局名称空间——>内置名称空间

x = 1
def f1():
    x = 10
    print(x)

f1()  # 输出 10

全局使用:全局——>内置

#需要注意的是:在全局无法查看局部的,在局部可以查看全局的,如下示例

x = 1
def f1():
    x = 10
    print(x)

print(x)  # 输出  1

2. 作用域

作用域就是变量名的生效范围
分为: 全局作用域 和 局部作用域

a. 全局作用域

  • 内置的名称空间中的名字和全局名称空间的名字属于这个全局作用域。

  • 全局作用域中的名字,在整个文件的任意位置都能被引用,全局存活,全局内都有效。

b. 局部作用域

局部名称空间的名字属于局部作用域。

  • 局部作用域中的名字只能在其本地局部生效和使用。
  • python 中局部作用域就是函数内定义或生成的名字,临时存活,随着函数调用的结束而消失。

二、 高阶函数

特点

把一个函数的函数名当做实参传给另一个函数
函数本身可以作为另外一个函数的返回值

def foo():
    return 10

def func(f):
        print(id(f), f)

# 直接打印原函数的 id
print(id(foo))

# 调用函数 并把 foo 作为实参传递进去,查看传输的函数的 id
func(foo)

三、内部函数

在一个函数内部定义的函数

def outer():
    def inner():
        x = 10

函数 inner 就是一个内部函数

四、 闭包

是另一个函数动态生成的函数,并且返回一个 包含了外部作用域而非全局作用域变量名称的 函数。这个函数可以使用外部作用域的变量。

def outer(f):
    def inner():
        print(f)
    return inner

really_inner = outer(10)

really_inner()

上面的 f 可以是任何的 python 对象,当然也可以是给函数。

def foo():
    pass

def outer(f):
    def inner():
        print(f)
    return inner

really_inner = outer(foo)

此时, really_inner 就是闭包, 其本质就是 inner 函数对象, 并且包含了 foo 这个函数对象。

五、 装饰器

原始方式实现(老的方式)

def outer(arg):
    def inner():
        print("*" * 20)
        arg()
        print("*" * 20)

    return inner

def echo():
    print('欢迎')

echo = outer(echo)   # inner

echo()

语法糖实现(目前使用此种方式)

def outer(arg):
    def inner():
        print("*" * 20)
        arg()
        print("*" * 20)

    return inner

@outer   # echo = outer(echo)   # inner
def echo():
    print('欢迎')

echo()

使用装饰器的理由

在软件开发领域有个规则:

在开发时,需要遵循 开放封闭原则,就是对扩展开放,对修改封闭。

扩展开放,就是可以对原来的函数功能进行扩展。

修改封闭,就是给原来的函数添加功能的时候,不可以直接修改原来的函数。

装饰器的作用是什么

装饰器时装饰其他对象的器具,本身可以是任意可调用对象,被装饰者也可以是任意可调用对象。

强调装饰器的原则:

1.不修改被装饰对象的源代码

2.不修改被装饰对象的调用方式
装饰器的目标:

在遵循1和2的前提下,为被装饰对象添加上新功能

补充内置函数 枚举 enumerate

li = ["hello","world", 'len', 'network']
#
# for idx, item in enumerate(li):
#     print(idx, item)


# for idx, item in enumerate(li, 1):
#     print(idx, item)

练习

源数据

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])
file = '/root/pythoncode/day05/数据筛选.txt'
file2='/root/pythoncode/day05/new数据筛选.txt'
with open(file,'r',encoding='utf-8') as f,open(file2,'w',encoding='utf-8') as f2:
  for  li in f.readlines():
    # print(li_b)
    if 'click_sum' in li:
      f2.write(li)
with open(file2,'r',encoding='utf-8') as a:
  for li in a:
    li_a=li.split(':')[1].split(' ')[0]
    # per=li.split(':')[2].strip('\n').strip('%')
    per = li.split(':')[0].split(' ')[2].split(':')[1].split('.')[0]
    # print(per)
    if float(li_a) > 100 and float(per) > 30:
      print(li)

你可能感兴趣的:(高阶函数)