Python 数据结构之字典

Python-dictionary

[Reference]
[1] https://docs.python.org/3/library/stdtypes.html#typesmapping

1. dict 格式和特性

A mapping object maps hashable values to arbitrary objects. Mappings are mutable objects. There is currently only one standard mapping type, the dictionary.

映射对象将可散列的值映射为任意对象。映射是可变对象,目前只有一种标准映射类型:字典。

注意

  1. 虽然字典的键(key)几乎是任意可散列值(不可散列的值:listdict或其他可变对象);

  2. 用于键的数字类型遵循数字比较规则,因此可以使用浮点数(近似)但是不建议;

  3. 可散列:如果一个对象是可散列的,那么这个对象的生命周期中,其对应的散列值是不可变的,而且这个对象需要实现__hash__()方法,同时可散列对象还需要__eq__()方法,方便和其他键值进行比较。通常原子不可变数据类型 strbytes 和数值类型都是可散列的;

  4. 一般来讲用户自定义的类型都是可散列的,通过id()函数即可获取其对应的散列值,在没有创建 __eq__() 方法,所有这些对象都是不等的,假设一个对象实现该方法且用到了该对象的内部状态,那么当所有这些内部状态均不可变,这个对象才是可散列的;

  5. frozenset也是可散列的(因为frozenset只能容纳可散列类型)

字典创建

字典可以通过在大括号中逗号分隔的多个键值对key: value创建,典型如下:

  • dict_a = {'jack': 4098, 'sjoerd': 4127}
  • dict_a = {x: x ** 2 for x in range(10)} 字典推导
  • dict([('a', 100), ('b', 200)]) 元组解包

补充事项

  • 如果没有给出位置参数(key: value),则创建一个空字典;
  • 如果给出了一个位置参数并且它是一个映射对象,则使用与映射对象相同的键值对创建一个字典,否则,位置参数必须是可迭代对象;
  • 可迭代对象中的每个项目本身必须是一个恰好有两个对象的可迭代对象。每个项目的第一个对象成为新字典中的键,第二个对象成为相应的值;
  • 如果某个键出现多次,则该键的最后一个值将成为新字典中的相应值。
  • 如果给出了关键字参数,则关键字参数及其值将添加到从位置参数创建的字典中。如果要添加的键已经存在,则来自关键字参数的值将替换来自位置参数的值。

2. dict 初始化

通常我们只会用第一节所写的方式初始化字典 {key: value, …},参考如下代码,官方文档中还给出了其他的初始化方式:

  • 使用zip将对应的键和值list捆绑成键值对;
  • 使用多个元组构成的list,根据元组的解包特性实现;这里注意:传入dict的可以是[]/()对象,其成员满足包含两个元素;
  • 混合使用花括号和=
  • 使用字典推导。
""" initial dict """
a = dict(one=1, two=2, three=3)
b = {'one': 1, 'two': 2, 'three': 3}
c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
d = dict([('two', 2), ('three', 3), ('one', 1)])
e = dict({'three': 3, 'one': 1, 'two': 2})
f = dict({'one': 1, 'three': 3}, two=2)
info = [(1, 'one'),
		(2, 'two'),
		(3, 'three')]
g = {key: value for value, key in info}
print(a == b == c == d == e == f == g)

除了以上这些方式,还可以通过字典的方法:fromkeys(),从序列中批量创建指定值的字典,详情见后。
res = dict.fromkeys(range(10), 1)

3. dict 方法

这里直接拉取官方文档的方法。详情参考后续展开部分。

  • list(d)
  • len(d)
  • d[key]
  • d[key] = value
  • del d[key]
  • key in d / key not in d
  • iter(d)
  • clear()
  • copy()
  • get(key, [, default])
  • items()
  • keys()
  • values()
  • pop(key, [, default])
  • popitem()
  • reversed(d)
  • setdefault()
  • update()
  • d | other
  • d |= other

后续使用的例子a均使用字典推导式(其原理和列表推导式一致)。

3.1 list(d)

将字典的键返回成list,参考如下列子:

a = {x: x * 2 for x in range(6)}
print('d = {}'.format(a))
print('Test list(d): {}'.format(list(a)))
# 测试结果
d = {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10}
Test list(d): [0, 1, 2, 3, 4, 5]

3.2 len(d)

返回字典的键值对(key/value)个数。

a = {x: x * 2 for x in range(6)}
len(a)	# res: 6

3.3 d[key]

根据键从字典获取对应值的信息。

a = {x: x * 2 for x in range(6)}
a[0]	# a[0] = 0

3.4 d[key] = value

设置键的新值。

a = {x: x * 2 for x in range(6)}
a[0] = 100
a
# 测试结果
{0: 100, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10}

3.5 del d[key]

删除指定的键值对

a = {x: x * 2 for x in range(6)}
del a[0]
a
# 测试结果
{1: 2, 2: 4, 3: 6, 4: 8, 5: 10}

3.6 key in d

判断字典中是否存在对应的键**key**,非 用法key not in d

a = {x: x * 2 for x in range(6)}

print('Key verify: 0 in a: [{}], 7 in a: [{}], 8 not in a: [{}]'.format(0 in a, 7 in a, 8 not in a))
Key verify: 0 in a: [True], 7 in a: [False], 8 not in a: [True]

3.7 iter(d)

基于字典的键返回一个迭代器,其对应iter(d.keys())

a = {x: x * 2 for x in range(6)}
print(list(iter(a)))
# 测试结果
[0, 1, 2, 3, 4, 5]

3.8 clear()

清空字典,删除所有项目。

a = {x: x * 2 for x in range(6)}
print('a = {}'.format(a))
a.clear()
print('Use clear(): a = {}'.format(a))
a = {0: 0, 1: 2, 2: 4, 3: 6, 4: 8, 5: 10}
Use clear(): a = {}

3.9 copy()

拷贝字典,需要注意这里的拷贝是浅拷贝。这里的浅拷贝不同于list的浅拷贝,字典的浅拷贝实际是深拷贝父对象(一级目录),子对象(二级目录)不拷贝而是引用。直接使用=赋值,则是使用引用。

import copy


a = {x: x * 2 for x in range(3)}
a[4] = [1, 2, 3]

b = a                   # reference assignment.
c = a.copy()            # just deep copy 1st layer
d = copy.deepcopy(a)    # all deep copy

# alter b[0], b[4]
b[0] = 7
b[4].append(4)
print('a = {}, b = {}, c = {}, d = {}'.format(a, b, c, d))
print('a == b is {}'.format(a == b))

# alter c[0], c[4]
c[0] = 9
c[4].remove(1)
print('a = {}, b = {}, c = {}, d = {}'.format(a, b, c, d))
# 测试结果
a = {0: 7, 1: 2, 2: 4, 4: [1, 2, 3, 4]}, b = {0: 7, 1: 2, 2: 4, 4: [1, 2, 3, 4]}, c = {0: 0, 1: 2, 2: 4, 4: [1, 2, 3, 4]}, d = {0: 0, 1: 2, 2: 4, 4: [1, 2, 3]}
a == b is True
a = {0: 7, 1: 2, 2: 4, 4: [2, 3, 4]}, b = {0: 7, 1: 2, 2: 4, 4: [2, 3, 4]}, c = {0: 9, 1: 2, 2: 4, 4: [2, 3, 4]}, d = {0: 0, 1: 2, 2: 4, 4: [1, 2, 3]}

stackoverflow: dict-shallow-copy

stackoverflow 关于该讨论给出了几个数据共享示意图。对应上述代码可知:

  • b 即 a 的引用
  • c 共享了一级的键值,对于值中的二级可变对象或者嵌套字典则为引用;
  • d 完全地独立

3.10 classmethod fromkeys(iterable[, value])

基于可迭代对象(典型如 list )和初值,创建一个键为可迭代对象的值,值为初值的字典,即所有的值都引用自一个实例。

注意:如果未设置初值 value ,则默认为 None

seq_list = ['google', 'facebook', 'microsoft', 'alibaba', 'tencent']
seq_tuple = ('google', 'facebook', 'microsoft', 'alibaba', 'tencent')

a = dict.fromkeys(seq_list)
b = dict.fromkeys(seq_tuple)
print('a == b is {}'.format(a == b))
print(a)
c = dict.fromkeys(seq_tuple, 1)             # set value is 1
d = dict.fromkeys(seq_tuple, [1, 2, 3, 4])  # set value is list: [1,2,3,4]
print(c)
print(d)
# test result
a == b is True
{'google': None, 'facebook': None, 'microsoft': None, 'alibaba': None, 'tencent': None}
{'google': 1, 'facebook': 1, 'microsoft': 1, 'alibaba': 1, 'tencent': 1}
{'google': [1, 2, 3, 4], 'facebook': [1, 2, 3, 4], 'microsoft': [1, 2, 3, 4], 'alibaba': [1, 2, 3, 4], 'tencent': [1, 2, 3, 4]}

3.11 get(key[, default])

同3.3 获取对应keyvalue,如果字典中不存在,则返回默认值(None),如果默认值不存在则抛出KeyError

a = {x: x * 2 for x in range(3)}
a.get(1)	# 2

3.12 items()

获取字典全部键值对的新视图(元组数组)。

a = {x: x * 2 for x in range(3)}
print(a.items())
# test result
dict_items([(0, 0), (1, 2), (2, 4)])

3.13 keys()

返回字典中全部键(key

a = {x: x * 2 for x in range(3)}
print(a.keys())
dict_keys([0, 1, 2])

3.14 pop(key[, default])

如果键在字典中,则移除键并且返回value,否则返回默认值,如果默认值不存在,则抛出keyError

a = {x: x * 2 for x in range(3)}
print(a.pop(2))
print(a)
# test result
4
{0: 0, 1: 2}

3.15 popitem()

从键值中按栈(LIFO: 后进先出)顺序删除并返回对应的键值对。LIFO需要ver.>=3.7

a = {x: x * 2 for x in range(3)}
print('{}->{}->{}'.format(a.popitem(), a.popitem(), a.popitem()))
# test result
(2, 4)->(1, 2)->(0, 0)

3.16 reversed()

在字典的键上返回一个反向迭代器,其相当于reversed(d.keys())

a = {x: x * 2 for x in range(3)}
b = list(reversed(a))
print(b)
# test result
[2, 1, 0]

3.17 setdefault(key[, default])

如果键存在则返回对应的值,反之添加该键并将值设为默认值。

a = {x: x * 2 for x in range(3)}
a.setdefault(4)
print(a)
# test result
{0: 0, 1: 2, 2: 4, 4: None}

3.18 update([other])

使用其他的键值对覆盖现有键,返回None。other可以是另一个字典对象或者键/值对的可迭代对象(元组)。如果指定关键字参数,字典,然后用这些键/值对更新:d.update(red=1, blue=2)
update() 函数处理参数m的方式,是典型的 duck typingref1ref2。函数首先检查m是否有keys方法,如果有,那么update()函数就把它当做映射对象处理。否则函数会退一步,转而把m 当做包含了键值对(key, value) 元素的迭代器。

a = {x: x * 2 for x in range(3)}
b = {x: x ** 2 for x in range(4)}

a.update(b)
print(a)

b.update(age=25)
print(b)

a.update(name='naruto', age=20)
print(a)

b.update({'age': 25})
print(b)
# test result
{0: 0, 1: 1, 2: 4, 3: 9}
{0: 0, 1: 1, 2: 4, 3: 9, 'age': 25}
{0: 0, 1: 1, 2: 4, 3: 9, 'name': 'naruto', 'age': 20}
{0: 0, 1: 1, 2: 4, 3: 9, 'age': 25}

3.19 values()

返回字典中所有键对应的值。

a = {x: x * 2 for x in range(3)}
print(list(a.values()))
# test result
[0, 2, 4]

3.20 d | other

合并 d 和 other 中的键和值来创建一个新的字典,两者必须都是字典。当 d 和 other 有相同键时, other 的值优先。注意仅支持 python>= 3.9

a = {x: x * 2 for x in range(3)}
other = {x: x ** 2 for x in range(3)}
b = a | other
print(b)

3.21 d |= other

用 other 的键和值更新字典 d ,other 可以是 mapping 或 iterable 的键值对。当 d 和 other 有相同键时, other 的值优先。注意仅支持 python>= 3.9

a = {x: x * 2 for x in range(3)}
other = {x: x ** 2 for x in range(3)}
print(a |= other)
<think>好的,我现在需要帮助用户解决关于Dify循环实现的问题。首先,我需要明确用户的具体需求。他们提到“dify 循环实现”或“dify 如何处理循环”,但Dify本身可能没有直接称为“循环”的功能,所以需要结合现有文档中的信息来推断可能的解决方案。 根据用户提供的引用内容,Dify工作流中有迭代节点[^1]。这可能类似于编程中的循环结构,用于重复执行某个任务。例如,在处理列表数据或需要多次执行同一操作时,迭代节点可以派上用场。我需要详细解释迭代节点的配置和使用步骤,确保用户能够理解如何设置循环次数或遍历数据集。 另外,用户可能对如何处理循环中的错误或性能问题感兴趣。引用[2]提到在Dify中处理PEM文件的问题,这可能涉及在循环中正确处理数据格式,避免错误积累。需要提醒用户在循环中注意错误处理和资源管理,确保每次迭代的稳定性。 引用[3]中的例子展示了如何结合FastAPI和Selenium进行实时监控并生成GIF,这可能涉及循环截取浏览器内容。虽然Dify本身可能不直接控制这类循环,但可以通过外部脚本或定时任务触发工作流,模拟循环执行。这部分需要说明如何将外部循环机制与Dify结合使用。 接下来,我需要组织回答结构。首先介绍迭代节点的基本概念和配置步骤,然后讨论循环中的数据处理和错误处理,最后补充外部触发循环的方法。同时,生成相关问题以帮助用户进一步探索,比如优化循环性能或处理复杂数据结构。 需要确保回答符合格式要求,使用正确的中文表达,行内公式用$...$,独立公式用$$...$$,但当前问题不涉及数学公式,所以可能不需要使用。同时,引用标识要自然地添加到相关段落末尾,如、[^2]、[^3]。 最后,检查是否有遗漏点,比如Dify的其他循环相关功能或用户可能遇到的常见问题,确保回答全面且易于理解。</think>在Dify中处理循环逻辑主要通过**迭代节点**实现,以下是具体实现方式和应用场景的解析: ### 一、Dify循环实现机制 Dify通过**工作流设计器**中的迭代节点处理循环需求,其核心原理类似编程中的`for循环`。迭代节点可遍历以下数据类型: - 数组列表:`["A","B","C"]` - 字典集合:`{"key1":"value1", "key2":"value2"}` - 数值范围:通过`range()`函数生成序列 配置示例: ```python # 模拟迭代节点的数据输入 input_data = { "dataset": [1,2,3,4,5], "process_logic": "item * 2" # 对每个元素执行乘以2的操作 } ``` ### 二、迭代节点的关键配置步骤 1. **数据源绑定**:将数组/字典类型变量连接到迭代节点的输入端口 2. **循环变量命名**:设定当前元素的变量名(默认为`item`) 3. **子流程设计**:在迭代节点内部构建需要重复执行的逻辑模块 4. **结果聚合**:通过`outputs`收集所有迭代结果,支持数组或对象格式 $$ \text{总耗时} = \sum_{i=1}^{n}(单次迭代时间_i) + 系统开销 $$ ### 三、循环中的特殊处理 1. **错误中断控制**: - 启用`continueOnError`参数可跳过失败迭代 - 通过`try-catch`模块包裹敏感操作 2. **并行优化**: ```python # 伪代码示例 Parallel.forEach(dataset, lambda item: process(item)) ``` 3. **结果过滤**: ```python filtered = filter(lambda x: x%2==0, processed_results) ``` ### 四、应用场景案例 1. **批量文件处理**:遍历存储桶中的文件列表进行格式转换 2. **数据清洗**:对数据库查询结果集进行逐条校验 3. **API轮询**:定时循环调用第三方接口直到满足特定条件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值