学习日志28 python
1 Python3 列表操作与拼接
(2023_小红书)
在python3中,对于列表T=['a', 'b', 'c', 'd']下列选项中表达式结果相同的是()A ''.join(T)
B ''.join(T[::2] + T[1::2])
C ''.join(T[::-1])
D ''.join(T[2:][::-1]+T[:2][::-1])正确答案:CD
要解决这个问题,我们需要分析每个选项对列表 T=['a', 'b', 'c', 'd']
进行的操作及其结果。
首先,我们来理解列表切片的基本规则:
T[start:end:step]
表示从索引start
开始,到end
之前结束,步长为step
- 当
step
为正数时,正向切片;为负数时,反向切片 - 省略
start
表示从开头(正向)或结尾(反向)开始 - 省略
end
表示到结尾(正向)或开头(反向)结束
各选项分析:
选项 A:
''.join(T)
- 直接将列表所有元素拼接
- 结果:
'abcd'
选项 B:
''.join(T[::2] + T[1::2])
T[::2]
:从开始,步长为 2,取元素['a', 'c']
T[1::2]
:从索引 1 开始,步长为 2,取元素['b', 'd']
- 拼接两个子列表得到
['a', 'c', 'b', 'd']
- 结果:
'acbd'
选项 C:
''.join(T[::-1])
T[::-1]
:步长为 - 1,反向取所有元素,得到['d', 'c', 'b', 'a']
- 结果:
'dcba'
选项 D:
''.join(T[2:][::-1] + T[:2][::-1])
T[2:]
:从索引 2 开始取到结尾,得到['c', 'd']
T[2:][::-1]
:将上述子列表反向,得到['d', 'c']
T[:2]
:从开头取到索引 2 之前,得到['a', 'b']
T[:2][::-1]
:将上述子列表反向,得到['b', 'a']
- 拼接两个反向子列表得到
['d', 'c', 'b', 'a']
- 结果:
'dcba'
结论:
选项 C 和选项 D 的结果相同,都是 'dcba'
。
切片操作中,遵循的是左闭右开规则
具体来说,对于切片 T[start:end]
:
- 包含索引为
start
的元素(左闭) - 不包含索引为
end
的元素(右开)
例如,对于列表 T = ['a', 'b', 'c', 'd']
:
T[1:3]
会选取索引1
和2
的元素,结果为['b', 'c']
(包含索引 1,不包含索引 3)T[:2]
会选取从开头到索引 2 之前的元素,结果为['a', 'b']
T[2:]
会选取从索引 2 到结尾的元素,结果为['c', 'd']
这种左闭右开的设计使得:
- 切片的长度可以通过
end - start
直接计算(如T[1:3]
的长度是3-1=2
) - 相邻切片不会重叠且能完整覆盖原列表(如
T[:2] + T[2:]
等于原列表)
2 ,str.join(iterable)
在 Python 中,str.join(iterable)
是字符串的一个方法,用于将可迭代对象(如列表、元组、字符串等)中的元素通过指定的字符串连接起来,最终返回一个新的字符串。
- 其中,
.
前面的字符串是「连接符」 - 括号里的参数是要被连接的「可迭代对象」
举个例子:
python
运行
T = ['a', 'b', 'c', 'd']# 用空字符串连接列表元素
result = ''.join(T)
print(result) # 输出:abcd# 用逗号连接列表元素
result = ','.join(T)
print(result) # 输出:a,b,c,d# 用换行符连接
result = '\n'.join(T)
print(result)
# 输出:
# a
# b
# c
# d
需要注意:
- 被连接的可迭代对象中的元素必须都是字符串类型,否则会报错
- 连接符可以是空字符串(如
''.join(...)
),此时直接拼接所有元素 - 原列表不会被修改,
join()
只会返回一个新的字符串
3 如何判断一个类表现得像一个序列?
在 Python 中,判断一个类是否 “表现得像一个序列”(即符合序列的行为特征),主要看它是否实现了序列类型的核心方法,以支持序列的典型操作。以下是判断标准和关键特征:
1. 核心方法:__getitem__
这是最基础的要求。实现 __getitem__(self, key)
方法后,对象可以通过索引(如 obj[0]
)或切片(如 obj[1:3]
)访问元素,这是序列最基本的行为。
例如,上题中的 Foo
类实现了 __getitem__
,因此可以通过 foo[0]
访问元素,也能被迭代(见下文)。
2. 支持迭代
序列可以被 for
循环遍历。只要实现了 __getitem__
方法,Python 会默认通过索引从 0
开始尝试访问元素,直到抛出 IndexError
,从而支持迭代。
例如:
python
运行
for item in foo: # 可行,因为 Foo 实现了 __getitem__print(item)
3. 可选但重要的方法:__len__
标准序列(如列表、元组)都实现了 __len__(self)
方法,用于返回序列长度(支持 len(obj)
操作)。如果一个类没有实现 __len__
,虽然仍可通过 __getitem__
表现出部分序列特征,但不完整。
例如,列表 [1,2,3]
可以用 len()
获取长度,但上题中的 Foo
类不能(会报错)。
4. 其他序列特征
完整的序列通常还支持:
- 成员判断(
in
运算符):本质是通过迭代实现,只要可迭代即可支持。 - 切片操作:
__getitem__
方法如果正确处理切片参数(如key
是slice
对象),就支持切片。
总结
一个类 “表现得像序列” 的最低标准是:
- 实现
__getitem__
方法,支持索引和切片访问。 - 支持迭代(由
__getitem__
间接实现)。
如果再实现 __len__
方法,就更接近列表、元组等标准序列的行为。
例如,Python 中的 range
对象就是典型的 “类序列” 对象,它实现了 __getitem__
和 __len__
,支持索引、切片、迭代和 len()
操作,但不是列表那样的 “容器型” 序列。
4 解释型语言和编译型语言的核心区别
题友说......:
“解释型语言目前我就接触过Python和JavaScript,效率低自不必说,JavaScript就依赖环境,node,浏览器,编译前不执行,编译时才执行,明显效率低
”“ 非独立:JavaScript语言依赖执行环境,对于客户端来说是浏览器,对于服务端来说是node。
效率低:执行前不需要编译,执行时才编译,因此效率低。 ”
=========================================
解释型语言和编译型语言的核心区别在于代码执行的方式,具体可以从以下几个方面理解:
1. 核心区别:代码如何转化为机器可执行指令
编译型语言(如 C、C++、Go):
- 有一个专门的 “编译过程”:在代码运行前,通过编译器将整个源代码一次性翻译成机器能直接理解的二进制指令(可执行文件)。
- 之后运行时,直接执行这个二进制文件,不再需要源代码或编译器参与。
- 优点:编译一次后可多次运行,执行效率高(因为已经是机器码)。
- 缺点:跨平台性差(不同操作系统的机器码不兼容),修改代码后需重新编译。
解释型语言(如 Python、JavaScript、PHP):
- 没有 “预编译” 成可执行文件的过程,而是通过解释器逐行(或逐段)读取源代码,边解释(翻译)边执行。
- 每次运行代码时都需要解释器参与,源代码本身不直接转化为机器码。
- 优点:跨平台性好(只要安装对应解释器即可运行),开发迭代快(修改后直接运行,无需编译)。
- 缺点:执行效率通常低于编译型语言(因为每次运行都要重复解释过程)。
2. 关于 JavaScript 的 “编译” 误解
你提到 “JavaScript 执行时才编译”,这个说法需要修正:
JavaScript 是解释型语言,但现代 JavaScript 引擎(如 V8,用于 Chrome 和 Node.js)会采用 “即时编译(JIT)” 优化:
- 执行时,解释器先逐行解释代码;
- 对于反复执行的热点代码,引擎会动态将其编译为机器码缓存起来,后续直接执行机器码,提升效率。
这里的 “编译” 是引擎内部的动态优化,和编译型语言的 “预编译” 完全不同:
- 编译型语言的编译是 “一次性、运行前” 的过程;
- JavaScript 的 JIT 编译是 “动态、运行中” 的优化,本质上还是以解释执行为基础。
3. 关于 “依赖环境”
解释型语言确实依赖解释器(环境):
- Python 需要 Python 解释器,JavaScript 需要浏览器引擎或 Node.js(本质是 V8 引擎的独立运行环境)。
- 这是因为解释型语言的源代码不能直接被机器执行,必须通过解释器 “翻译”。
- 而编译型语言编译后的二进制文件,可直接在对应操作系统上运行,不依赖编译器(但仍受操作系统限制)。
总结
特性 | 编译型语言 | 解释型语言 |
---|---|---|
执行方式 | 预编译为机器码,直接运行 | 解释器边解释边执行 |
效率 | 高(无需重复翻译) | 较低(但 JIT 可优化) |
跨平台性 | 差(依赖操作系统) | 好(依赖解释器) |
典型代表 | C、C++、Go | Python、JavaScript、PHP |
简单说:编译型是 “一次翻译,多次运行”,解释型是 “每次运行都翻译”。JavaScript 的效率虽然不如编译型语言,但通过 JIT 等技术,已经能满足大多数场景的需求。