Python-VBA函数之旅-zip函数
目录
一、zip函数的常见应用场景
二、zip函数使用注意事项
三、如何用好zip函数?
1、zip函数:
1-1、Python:
1-2、VBA:
2、推荐阅读:
个人主页:https://myelsa1024.blog.csdn.net/
一、zip函数的常见应用场景
zip函数在Python中有许多实用的应用场景,尤其是在处理多个列表或可迭代对象时,它提供了一种简洁而强大的方式来组合这些对象的元素,其常见的应用场景有:
1、并行迭代:当你有两个或多个列表,并且你想同时迭代它们时,zip()函数非常有用。例如,你可能有两个列表,一个包含名字,另一个包含对应的年龄,你想同时处理这两个列表中的元素。
2、字典键值对解包:在Python 3中,zip()函数经常与`*`操作符一起使用,用于字典的键值对解包,这在你需要交换字典的键和值时特别有用。
3、处理不等长的迭代器:当使用zip()函数迭代多个不等长的迭代器时,输出将仅在最短的迭代器耗尽时结束,这可以用于处理具有缺失数据的情况。
4、创建字典:你可以使用zip()函数和dict()函数来创建一个字典,其中一个列表包含键,另一个列表包含值。
5、与其他函数结合使用:zip()函数可以与Python中的其他函数(如map()、filter()、sorted()等)结合使用,以执行更复杂的操作。
6、数据预处理和转换:在数据分析和机器学习项目中,zip()函数可以用于同时处理多个特征列(例如,缩放或归一化多个特征)。
7、文件操作:在处理多个相关文件(如具有相同索引的数据和标签文件)时,zip()函数可以帮助你将它们的内容配对起来。
8、生成器表达式:你可以将zip()函数与生成器表达式结合使用,以创建更复杂的迭代器,而无需在内存中存储所有结果。
9、代码简化:在需要同时迭代多个可迭代对象的情况下,使用zip()函数可以使代码更简洁、更易读。
二、zip函数使用注意事项
在Python中使用zip()函数时,请注意以下事项:
1、返回迭代器:zip()函数返回的是一个迭代器,而不是一个列表,这意味着你只能遍历一次它的结果,除非你将其转换为列表、元组或其他可迭代对象。
2、不等长迭代器的处理:如果zip()函数中的可迭代对象长度不等,那么zip()函数将在最短的可迭代对象耗尽时停止,这可能会导致一些意料之外的行为,特别是当你期望所有迭代器的元素都被处理时。
3、与`*`运算符的结合使用:虽然zip()函数可以与`*`运算符结合使用来解包参数,但这通常不是zip()函数的常见用法,更常见的用法是使用`*`运算符与zip()函数的结果一起,将多个可迭代对象的元素作为单独的位置参数传递给函数。
4、修改元组内的值:由于zip()函数返回的是包含元组的迭代器或列表(如果你将其转换为列表),而元组是不可变的,因此你不能直接修改元组内的值,如果你需要修改元素,可以考虑将元组转换为列表。
5、内存使用:虽然zip()函数本身不会消耗大量内存(因为它是一个迭代器),但如果你将zip()函数的结果转换为列表,并且处理的数据集非常大,那么可能会消耗大量内存,在这种情况下,考虑使用其他方法来处理数据,如逐元素处理或使用生成器表达式。
6、Python版本差异:在Python 2中,zip()函数返回的是一个列表;但在Python 3中,它返回的是一个迭代器,这是Python 2和Python 3之间的一个重要区别,需要注意。
三、如何用好zip函数?
zip()函数在Python中是一个非常有用的内置函数,它允许你将多个可迭代对象(如列表、元组、字符串等)的元素打包成一个个元组,然后返回由这些元组组成的对象。为了用好zip()函数,请遵循以下建议:
1、并行迭代:当你需要同时迭代多个可迭代对象时,zip()函数非常有用,它允许你同时处理这些对象的元素。
2、处理不等长可迭代对象:默认情况下,zip()函数会在最短的可迭代对象耗尽时停止,如果你想要处理不等长的迭代器,并且希望保持较长的迭代器中剩余的元素,可以使用itertools.zip_longest()(在Python 2中是itertools.izip_longest())。
3、解压(Unzip):你可以使用zip(*...)来解压一个由元组组成的列表,或者任何形式的可迭代对象,只要它包含相同数量的元素。
4、与列表推导式结合使用:你可以将zip()与列表推导式结合使用,以创建新的数据结构或过滤数据。
5、作为字典的键和值:你可以使用zip()函数来创建一个字典,其中可迭代对象的元素作为键,另一个可迭代对象的元素作为值。
6、注意内存使用:当你处理大型数据集时,将zip()函数的结果转换为列表可能会消耗大量内存,在这种情况下,考虑使用迭代器直接处理数据,或者使用生成器表达式。
7、保持代码清晰:使用zip()函数时,确保你的代码易于阅读和理解,如果可能的话,为变量使用有意义的名称,并在必要时添加注释。
8、检查输入:在使用zip()函数之前,确保你的输入是可迭代的,并且长度是预期的,这有助于避免在运行时出现错误。
9、与map()函数结合使用:虽然zip()和map()在功能上有所不同,但你可以将它们结合使用来处理多个可迭代对象的元素。例如,你可以使用map()函数对每个元组应用一个函数。
1、zip函数:
1-1、Python:
# 1.函数:zip # 2.功能: # 2-1、无实参:用于创建空的迭代器 # 2-2、有实参:用于将可迭代对象打包成元组 # 3.语法:zip([*iterables, strict=False]) # 4.参数: # 4-1、*iterables(可选):一个位置参数,表示任意数量的可迭代对象,如列表、字典、元组、字符串等,zip()函数允许多个可迭代对象作为参数 # 4-2、strict(可选):迭代停止条件,默认为False,即作为迭代器对象的长度可以不一样;若设置为True,则要求所有的迭代器对象必须等长 # 5.返回值: # 5-1、无实参:返回空的迭代器 # 5-2、有实参:返回一个可迭代的zip对象,其内部元素为元组 # 6.说明: # 6-1、如果未指定strict=True参数,所有导致可迭代对象长度不同的错误都会被抑制,这可能会在程序的其他地方表现为难以发现的错误 # 7.示例: # 用dir()函数获取该函数内置的属性和方法 print(dir(zip)) # ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__', # '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__', # '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__'] # 用help()函数获取该函数的文档信息 help(zip) # 应用一:并行迭代 # 示例1: 迭代两个列表 list1 = [1, 2, 3] list2 = ['a', 'b', 'c'] for item1, item2 in zip(list1, list2): print(f'{item1}, {item2}') # 1, a # 2, b # 3, c # 示例2: 迭代多个列表 list1 = [1, 2, 3] list2 = ['a', 'b', 'c'] list3 = ['one', 'two', 'three'] for item1, item2, item3 in zip(list1, list2, list3): print(f'{item1}, {item2}, {item3}') # 1, a, one # 2, b, two # 3, c, three # 示例3: 列表长度不同时的处理 from itertools import zip_longest list1 = [1, 2, 3] list2 = ['a', 'b'] for item1, item2 in zip_longest(list1, list2, fillvalue='-'): print(f'{item1}, {item2}') # 1, a # 2, b # 3, - # 示例4: 使用字典解压来并行迭代 names = ['Myelsa', 'Bruce', 'Jimmy'] ages = [18, 6, 15] for name, age in zip(names, ages): print(f'{name} is {age} years old.') # 或者使用字典解压 for name, age in zip(names, ages): person = {'name': name, 'age': age} print(f'{person["name"]} is {person["age"]} years old.') # Myelsa is 18 years old. # Bruce is 6 years old. # Jimmy is 15 years old. # Myelsa is 18 years old. # Bruce is 6 years old. # Jimmy is 15 years old. # 应用二:字典键值对解包 # 示例1: 迭代字典的键和值 # 假设我们有一个字典 d = {'a': 1, 'b': 2, 'c': 3} # 使用items()方法直接迭代键和值 for key, value in d.items(): print(f'Key: {key}, Value: {value}') # 如果非要使用zip(),可以这样做(但通常不推荐) keys, values = zip(*d.items()) for key, value in zip(keys, values): print(f'Key: {key}, Value: {value}') # 注意:上述zip()用法是不必要的,因为它没有提供任何额外的好处 # 并且如果字典很大,它还会消耗额外的内存来存储keys和values元组 # Key: a, Value: 1 # Key: b, Value: 2 # Key: c, Value: 3 # Key: a, Value: 1 # Key: b, Value: 2 # Key: c, Value: 3 # 示例2: 使用zip()将字典的键和值与其他可迭代对象组合 # 原始字典的键 keys = ['a', 'b', 'c'] # 另一个列表的值 values = [1, 2, 3] # 使用zip()将键和值组合成一个元组的迭代器 key_value_pairs = zip(keys, values) # 将元组迭代器转换为字典 new_dict = dict(key_value_pairs) print(new_dict) # {'a': 1, 'b': 2, 'c': 3} # 示例3: 解包字典的键和值到函数参数中 def process_key_value(key, value): print(f'Processing key: {key}, value: {value}') # 字典 d = {'a': 1, 'b': 2, 'c': 3} # 迭代字典的项并将它们作为参数传递给函数 for key, value in d.items(): process_key_value(key, value) # Processing key: a, value: 1 # Processing key: b, value: 2 # Processing key: c, value: 3 # 应用三:处理不等长的迭代器 # 使用zip迭代这些列表(注意:不会处理不等长) from itertools import zip_longest # 定义不等长的迭代器 list1 = [1, 2, 3] list2 = ['a', 'b'] list3 = ['x', 'y', 'z', 'w'] # 使用zip_longest迭代这些列表,并为较短的列表填充默认值(例如None) for item1, item2, item3 in zip_longest(list1, list2, list3, fillvalue='-'): print(f'{item1}, {item2}, {item3}') # 1, a, x # 2, b, y # 3, -, z # -, -, w for item1, item2, item3 in zip(list1, list2, list3): print(f'{item1}, {item2}, {item3}') # 1, a, x # 2, b, y # 注意:'z'和'w'没有被打印出来,因为zip在最短的列表耗尽时停止了 # 应用四:创建字典 # 定义两个列表,一个作为键,一个作为值 keys = ['a', 'b', 'c'] values = [1, 2, 3] # 使用zip()将键和值组合成元组的迭代器 key_value_pairs = zip(keys, values) # 将元组迭代器转换为字典 dictionary = dict(key_value_pairs) # 打印创建的字典 print(dictionary) # {'a': 1, 'b': 2, 'c': 3} # 应用五:与其他函数结合使用 # 示例1: 与sorted()结合进行排序 keys = ['c', 'a', 'b'] values = [3, 1, 2] # 使用zip()将键和值组合成一个元组的列表,然后根据键进行排序 sorted_items = sorted(zip(keys, values), key=lambda item: item[0]) # 解包排序后的元组列表回两个单独的列表 sorted_keys, sorted_values = zip(*sorted_items) # 如果需要列表而不是元组迭代器,可以转换为列表 sorted_keys = list(sorted_keys) sorted_values = list(sorted_values) print(sorted_keys) print(sorted_values) # ['a', 'b', 'c'] # [1, 2, 3] # 示例2: 与filter()结合进行过滤 keys = ['a', 'b', 'a', 'c'] values = [1, 2, 3, 4] # 使用filter()和lambda表达式过滤出键为'a'的元素对 filtered_items = filter(lambda item: item[0] == 'a', zip(keys, values)) # 将过滤后的迭代器转换为列表(如果需要) filtered_items_list = list(filtered_items) print(filtered_items_list) # [('a', 1), ('a', 3)] # 示例3: 与map()结合进行映射 keys = ['a', 'b', 'c'] values = [1, 2, 3] # 使用map()和lambda表达式将键和值相加(这里只是一个示例,通常键和值类型不同不会相加) # 但在实际应用中,你可以执行任何你需要的操作 result = map(lambda item: item[0] + str(item[1]), zip(keys, values)) # 将map对象转换为列表(如果需要) result_list = list(result) print(result_list) # ['a1', 'b2', 'c3'] # 示例4: 与列表推导式结合使用 keys = ['a', 'b', 'c'] values = [1, 2, 3] # 使用列表推导式将键和值组合成字符串,并创建一个新列表 combined = [f"{key}:{value}" for key, value in zip(keys, values)] print(combined) # ['a:1', 'b:2', 'c:3'] # 应用六:数据预处理和转换 # 示例1: 将两个列表中的元素合并成字典列表 names = ['Myelsa', 'Bruce', 'Jimmy'] ages = [18, 6, 15] # 使用 zip() 和列表推导式合并两个列表为字典列表 people = [{'name': name, 'age': age} for name, age in zip(names, ages)] print(people) # [{'name': 'Myelsa', 'age': 18}, {'name': 'Bruce', 'age': 6}, {'name': 'Jimmy', 'age': 15}] # 示例2: 对两个列表中的元素进行数值转换 prices = [100, 200, 300] discount_rates = [0.1, 0.15, 0.2] # 使用zip()和列表推导式计算折扣价格 discounted_prices = [price * (1 - discount_rate) for price, discount_rate in zip(prices, discount_rates)] print(discounted_prices) # [90.0, 170.0, 240.0] # 示例3: 将两个列表中的字符串连接成新的字符串列表 first_names = ['Myelsa', 'Bruce', 'Jimmy'] last_names = ['Smith', 'Johnson', 'Brown'] # 使用zip()和列表推导式连接字符串 full_names = [first + ' ' + last for first, last in zip(first_names, last_names)] print(full_names) # ['Myelsa Smith', 'Bruce Johnson', 'Jimmy Brown'] # 示例4: 合并多个列表为元组列表 names = ['Myelsa', 'Bruce', 'Jimmy'] ages = [18, 6, 15] cities = ['Guangzhou', 'Foshan', 'Los Angeles'] # 使用zip()和列表推导式合并多个列表为元组列表 person_info = [(name, age, city) for name, age, city in zip(names, ages, cities)] print(person_info) # [('Myelsa', 18, 'Guangzhou'), ('Bruce', 6, 'Foshan'), ('Jimmy', 15, 'Los Angeles')] # 应用七:文件操作 # 文件名列表 filenames = ['file.txt', 'test.txt'] # 使用with open语句来确保文件在使用后正确关闭 # 使用zip函数来同时读取每个文件的行 with open(filenames[0], 'r') as file1, open(filenames[1], 'r') as file2: # 使用zip函数将两个文件对象(它们是可迭代的行)组合在一起 for line1, line2 in zip(file1, file2): # 去除行尾的换行符(如果需要的话) line1 = line1.strip() line2 = line2.strip() # 打印或处理每对行 print(f"从 file.txt 读取: {line1}") print(f"从 test.txt 读取: {line2}") print() # 打印一个空行以便区分不同的行对 # 当 with 语句块结束时,文件将自动关闭 # 从 file.txt 读取: 11 # 从 test.txt 读取: 24 # # 从 file.txt 读取: 22 # 从 test.txt 读取: 32 # # 从 file.txt 读取: 33 # 从 test.txt 读取: 46 import itertools filenames = ['file.txt', 'test.txt'] with open(filenames[0], 'r') as file1, open(filenames[1], 'r') as file2: for line1, line2 in itertools.zip_longest(file1, file2, fillvalue=''): line1 = line1.strip() if line1 else '(无内容)' line2 = line2.strip() if line2 else '(无内容)' print(f"从 file1.txt 读取: {line1}") print(f"从 file2.txt 读取: {line2}") print() # 从 file1.txt 读取: 11 # 从 file2.txt 读取: 24 # # 从 file1.txt 读取: 22 # 从 file2.txt 读取: 32 # # 从 file1.txt 读取: 33 # 从 file2.txt 读取: 46 # # 从 file1.txt 读取: (无内容) # 从 file2.txt 读取: 58 # 应用八:生成器表达式 # 示例1: 合并两个迭代器并生成元组 # 定义两个迭代器 iter1 = range(1, 4) iter2 = range(10, 13) # 使用zip()和生成器表达式(这里实际上不需要,因为zip()已经是一个迭代器) zipped = zip(iter1, iter2) # 遍历结果 for item in zipped: print(item) # (1, 10) # (2, 11) # (3, 12) # 示例2: 使用生成器表达式扩展zip()的结果 # 定义两个迭代器 iter1 = ['a', 'b', 'c'] iter2 = [1, 2, 3] # 使用zip()和生成器表达式来转换结果 formatted_items = (f"({item1}, {item2})" for item1, item2 in zip(iter1, iter2)) # 遍历结果 for item in formatted_items: print(item) # (a, 1) # (b, 2) # (c, 3) # 示例3: 处理不同长度的迭代器并填充缺失值 import itertools # 定义两个不同长度的迭代器 iter1 = ['a', 'b', 'c', 'd'] iter2 = [1, 2, 3] # 使用itertools.zip_longest()和生成器表达式来处理不同长度的迭代器 filled_items = (f"({item1 or 'None'}, {item2 or 'None'})" for item1, item2 in itertools.zip_longest(iter1, iter2, fillvalue='None')) # 遍历结果 for item in filled_items: print(item) # (a, 1) # (b, 2) # (c, 3) # (d, None) # 应用九:代码简化 # 示例1: 合并两个列表并解压为变量 # 不使用zip() list1 = ['a', 'b', 'c'] list2 = [1, 2, 3] for i in range(len(list1)): print(f"list1: {list1[i]}, list2: {list2[i]}") # 使用zip()简化 for item1, item2 in zip(list1, list2): print(f"list1: {item1}, list2: {item2}") # list1: a, list2: 1 # list1: b, list2: 2 # list1: c, list2: 3 # list1: a, list2: 1 # list1: b, list2: 2 # list1: c, list2: 3 # 示例2: 合并多个列表为字典 # 不使用zip() keys = ['a', 'b', 'c'] values = [1, 2, 3] dictionary = {} for i in range(len(keys)): dictionary[keys[i]] = values[i] # 使用zip()简化 dictionary = dict(zip(keys, values)) print(dictionary) # {'a': 1, 'b': 2, 'c': 3} # 示例3: 交换列表中的元素位置 # 原始列表 list1 = ['a', 'b', 'c'] list2 = [1, 2, 3] # 使用zip()交换元素位置(这里只是打印结果,实际并未交换列表) for item1, item2 in zip(list1, list2): print(f"Original: ({item1}, {item2}), Swapped: ({item2}, {item1})") # 如果真的想要交换两个列表的元素并存储到新的列表中 swapped_list1, swapped_list2 = zip(*zip(list2, list1)) swapped_list1, swapped_list2 = list(swapped_list1), list(swapped_list2) print(swapped_list1) print(swapped_list2) # Original: (a, 1), Swapped: (1, a) # Original: (b, 2), Swapped: (2, b) # Original: (c, 3), Swapped: (3, c) # [1, 2, 3] # ['a', 'b', 'c'] # 示例4: 遍历多个列表并找出最长的字符串 # 多个列表 lists = [['apple', 'banana'], ['cat', 'dog', 'elephant'], ['fish']] # 使用zip()和max()找出每个列表中的最长字符串(但zip()在这里并不直接有用,因为它会截断到最短列表的长度) longest_strings = [max(lst, key=len) for lst in lists] print(longest_strings) # 如果我们确实想要用zip()来处理(尽管不推荐,因为会截断),可以这样做: # 注意:这只会给出最短列表中的最长字符串,因为zip()会停止在最短的迭代器结束处 longest_in_zip = [max(tup, key=len) for tup in zip(*lists)] print(longest_in_zip) # ['banana', 'elephant', 'fish'] # ['apple']
1-2、VBA:
略,待后补。
2、推荐阅读:
2-1、Python-VBA函数之旅-enumerate()函数
Python算法之旅:Algorithms
Python函数之旅:Functions