吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1316|回复: 17
收起左侧

[Python 原创] 【学习笔记】关于匿名函数 λ 的几个例子

[复制链接]
whyerect 发表于 2023-3-23 18:21
本帖最后由 whyerect 于 2023-3-23 19:20 编辑

例一:把列表中的学生按年龄排序


[Python] 纯文本查看 复制代码
students = [
    {"姓名": "张三", "年龄": 18},
    {"姓名": "李四", "年龄": 7},
    {"姓名": "王五", "年龄": 99},
    {"姓名": "赵六", "年龄": 30},
    {"姓名": "田七", "年龄": 22}
]

print("排序前:", students)
students.sort(key=lambda x: x["年龄"])
print("排序后:", students)


如果不用匿名函数lambda,用普通函数怎么做?

[Python] 纯文本查看 复制代码
def sort_func(item):
    return item["年龄"]


students = [
    {"姓名": "张三", "年龄": 18},
    {"姓名": "李四", "年龄": 7},
    {"姓名": "王五", "年龄": 99},
    {"姓名": "赵六", "年龄": 30},
    {"姓名": "田七", "年龄": 22}
]

print("排序前:", students)
students.sort(key=sort_func)
print("排序后:", students)


输出结果:
排序前: [{'姓名': '张三', '年龄': 18}, {'姓名': '李四', '年龄': 7}, {'姓名': '王五', '年龄': 99}, {'姓名': '赵六', '年龄': 30}, {'姓名': '田七', '年龄': 22}]
排序后: [{'姓名': '李四', '年龄': 7}, {'姓名': '张三', '年龄': 18}, {'姓名': '田七', '年龄': 22}, {'姓名': '赵六', '年龄': 30}, {'姓名': '王五', '年龄': 99}]





例二:sorted 函数可以用 key=函数名 对排序的列表先进行函数变换再排序

[Python] 纯文本查看 复制代码
num_list = [45, -100, -57, 666, 0]

# 先对列表取绝对值再进行排序
num_list_1 = sorted(num_list, key=abs)
print(num_list_1)


输出结果:
[0, 45, -57, -100, 666]


[Python] 纯文本查看 复制代码
my_list = ["abcd", "a", "ab", "abc", "12345", "1"]
my_list_1 = sorted(my_list, key=lambda x: len(x))
print(my_list_1)



输出结果:
['a', '1', 'ab', 'abc', 'abcd', '12345']




例三:min 函数可以用 key=函数名 对求最小值的列表先进行函数变换再排序

有一个列表比如 [1, 2, 3,  ......10] 需求是用户输入一个小数,比如:3.14,要求判断输入的小数距离列表中哪个数最近,如何实现?

[Python] 纯文本查看 复制代码
my_list = list(range(1, 11))
my_num = float(input("请输入1-10之间的小数:"))
result = min(my_list, key=lambda x: abs(x-my_num))
print(result)

免费评分

参与人数 5吾爱币 +5 热心值 +4 收起 理由
liugngg + 1 我很赞同!
hodouq + 1 + 1 我很赞同!
qiaosefennu + 1 + 1 用心讨论,共获提升!
xiaosanmeng + 1 + 1 我很赞同!
laolatiao + 1 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| whyerect 发表于 2023-3-31 16:29

用多线程采集阿里招聘的数据

本帖最后由 whyerect 于 2023-4-1 21:28 编辑

获取阿里巴巴的招聘数据,需要字段,标题,更新时间,地址,通过多任务的方式获取10页数据
网址:https://talent.alibaba.com/off-campus/position-list?lang=zh
[Python] 纯文本查看 复制代码
import pymongo
from queue import Queue
import requests
from threading import Thread
import time


class Alibaba:
    def __init__(self):
        self.client = pymongo.MongoClient()
        self.collection = self.client['spider']['alibaba']
        self.url = 'https://talent.alibaba.com/position/search?_csrf=b8ec86e6-d9fc-4eb5-8870-b43f9639c5b4'
        self.data = {
            "channel": "group_official_site",
            "language": "zh",
            "batchId": "",
            "categories": "",
            "deptCodes": [],
            "key": "",
            "pageIndex": 1,
            "pageSize": 10,
            "regions": "",
            "subCategories": ""
        }
        self.headers = {
            'cookie': 'prefered-lang=zh; cna=vOuhHKfdx1QCART5EuvFqCw6; XSRF-TOKEN=b8ec86e6-d9fc-4eb5-8870-b43f9639c5b4; SESSION=QzVGRTFCMjEyRkU2OEI3MDFEODgxRERENDJGMEZFMkM=; xlly_s=1; l=fBrKCclVNEWXfjn8BO5Bhurza77T4IOfGlVzaNbMiIEGa61P1HHx8NCsVs79RdtjgTf4setr24w81dhM8b4U-x9_PwJbsiooVxJ6-bpU-L5..; tfstk=cVgRBPGAdKvlxU93uzKcL-Zg5rgdZ5_8p_wNJVc0hoLVEA7di_uiWS_kV5eaeIC..; isg=BLW1ZBPfPVEEo1nXeZpCfsU_xDFvMmlEavcOvjfbKixwDtEA_4ONFSLIWNI4dYH8',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36'
        }
        self.page_queue = Queue()
        self.json_queue = Queue()
        self.parsed_queue = Queue()

    def get_pages(self):
        for i in range(1, 11):
            self.data['pageIndex'] = i
            self.page_queue.put(self.data)

    def get_data(self):
        while True:
            data = self.page_queue.get()
            self.page_queue.task_done()
            response = requests.post(url=self.url, json=data, headers=self.headers)
            # print(response.json(), '\n' * 3)
            self.json_queue.put(response.json())

    def parse_data(self):
        while True:
            data = self.json_queue.get()
            self.json_queue.task_done()
            for i in data['content']['datas']:
                item = {
                    'name': i['name'],
                    'update_time': self.timestamp_to_date(i['modifyTime']),
                    'workLocations': '/'.join(i['workLocations'])
                }
                self.parsed_queue.put(item)

    def save_data(self):
        i = 0
        while True:
            i += 1
            item = self.parsed_queue.get()
            self.parsed_queue.task_done()
            print(i, item)
            self.collection.insert_one(item)

    @staticmethod
    def timestamp_to_date(timestamp_13):
        #  Convert a 13-digit timestamp to year, month, and day
        timestamp = timestamp_13
        date = time.localtime(timestamp / 1000.0)
        year = date.tm_year
        month = date.tm_mon
        day = date.tm_mday
        date_string = str(year) + '年' + str(month) + '月' + str(day) + '日'
        return date_string

    def main(self):
        t_list = list()
        t_get_pages = Thread(target=self.get_pages)
        t_list.append(t_get_pages)
        for i in range(6):
            t_get_data = Thread(target=self.get_data)
            t_list.append(t_get_data)
        for i in range(8):
            t_parse_data = Thread(target=self.parse_data)
            t_list.append(t_parse_data)
        t_save_data = Thread(target=self.save_data)
        t_list.append(t_save_data)
        for t in t_list:
            t.daemon = True
            t.start()
        for q in [self.page_queue, self.json_queue, self.parsed_queue]:
            q.join()
        """
        做这个作业的时候,我遇到很大一个坑就在这里,注意到t_save_data这个线程没有?队列为空的时候这个线程可能并没有执行完成,
        q.join()并不能控制t_save_data这个线程已经运行完毕,由于它又是守护线程,所以随着队列为空,q.join()阻塞放行,
        主线程结束,t_save_data执行到一半也被结束,因此只好用下面的time.sleep(5)人为添加阻塞。
        
        另外,扩展一下,即使不考虑存储数据这个最后的线程好了,我们只考虑前面步骤的线程,
        “队列q为空”和“所有线程执行完毕”之间是有时间差的,等于篮子是已经空了,任务已经被领完了,但执行任务还是需要时间的,
        这中间有时间差,哪怕是0.000000001秒,由于q.join()只根据篮子空没空判断是否阻塞,主进程一结束,守护线程结束,
        这有可能导致程序运行的偏差。
        
        最后,总结一下这个程序的思路,也是对初学者最不好理解的地方:通过篮子是否为空(队列里的任务是否被领完)来控制
        主线程的节奏,涉及q.get();q.task_done()和q.join(),然后通过主线程的结束而结束守护线程来退出死循环。
        我一开始怎么也想不通,每个方法都是while True的死循环,而且循环体中没有break,它们是怎么退出的???
        原来,就是靠设置成守护线程daemon=True来退出的。
        q.join()方法的用途就是:用于等待守护线程运行结束,避免因主线程的提前结束而导致守护线程突然终止的问题。        
        """
        time.sleep(5)


if __name__ == '__main__':
    start_time = time.time()
    alibaba = Alibaba()
    alibaba.main()
    print("__main__总共花费时间:", time.time()-start_time)
 楼主| whyerect 发表于 2023-3-30 16:45

多进程方式采集腾讯视频的电视剧介绍

[Python] 纯文本查看 复制代码
import requests
import pymongo
from multiprocessing import Process
from multiprocessing import JoinableQueue as Queue
import time


class Tengxun():
    client = pymongo.MongoClient()
    collection = client['spider']['tengxun']

    def __init__(self):
        self.headers = {
            "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
        }
        self.url = 'https://pbaccess.video.qq.com/trpc.vector_layout.page_view.PageService/getPage?video_appid=3000010'
        # 存储需要传递的json
        self.data_queue = Queue()
        # 存放获取到的响应数据
        self.json_queue = Queue()
        # 存放解析之后的数据
        self.content_queue = Queue()

    def get_post_data(self):
        for i in range(1, 11):
            data = {
                "page_context": {
                    "page_index": str(i)
                },
                "page_params": {
                    "page_id": "channel_list_second_page",
                    "page_type": "operation",
                    "channel_id": "100113",
                    "filter_params": "ifeature=-1&iarea=-1&iyear=-1&ipay=-1&sort=75",
                    "page": str(i)
                },
                "page_bypass_params": {
                    "params": {
                        "page_id": "channel_list_second_page",
                        "page_type": "operation",
                        "channel_id": "100113",
                        "filter_params": "ifeature=-1&iarea=-1&iyear=-1&ipay=-1&sort=75",
                        "page": str(i),
                        "caller_id": "3000010",
                        "platform_id": "2",
                        "data_mode": "default",
                        "user_mode": "default"
                    },
                    "scene": "operation",
                    "abtest_bypass_id": "ddf6b146f5be0ab4"
                }
            }
            self.data_queue.put(data)

    def get_data(self):
        while True:
            data = self.data_queue.get()
            self.data_queue.task_done()
            # 表单数据传递的是字典,载荷数据传递的是JSON
            response = requests.get(self.url, self.headers, json=data)
            self.json_queue.put(response.json())

    def parse_data(self):
        while True:
            data = self.json_queue.get()
            self.json_queue.task_done()
            for video in data['data']['CardList'][0]['children_list']['list']['cards']:
                item = {
                    'title': video['params']['title'],
                    'second_title': video['params']['second_title'],
                    'timelong': video['params']['timelong'] if video['params'].get('timelong') else 'NULL'
                }
                print(item)
                self.content_queue.put(item)

    def save_data(self):
        while True:
            item = self.content_queue.get()
            self.content_queue.task_done()
            self.collection.insert_one(item)

    def main(self):
        process_list = list()
        p_get_json = Process(target=self.get_post_data)
        process_list.append(p_get_json)
        p_get_data = Process(target=self.get_data)
        process_list.append(p_get_data)
        p_parse_data = Process(target=self.parse_data)
        process_list.append(p_parse_data)
        p_save_data = Process(target=self.save_data)
        process_list.append(p_save_data)
        for p in process_list:
            p.daemon = True
            p.start()
            time.sleep(2)
        for q in [self.data_queue, self.json_queue, self.content_queue]:
            q.join()


if __name__ == '__main__':
    tx = Tengxun()
    tx.main()
NINE09 发表于 2023-3-24 09:31
感谢分享!!!!

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
whyerect + 1 + 1 谢谢鼓励!

查看全部评分

xiaosanmeng 发表于 2023-3-24 09:37
感谢分享!!!!

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
whyerect + 1 + 1 谢谢鼓励!

查看全部评分

qiaosefennu 发表于 2023-3-24 10:33
支持支持一下

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
whyerect + 1 + 1 用心讨论,共获提升!谢谢鼓励!

查看全部评分

 楼主| whyerect 发表于 2023-3-24 13:03

关于”对象关联“的几个例子

本帖最后由 whyerect 于 2023-3-24 13:11 编辑

Python中一切皆对象,面向对象的三大特性:封装、继承、多态。听老师上课举了几个“多态”的例子,全部用到【对象关联】,下面是对象关联的几个例子,一个是不同的犬吠;一个是迷你操作系统安装app;一个是学生与班级;一个是迭代器。这些都是对象关联的例子。

例一:众狗汪汪汪

[Python] 纯文本查看 复制代码
class Dog(object):
    def bark(self):
        print("狗汪汪叫...")


class LangDog(Dog):
    def bark(self):
        print("狼狗震耳欲聋的叫...")


class ZangAo(Dog):
    pass


class Person(object):
    def pk_dog(self, dog_obj):
        print("人用力的向狗进行了攻击...")
        dog_obj.bark()


anna = Person()
dog1 = Dog()
dog2 = LangDog()
dog3 = ZangAo()

anna.pk_dog(dog1)
anna.pk_dog(dog2)
anna.pk_dog(dog3)



输出结果:

人用力的向狗进行了攻击...
狗汪汪叫...
人用力的向狗进行了攻击...
狼狗震耳欲聋的叫...
人用力的向狗进行了攻击...
狗汪汪叫...





例二:APP装装装


[Python] 纯文本查看 复制代码
class MiniOS(object):
    """MiniOS 操作系统类 """
    def __init__(self, name):
        self.name = name
        self.apps = []  # 安装的应用程序名称列表

    def __str__(self):
        return "%s 安装的软件列表为 %s" % (self.name, str(self.apps))

    def install_app(self, app_obj):
        # 判断是否已经安装了软件
        if app_obj.name in self.apps:
            print("已经安装了 %s,无需再次安装" % app_obj.name)
        else:
            app_obj.install()
            self.apps.append(app_obj.name)


class App(object):
    def __init__(self, name, version, desc):
        self.name = name
        self.version = version
        self.desc = desc

    def __str__(self):
        return "%s 的当前版本是 %s - %s" % (self.name, self.version, self.desc)

    def install(self):
        print("将 %s [%s] 的执行程序复制到程序目录..." % (self.name, self.version))


class PyCharm(App):
    pass


class Chrome(App):
    def install(self):
        print("正在解压缩安装程序...")
        super().install()


linux = MiniOS("Linux")
print(linux)

pycharm = PyCharm("PyCharm", "1.0", "python开发的IDE环境")
chrome = Chrome("Chrome", "2.0", "谷歌浏览器")

linux.install_app(pycharm)
linux.install_app(chrome)
linux.install_app(chrome)

print(linux)



例三:学生在班里
[Python] 纯文本查看 复制代码
class Classroom(object):
    def __init__(self, name):
        self.classroom_name = name
        self.stus = []  # 一般情况下在本类的其它方法中用到的实例属性,都要在__init__方法中定义

    def add_new_stu(self, stu_obj):
        """定义新方法用来完成关联"""
        self.stus.append(stu_obj)


class Student(object):
    def __init__(self, name):
        self.student_name = name


# 创建一个教室对象
class205 = Classroom("205班")

# 创建多个学生对象
stu01 = Student("学生1")
stu02 = Student("学生2")
stu03 = Student("学生3")

# 调用方法将学生添加到对象中
class205.add_new_stu(stu01)
class205.add_new_stu(stu02)
class205.add_new_stu(stu03)

# 调用学生的姓名
# 205教室.列表[下标].姓名
print(class205.stus[0].student_name)
print(class205.stus[1].student_name)
print(class205.stus[2].student_name)




例四:自制迭代器
[Python] 纯文本查看 复制代码
class MyList(object):
    """自定义的一个可迭代对象"""
    def __init__(self):
        self.items = []

    def add(self, val):
        self.items.append(val)

    def __iter__(self):
        myiterator = MyIterator(self)
        return myiterator


class MyIterator(object):
    """自定义的供上面可迭代对象使用的一个迭代器"""
    def __init__(self, mylist_obj):
        self.mylist = mylist_obj
        # current用来记录当前访问到的位置
        self.current = 0

    def __next__(self):
        if self.current < len(self.mylist.items):
            item = self.mylist.items[self.current]
            self.current += 1
            return item
        else:
            raise StopIteration

    def __iter__(self):
        return self


if __name__ == '__main__':
    mylist = MyList()
    mylist.add(1)
    mylist.add(2)
    mylist.add(3)
    mylist.add(4)
    mylist.add(5)

    nums = list(mylist)
    print(nums)
 楼主| whyerect 发表于 2023-3-24 17:19
我发现我现在 BeautifulSoup 学得入门了

[Python] 纯文本查看 复制代码
import requests
import os
from bs4 import BeautifulSoup


path = "/铃声"

if not os.path.exists(path):
    os.mkdir(path)


url = "https://sc.chinaz.com/yinxiao/index.html"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}

response = requests.get(url, headers=headers).content.decode("utf-8")

soup = BeautifulSoup(response, "lxml")
div_list = soup.select("#AudioList .container .audio-item")
# print(div_list)
for div in div_list:
    name = div.select(".name")[0].get_text()
    print(name.strip())
XS20220313 发表于 2023-3-25 09:56
感谢分享!!!!

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
whyerect + 1 + 1 谢谢鼓励!用心讨论,共获提升!

查看全部评分

 楼主| whyerect 发表于 2023-3-25 14:06

用lxml解析数据,然后,保存为JSON格式的文件

本帖最后由 whyerect 于 2023-3-25 14:50 编辑

[Python] 纯文本查看 复制代码
import json
import requests
from lxml import etree

url = "https://www.4399.com/flash/"

headers = {

    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}

response = requests.get(url=url, headers=headers)
response.encoding = "gb2312"
html = etree.HTML(response.text)
li_list = html.xpath('//ul[@class="n-game cf"]/li')

data_list = list()

for li in li_list:
    name = li.xpath("./a/b/text()")[0]
    href = li.xpath("./a/@href")[0]
    item = {"title": name, "href": href}
    data_list.append(item)
    
with open("games.json", "w", encoding="utf-8") as f:
    f.write(json.dumps(data_list, ensure_ascii=False, indent=2))


    




 楼主| whyerect 发表于 2023-3-25 15:02

CSV模块的使用

本帖最后由 whyerect 于 2023-3-25 15:49 编辑

[Python] 纯文本查看 复制代码
import csv

with open("data.csv", "w", encoding="gbk", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["姓名", "年龄", "性别"])
    writer.writerow(["张三", "16", "男"])
    writer.writerow(["李四", "39", "女"])
    writer.writerow(["王五", "58", "女"])
    writer.writerow(["赵六", "89", "LGBT"])



当然不导入csv模块也是可以的,可以直接写:
[Python] 纯文本查看 复制代码
with open("data1.csv", "w", encoding="gbk") as f:

    f.write("姓名, 年龄, 性别\n")
    f.write("张三, 16, 男\n")
    f.write("李四, 39, 女\n")
    f.write("王五, 58, 女\n")
    f.write("赵六, 89, LGBT\n")
 楼主| whyerect 发表于 2023-3-25 16:10

关于匿名函数 lambda 的几个例子

例一:sorted 函数可以用 key=函数名 对排序的列表先进行函数变换再排序
num_list = [45, -100, -57, 666, 0]

# 先对列表取绝对值再进行排序
num_list_1 = sorted(num_list, key=abs)
print(num_list_1)

输出结果:
[0, 45, -57, -100, 666]

my_list = ["abcd", "a", "ab", "abc", "12345", "1"]
my_list_1 = sorted(my_list, key=lambda x: len(x))
print(my_list_1)

输出结果:
['a', '1', 'ab', 'abc', 'abcd', '12345']

例二:min 函数可以用 key=函数名 对求最小值的列表先进行函数变换再排序

有一个列表比如 [1, 2, 3,  ......10] ,现在的需求是:用户输入一个小数,比如:3.14,要求判断输入的小数距离列表中哪个数最近,如何实现?

my_list = list(range(1, 11))
my_num = float(input("请输入1-10之间的小数:"))
result = min(my_list, key=lambda x: abs(x-my_num))
print(result)
例三:顾安老师上课讲的例子:把列表中的学生按年龄排序
students = [
    {"姓名": "张三", "年龄": 18},
    {"姓名": "李四", "年龄": 7},
    {"姓名": "王五", "年龄": 99},
    {"姓名": "赵六", "年龄": 30},
    {"姓名": "田七", "年龄": 22}
]

print("排序前:", students)
students.sort(key=lambda x: x["年龄"])
print("排序后:", students)

如果不用匿名函数lambda,用普通函数怎么做?

def sort_func(item):
    return item["年龄"]

students = [
    {"姓名": "张三", "年龄": 18},
    {"姓名": "李四", "年龄": 7},
    {"姓名": "王五", "年龄": 99},
    {"姓名": "赵六", "年龄": 30},
    {"姓名": "田七", "年龄": 22}
]

print("排序前:", students)
students.sort(key=sort_func)
print("排序后:", students)

输出结果:
排序前: [{'姓名': '张三', '年龄': 18}, {'姓名': '李四', '年龄': 7}, {'姓名': '王五', '年龄': 99}, {'姓名': '赵六', '年龄': 30}, {'姓名': '田七', '年龄': 22}]
排序后: [{'姓名': '李四', '年龄': 7}, {'姓名': '张三', '年龄': 18}, {'姓名': '田七', '年龄': 22}, {'姓名': '赵六', '年龄': 30}, {'姓名': '王五', '年龄': 99}]

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 23:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表