学习日志15 python

filter() 函数

filter(function, iterable)

filter函数是python中的高阶函数, 第一个参数是一个筛选函数, 第二个参数是一个可迭代对象, 返回的是一个生成器类型, 可以通过next获取值。

filter() 函数是 Python 内置的高阶函数,其主要功能是对可迭代对象中的每个元素运用筛选函数进行判断,然后把符合条件的元素以生成器的形式返回。下面为你详细介绍它的用法和特性:

基础语法

python

运行

filter(function, iterable)

这里的参数 function 是一个用于筛选元素的函数,它会返回布尔值;iterable 则是一个可迭代对象,像列表、元组、集合等都属于此类。

核心特性

  1. 返回生成器filter() 返回的是一个生成器对象,这意味着它是惰性求值的,只有在需要的时候才会生成值,这样能有效节省内存。
  2. 筛选逻辑:当 function 返回 True 时,对应的元素会被保留;若返回 False,则该元素会被过滤掉。要是 function 为 Nonefilter() 会保留 iterable 中所有布尔值为 True 的元素。

示例

示例 1:过滤偶数

python

运行

numbers = [1, 2, 3, 4, 5, 6]
evens = filter(lambda x: x % 2 == 0, numbers)print(list(evens))  # 输出: [2, 4, 6]
示例 2:过滤空字符串

python

运行

words = ["hello", "", "world", "  ", None, "python"]
valid_words = filter(None, words)  # 不传筛选函数时,会过滤掉布尔值为 False 的元素print(list(valid_words))  # 输出: ['hello', 'world', 'python']
示例 3:使用生成器特性

python

运行

numbers = [1, 2, 3, 4, 5]
filtered = filter(lambda x: x > 3, numbers)print(next(filtered))  # 输出: 4
print(next(filtered))  # 输出: 5

替代实现

你也可以通过列表推导式或者生成器表达式来实现相同的筛选功能:

python

运行

# 列表推导式
evens = [x for x in numbers if x % 2 == 0]# 生成器表达式(更节省内存)
evens_gen = (x for x in numbers if x % 2 == 0)

总结

filter() 函数特别适合用于数据筛选场景,它返回的生成器能高效处理大规模数据。不过在 Python 3 中,需要注意 filter() 返回的不再是列表,而是生成器,这一点和 Python 2 有所不同。

filter返回符合后面表达式为真的部分

filter() 函数会保留 function 返回值为 True 的元素,过滤掉返回 False 的元素。具体规则如下:

  1. 当 function 是自定义函数或 lambda 时
    只有当函数对元素的计算结果为 True 时,该元素才会被保留。

    python

    运行

    numbers = [1, 2, 3, 4]
    result = filter(lambda x: x > 2, numbers)  # 保留大于 2 的数
    print(list(result))  # 输出: [3, 4]
    
  2. 当 function 为 None 时
    会自动过滤掉任何布尔值为 False 的元素(如 None0、空字符串 ""、空列表 [] 等)。

    python

    运行

    values = [0, "", None, "hello", 5]
    result = filter(None, values)  # 保留布尔值为 True 的元素
    print(list(result))  # 输出: ['hello', 5]
    

底层逻辑

可以将 filter() 函数等价理解为一个生成器表达式:

python

运行

# 以下两种写法等价
filter(function, iterable)
(x for x in iterable if function(x))  # 当 function 不为 None 时
(x for x in iterable if x)            # 当 function 为 None 时

注意事项

返回值是生成器:需要用 list() 转换为列表(或用 next() 逐个获取值)。

函数参数的顺序function 在前,iterable 在后,不要混淆。

以下代码运行结果为:func = lambda x:x%2
result = filter(func, [1, 2, 3, 4, 5])
print(list(result))正确答案:[1,3,5]

2 在 Python 中,没有单独的 char(字符)类型

Python的主要内置数据类型包括:

 - 数值类型:int(整数)、float(浮点数)、complex(复数)

- 序列类型:list(列表)、tuple(元组)、range(范围)

- 字符串类型:str - 映射类型:dict(字典)

- 集合类型:set(集合)、frozenset(不可变集合)

- 布尔类型:bool

- 空值类型:None

所以char并不在Python的数据类型体系中。

而是用长度为 1 的字符串 str 来表示单个字符。例如:

python

运行

char = 'A'  # 这是一个长度为 1 的字符串,而非 char 类型
print(type(char))  # 输出: <class 'str'>

为什么 Python 没有 char 类型?

  1. 字符串不可变:Python 的字符串是不可变序列,单个字符本质上就是长度为 1 的字符串,无需额外类型。
  2. Unicode 支持:Python 3 的 str 类型默认支持 Unicode,直接用 str 表示字符更符合国际化需求。
  3. 简化设计:避免引入多余类型,保持语言简洁性(如 Java 中 char 是基本类型,而 Python 一切皆对象)。

字符操作示例

虽然没有 char 类型,但可以通过索引访问字符串中的字符:

python

运行

s = "hello"
first_char = s[0]  # 'h'
print(type(first_char))  # <class 'str'>

与其他语言的对比

语言字符类型字符串类型
Pythonstr (长度 = 1)str
JavacharString
C/C++charchar[] 或 std::string

如果你需要处理字符编码(如 ASCII/Unicode 值),可以使用 ord() 和 chr() 函数:

python

运行

char = 'A'
code = ord(char)  # 65 (Unicode 码点)
back_to_char = chr(code)  # 'A'

这种设计让 Python 在处理文本时更加统一和灵活,无需担心字符与字符串的类型转换问题。 😊

3 生成一个PyCodeObject对象是什么意思?

在 Python 中,生成一个 PyCodeObject 对象 意味着将源代码编译为 Python 虚拟机(VM)可以执行的中间表示形式,也称为 字节码(bytecode)。这个过程是 Python 执行代码的关键步骤,理解它有助于掌握 Python 的运行机制。

1. 什么是 PyCodeObject

PyCodeObject 是 CPython 解释器(用 C 语言实现的 Python 官方解释器)中的一个核心数据结构,它存储了编译后的代码信息,包括:

  • 字节码指令:如 LOAD_CONSTCALL_FUNCTION 等,类似于汇编语言。
  • 常量池:存储数字、字符串等常量。
  • 局部变量信息:变量名、位置等。
  • 源代码位置:用于调试(如错误堆栈跟踪)。

可以将 PyCodeObject 看作是源代码的 编译产物,类似于 Java 的 .class 文件或 C 的目标文件(.o)。

2. 为什么需要 PyCodeObject

Python 是 解释型语言,但执行前需要先将源代码编译为字节码,原因如下:

  • 跨平台性:字节码可以在任何 Python 解释器上运行,无需重新编译。
  • 性能优化:编译一次,多次执行(字节码可以缓存,如 .pyc 文件)。
  • 简化解释器逻辑:解释器只需执行字节码,无需处理源代码的语法解析。

3. 生成 PyCodeObject 的过程

当你运行 Python 代码时:

  1. 词法分析:将源代码转换为 token(如 defclass、变量名)。
  2. 语法分析:构建抽象语法树(AST)。
  3. 代码生成:将 AST 转换为 PyCodeObject(包含字节码)。

这个过程由 Python 解释器自动完成,例如:

python

运行

def add(a, b):return a + b# 编译后,add 函数对应一个 PyCodeObject,包含以下字节码:
#   2           0 LOAD_FAST                0 (a)
#               2 LOAD_FAST                1 (b)
#               4 BINARY_ADD
#               6 RETURN_VALUE

4. 哪些代码会生成 PyCodeObject

以下情况会生成独立的 PyCodeObject

  • 模块(.py 文件):每个文件有一个全局的 PyCodeObject
  • 函数定义:每个 def 语句生成一个(包括 lambda 函数)。
  • 类定义:每个 class 语句生成一个(类体中的代码会被编译)。
  • 生成器表达式:如 (x for x in range(10))
  • 嵌套的代码块:如方法、嵌套函数等。

5. 如何查看字节码?

可以使用 dis 模块反汇编 PyCodeObject

python

运行

import disdef add(a, b):return a + bdis.dis(add)  # 打印字节码指令

输出:

plaintext

  2           0 LOAD_FAST                0 (a)2 LOAD_FAST                1 (b)4 BINARY_ADD6 RETURN_VALUE

总结

生成 PyCodeObject 是 Python 执行代码的必经之路,它将源代码转换为可执行的字节码,让 Python 兼具解释型语言的灵活性和编译型语言的部分性能优势。理解这一点有助于解释一些 Python 特性,如:

  • 为什么函数定义是运行时执行的(因为需要生成 PyCodeObject)。
  • 为什么修改源代码后需要重新运行(除非使用 .pyc 缓存)。
  • 为什么嵌套函数可以捕获外部变量(PyCodeObject 保存了闭包信息)。

Python 作用域与 PyCodeObject

题目
Python 代码经过编译后,一共生成多少个 PyCodeObject 对象?

python

运行

class A:pass
def Fun():pass
a = A()
Fun()

选项
A. 1
B. 2
C. 3
D. 4

你的答案
B. 2

正确答案
C. 3

🔍 错误原因分析

  1. 混淆作用域的定义

    • 误将类实例化(a = A())和函数调用(Fun())视为独立作用域。
    • 实际上,只有模块、类定义、函数定义会创建新的作用域
  2. 对 PyCodeObject 的生成规则理解不深

    • 每个独立作用域(名字空间)对应一个 PyCodeObject。
    • 题目中存在 3 个作用域

      python

      运行

      # 作用域1:模块级别(全局命名空间)
      class A:        # 作用域2:类 A 的命名空间passdef Fun():      # 作用域3:函数 Fun 的命名空间passa = A()         # 全局命名空间中的语句
      Fun()           # 全局命名空间中的语句
      

📚 关键知识点

  1. PyCodeObject 生成规则

    结构是否生成 PyCodeObject示例
    模块(.py 文件)整个代码文件
    类定义(classclass A: pass
    函数定义(defdef Fun(): pass
    实例化对象a = A()
    函数调用Fun()
    普通语句赋值、条件判断、循环等
  2. 验证方法
    通过 __code__ 属性查看对象对应的 PyCodeObject(实际是 code 对象):

    python

    运行

    print(A.__code__)       # 类体对应的 code 对象
    print(Fun.__code__)     # 函数体对应的 code 对象
    print(__code__)         # 当前模块对应的 code 对象
    

💡 记忆技巧

  1. 作用域划分口诀

    模块类函数,作用域三分;实例与调用,作用域不分

  2. 嵌套作用域示例

    python

    运行

    def outer():            # 作用域1x = 10class Inner:        # 作用域2passdef inner():        # 作用域3y = 20return inner
    

    上述代码包含 3 个 PyCodeObjectouterInnerinner 各一个)。

📝 总结

  1. 明确作用域边界:类、函数、模块是作用域的核心划分单位。
  2. 区分编译时与运行时
    • 编译时生成 PyCodeObject(如类 / 函数定义)。
    • 运行时执行代码(如实例化 / 函数调用)不生成新的 PyCodeObject。

下次遇到同类题目的思考步骤

  1. 找出代码中的模块、类、函数定义。
  2. 统计独立作用域的数量。
  3. 忽略实例化、函数调用等运行时操作。

5 Python中浅拷贝和深拷贝的区别,以及列表复制时的引用特性

执行以下程序,输出结果为()
a = [['1','2'] for i in range(2)]b = [['1','2']]*2a[0][1] = '3'b[0][0] = '4'print(a,b) A [['1', '3'], ['1', '3']] [['4', '2'], ['4', '2']]B [['1', '3'], ['1', '2']] [['4', '2'], ['4', '2']]C [['1', '3'], ['1', '2']] [['4', '2'], ['1', '2']]D [['1', '3'], ['1', '3']] [['4', '2'], ['1', '2']]答案:B

1. 列表初始化方式对比

方式语法示例对象关系内存特性
列表推导式a = [['1','2'] for _ in range(2)]创建多个独立对象子列表内存地址不同
乘法操作b = [['1','2']] * 2复制同一对象的引用子列表内存地址相同

2. 浅拷贝与深拷贝的区别

  • 浅拷贝
    仅复制容器(如列表)本身,内部元素仍为原对象的引用。
    示例b = [['1','2']] * 2 中,子列表 ['1','2'] 被重复引用。

  • 深拷贝
    递归复制容器及其所有嵌套对象,生成完全独立的新对象。
    实现方式:使用 copy.deepcopy() 函数。

3. 引用特性导致的修改行为差异

  • 独立对象(列表推导式)
    修改任一子列表仅影响当前对象。
    示例a[0][1] = '3' 仅修改 a[0]

  • 共享引用(乘法操作)
    修改任一子列表会影响所有引用同一对象的元素。
    示例b[0][0] = '4' 同时修改 b[0] 和 b[1]

4. 验证对象身份的方法

使用 id() 函数检查内存地址:

python

运行

a = [['1','2'] for _ in range(2)]
b = [['1','2']] * 2
print(id(a[0]) == id(a[1]))  # False(独立对象)
print(id(b[0]) == id(b[1]))  # True(共享引用)

5. 实际应用中的注意事项

  • 多维数组初始化
    初始化多维列表时,避免使用 [[val]*n]*m(如 [[0]*3]*3),应使用列表推导式 [[val for _ in range(n)] for _ in range(m)]

  • 数据处理场景
    在需要独立操作子元素的场景(如矩阵运算、数据分组)中,确保使用独立对象初始化。

6. 总结

  • 列表推导式适合创建独立的嵌套结构。
  • 乘法操作仅复制引用,适用于不可变元素(如整数、字符串),但不适合嵌套可变对象(如列表)。
  • 使用 id() 或 is 操作符验证对象身份,避免因引用共享导致的意外修改。

为了更直观地验证这一行为,我们可以通过以下代码检查对象的内存地址

python

运行

a = [['1','2'] for i in range(2)]
b = [['1','2']]*2print(f"a[0] 地址: {id(a[0])}")  # 不同地址
print(f"a[1] 地址: {id(a[1])}")print(f"b[0] 地址: {id(b[0])}")  # 相同地址
print(f"b[1] 地址: {id(b[1])}")a[0][1] = '3'
b[0][0] = '4'print("修改后 a:", a)
print("修改后 b:", b)

输出结果:

plaintext

a[0] 地址: 140281423443648
a[1] 地址: 140281423443904
b[0] 地址: 140281423443776
b[1] 地址: 140281423443776
修改后 a: [['1', '3'], ['1', '2']]
修改后 b: [['4', '2'], ['4', '2']]

关键点:

  1. 列表推导式创建独立对象a 的子列表内存地址不同,说明它们是独立的对象。
  2. 乘法操作复制引用b 的子列表内存地址相同,说明它们指向同一个对象。
  3. 修改行为验证:对 b 的任一子列表的修改会反映到所有引用中,而 a 的子列表相互独立。

这一特性在处理嵌套数据结构时尤为重要,例如矩阵操作或多维数组的初始化。理解引用机制可以避免潜在的逻辑错误。

理解这些特性可以有效避免 Python 中常见的引用陷阱,提升代码的健壮性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/90277.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/90277.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 环境下安装 MySQL 8.0.34 二进制 详细教程 附docker+k8s启动

文章目录Linux 环境下安装 MySQL 8.0&#xff08;二进制&#xff09;详细教程准备工作安装依赖包下载并解压 MySQL下载 MySQL 二进制包解压 MySQL移动目录并创建 MySQL 用户配置 MySQL配置数据目录与日志目录编辑配置文件 /etc/my.cnf初始化 MySQL 数据库配置启动脚本与环境变量…

HTML ISO-8859-1: 完全解析

HTML ISO-8859-1: 完全解析 引言 ISO-8859-1,又称为 Latin-1,是一种广泛使用的字符编码标准,特别是在HTML文档中。本文将详细介绍ISO-8859-1编码的特点、应用场景以及如何在使用HTML时正确地使用ISO-8859-1编码。 ISO-8859-1编码概述 定义 ISO-8859-1编码是一种单字节编…

c++学习第3篇编辑器——centos7.9.2009系统离线安装clion软件并成功调试c++程序

远程linux服务器安装clion0 前提2个&#xff1a;1 下载CLion-2021.1.1.tar.gz安装包2 上传到linux系统并解压3 修改linux系统里的/etc/ssh/sshd_config文件中的X11UseLocalhost 注释去掉并设为no4 安装xauth5 安装MobaXterm软件并使用ssh组件打开clion5.1 如果打不开clion,报错…

20250722解决在Ubuntu 24.04.2下编译RD-RK3588开发板的Android13出现找不到lz4的问题

20250722解决在Ubuntu 24.04.2下编译RD-RK3588开发板的Android13出现找不到lz4的问题 2025/7/22 15:21缘起&#xff1a;在Ubuntu 24.04.2下编译RD-RK3588开发板的Android13。 报错&#xff1a;/bin/sh: 1: lz4: not found为了简单起见&#xff0c;直接在 荣品的技术支持QQ群的 …

加载用户设置时遇到错误找到一个带有无效“icon“的配置文件。将该配置文件默认为无图标。确保设置“icon“时,该值是图像的有效文件路径“

"C:\Users\Yourname\AppData\Local\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json 修改所有icon字段位none 如&#xff1a;{"guid": "{bf61c995-08cc-4a56-b781-5dba411ef19c}","hidden": false,"icon&…

如何提升连带消费?从新零售“人-货-场”模型拆解

目录 一、分析背景 二、新零售分析思路和分析方法 1.具体分析思路 2.分析方法 三、新零售“人-货-场”分析的实操步骤 1.数据收集 2.数据处理 3.图表制作 四、总结 想让线上引来的顾客&#xff0c;在店里多买几件&#xff1f; 连带消费可是实体店赚钱的“秘密武器”&a…

Java异常处理核心原理与最佳实践

Java异常处理核心原理与最佳实践 场景&#xff1a; 你开发的文件处理工具在读取用户上传的文件时突然崩溃&#xff0c;控制台抛出FileNotFoundException。用户的操作被中断&#xff0c;数据丢失。这种糟糕的体验正是异常处理机制要解决的核心问题——如何在程序出错时优雅地恢复…

Ubuntu 安装 Odoo 17 详细教程

Ubuntu 安装 Odoo 17 详细教程 本教程将指导您在 Ubuntu 系统上从源代码安装 Odoo 17。Odoo 是一款功能强大的开源 ERP 和 CRM 软件套件。本教程适用于希望自行配置和管理 Odoo 环境的用户&#xff0c;尤其适合开发者和系统管理员。 教程概述 本教程将涵盖以下步骤&#xff…

鲲鹏·卓识系列2.45G传感器型有源标签:以国产化技术重塑安全监测与人员管理新标准

标题&#xff1a;鲲鹏卓识系列2.45G传感器型有源标签&#xff1a;以国产化技术重塑安全监测与人员管理新标准 随着工业4.0和智慧城市建设的加速推进&#xff0c;安全生产、环境监测和人员管理成为各行业的核心需求。在军事、工业、仓储、能源等领域&#xff0c;温湿度、烟雾、油…

腾讯云推出CodeBuddy:革新AI全栈开发体验

文章目录一、前言二、安装流程三、CodeBuddy 核心功能3.1 AI辅助开发3.2 Coding Design Chat 三大模式3.3 Boost Prompt3.4 Figma 集成3.5 Componen 控件库3.6 Config MCP3.7 Upload Images 图片上传和管理3.8 Preview功能3.9 Deploy 一键部署3.10 项目展示 | MCP生成小红书卡片…

龙虎榜——20250723

上证指数放量收上影线&#xff0c;未站上3600点&#xff0c;个股下跌明显多于上涨&#xff0c;指数有调整需求&#xff0c;注意短线风险。深证指数较昨日缩量收阴线&#xff0c;依然在5日均线上方运行&#xff0c;打到前期平台高点有震荡调整需求&#xff0c;注意风险。2025年7…

SpringBoot06-@ConfigurationProperties注解

ConfigurationProperties注解用于将配置文件&#xff08;application.properties 或 application.yml&#xff09;中的配置值&#xff0c;自动绑定到 Java Bean 对象上。1-1、基本用途比如我们在 application.yml 中有这样一段配置&#xff1a;app:name: myAppversion: 1.0.0au…

oracle里面concat函数用法,oracle wm_concat函数用法-

wmsys.wm_concat函数&#xff0c;它的作用是以’,’链接字符 例子如下&#xff1a; SQL> create table idtable (id number,name varchar2(30)); Table created SQL> insert into idtable values(10,’ab’); 1 row inserted SQL> insert into idtable values(10,’bc…

C++中的list(2)简单复现list中的关键逻辑

C中的list&#xff08;2&#xff09;//简单复现list中的关键逻辑 前言 这一节的主要内容就是&#xff1a;简单复现list中的关键逻辑。同样的&#xff0c;我们这一节也是先粗略的看一眼源码&#xff0c;结合源码&#xff0c;边理解边复现。源码我已经上传到gitee&#xff0c;网…

Linux——System V 共享内存 IPC

文章目录一、共享内存的原理二、信道的建立1.创建共享内存1.key的作用2.key的选取3.shmid的作用4.key和shmid的区别5.内存设定的特性6.shmflg的设定2.绑定共享内存3.代码示例三、利用共享内存通信1.通信2.解除绑定3.销毁共享内存1.命令行销毁2.程序中销毁四、共享内存的生命周期…

Python 程序设计讲义(9):Python 的基本数据类型——复数

Python 程序设计讲义&#xff08;9&#xff09;&#xff1a;Python 的基本数据类型——复数 复数与数学中的复数概念类似。在 Python 中&#xff0c;复数表示为 abj&#xff0c;其中&#xff1a;a为实数部分&#xff0c;b为虚数部分&#xff0c;j称为虚数单位。复数必须包含虚数…

leetcode_121 买卖股票的最佳时期

1. 题意 有一个股价变化图&#xff0c;你可以在一天买入&#xff0c;在未来一天卖出。 求通过这样一次操作的最大获利。 2. 题解 2.1 枚举 直接枚举&#xff0c;买入卖出的时间&#xff0c;肯定会超时啦~ 时间复杂度为O(n2)O(n^2)O(n2) 空间复杂度为O(1)O(1)O(1) class …

ToBToC的定义与区别

B 端和 C 端主要是从产品所面向的用户群体角度来区分的&#xff0c;B 端指的是企业用户&#xff08;Business&#xff09;&#xff0c;C 端指的是个人消费者&#xff08;Consumer&#xff09;&#xff0c;它们在多个方面存在明显区别&#xff0c;具体如下&#xff1a;用户特征B…

Python 程序设计讲义(8):Python 的基本数据类型——浮点数

Python 程序设计讲义&#xff08;8&#xff09;&#xff1a;Python 的基本数据类型——浮点数 目录Python 程序设计讲义&#xff08;8&#xff09;&#xff1a;Python 的基本数据类型——浮点数一、浮点数的表示形式1、小数形式2、指数形式二、浮点数的精确度浮点数也称小数&am…

MCP客户端架构与实施

前言:从模型到生产力 — MCP的战略价值 在过去的一年里,我们团队见证了大型语言模型(LLM)从技术奇迹向企业核心生产力工具的演变。然而,一个孤立的LLM无法解决实际的业务问题。真正的价值释放,源于将模型的认知能力与企业现有的数据、API及工作流进行无缝、安全、可扩展…