首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

Python-VBA函数之旅-zip函数

  • 25-03-03 04:43
  • 2707
  • 9279
blog.csdn.net

目录

一、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. # 1.函数:zip
  2. # 2.功能:
  3. # 2-1、无实参:用于创建空的迭代器
  4. # 2-2、有实参:用于将可迭代对象打包成元组
  5. # 3.语法:zip([*iterables, strict=False])
  6. # 4.参数:
  7. # 4-1、*iterables(可选):一个位置参数,表示任意数量的可迭代对象,如列表、字典、元组、字符串等,zip()函数允许多个可迭代对象作为参数
  8. # 4-2、strict(可选):迭代停止条件,默认为False,即作为迭代器对象的长度可以不一样;若设置为True,则要求所有的迭代器对象必须等长
  9. # 5.返回值:
  10. # 5-1、无实参:返回空的迭代器
  11. # 5-2、有实参:返回一个可迭代的zip对象,其内部元素为元组
  12. # 6.说明:
  13. # 6-1、如果未指定strict=True参数,所有导致可迭代对象长度不同的错误都会被抑制,这可能会在程序的其他地方表现为难以发现的错误
  14. # 7.示例:
  15. # 用dir()函数获取该函数内置的属性和方法
  16. print(dir(zip))
  17. # ['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getstate__',
  18. # '__gt__', '__hash__', '__init__', '__init_subclass__', '__iter__', '__le__', '__lt__', '__ne__', '__new__', '__next__',
  19. # '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setstate__', '__sizeof__', '__str__', '__subclasshook__']
  20. # 用help()函数获取该函数的文档信息
  21. help(zip)
  22. # 应用一:并行迭代
  23. # 示例1: 迭代两个列表
  24. list1 = [1, 2, 3]
  25. list2 = ['a', 'b', 'c']
  26. for item1, item2 in zip(list1, list2):
  27. print(f'{item1}, {item2}')
  28. # 1, a
  29. # 2, b
  30. # 3, c
  31. # 示例2: 迭代多个列表
  32. list1 = [1, 2, 3]
  33. list2 = ['a', 'b', 'c']
  34. list3 = ['one', 'two', 'three']
  35. for item1, item2, item3 in zip(list1, list2, list3):
  36. print(f'{item1}, {item2}, {item3}')
  37. # 1, a, one
  38. # 2, b, two
  39. # 3, c, three
  40. # 示例3: 列表长度不同时的处理
  41. from itertools import zip_longest
  42. list1 = [1, 2, 3]
  43. list2 = ['a', 'b']
  44. for item1, item2 in zip_longest(list1, list2, fillvalue='-'):
  45. print(f'{item1}, {item2}')
  46. # 1, a
  47. # 2, b
  48. # 3, -
  49. # 示例4: 使用字典解压来并行迭代
  50. names = ['Myelsa', 'Bruce', 'Jimmy']
  51. ages = [18, 6, 15]
  52. for name, age in zip(names, ages):
  53. print(f'{name} is {age} years old.')
  54. # 或者使用字典解压
  55. for name, age in zip(names, ages):
  56. person = {'name': name, 'age': age}
  57. print(f'{person["name"]} is {person["age"]} years old.')
  58. # Myelsa is 18 years old.
  59. # Bruce is 6 years old.
  60. # Jimmy is 15 years old.
  61. # Myelsa is 18 years old.
  62. # Bruce is 6 years old.
  63. # Jimmy is 15 years old.
  64. # 应用二:字典键值对解包
  65. # 示例1: 迭代字典的键和值
  66. # 假设我们有一个字典
  67. d = {'a': 1, 'b': 2, 'c': 3}
  68. # 使用items()方法直接迭代键和值
  69. for key, value in d.items():
  70. print(f'Key: {key}, Value: {value}')
  71. # 如果非要使用zip(),可以这样做(但通常不推荐)
  72. keys, values = zip(*d.items())
  73. for key, value in zip(keys, values):
  74. print(f'Key: {key}, Value: {value}')
  75. # 注意:上述zip()用法是不必要的,因为它没有提供任何额外的好处
  76. # 并且如果字典很大,它还会消耗额外的内存来存储keys和values元组
  77. # Key: a, Value: 1
  78. # Key: b, Value: 2
  79. # Key: c, Value: 3
  80. # Key: a, Value: 1
  81. # Key: b, Value: 2
  82. # Key: c, Value: 3
  83. # 示例2: 使用zip()将字典的键和值与其他可迭代对象组合
  84. # 原始字典的键
  85. keys = ['a', 'b', 'c']
  86. # 另一个列表的值
  87. values = [1, 2, 3]
  88. # 使用zip()将键和值组合成一个元组的迭代器
  89. key_value_pairs = zip(keys, values)
  90. # 将元组迭代器转换为字典
  91. new_dict = dict(key_value_pairs)
  92. print(new_dict)
  93. # {'a': 1, 'b': 2, 'c': 3}
  94. # 示例3: 解包字典的键和值到函数参数中
  95. def process_key_value(key, value):
  96. print(f'Processing key: {key}, value: {value}')
  97. # 字典
  98. d = {'a': 1, 'b': 2, 'c': 3}
  99. # 迭代字典的项并将它们作为参数传递给函数
  100. for key, value in d.items():
  101. process_key_value(key, value)
  102. # Processing key: a, value: 1
  103. # Processing key: b, value: 2
  104. # Processing key: c, value: 3
  105. # 应用三:处理不等长的迭代器
  106. # 使用zip迭代这些列表(注意:不会处理不等长)
  107. from itertools import zip_longest
  108. # 定义不等长的迭代器
  109. list1 = [1, 2, 3]
  110. list2 = ['a', 'b']
  111. list3 = ['x', 'y', 'z', 'w']
  112. # 使用zip_longest迭代这些列表,并为较短的列表填充默认值(例如None)
  113. for item1, item2, item3 in zip_longest(list1, list2, list3, fillvalue='-'):
  114. print(f'{item1}, {item2}, {item3}')
  115. # 1, a, x
  116. # 2, b, y
  117. # 3, -, z
  118. # -, -, w
  119. for item1, item2, item3 in zip(list1, list2, list3):
  120. print(f'{item1}, {item2}, {item3}')
  121. # 1, a, x
  122. # 2, b, y
  123. # 注意:'z'和'w'没有被打印出来,因为zip在最短的列表耗尽时停止了
  124. # 应用四:创建字典
  125. # 定义两个列表,一个作为键,一个作为值
  126. keys = ['a', 'b', 'c']
  127. values = [1, 2, 3]
  128. # 使用zip()将键和值组合成元组的迭代器
  129. key_value_pairs = zip(keys, values)
  130. # 将元组迭代器转换为字典
  131. dictionary = dict(key_value_pairs)
  132. # 打印创建的字典
  133. print(dictionary)
  134. # {'a': 1, 'b': 2, 'c': 3}
  135. # 应用五:与其他函数结合使用
  136. # 示例1: 与sorted()结合进行排序
  137. keys = ['c', 'a', 'b']
  138. values = [3, 1, 2]
  139. # 使用zip()将键和值组合成一个元组的列表,然后根据键进行排序
  140. sorted_items = sorted(zip(keys, values), key=lambda item: item[0])
  141. # 解包排序后的元组列表回两个单独的列表
  142. sorted_keys, sorted_values = zip(*sorted_items)
  143. # 如果需要列表而不是元组迭代器,可以转换为列表
  144. sorted_keys = list(sorted_keys)
  145. sorted_values = list(sorted_values)
  146. print(sorted_keys)
  147. print(sorted_values)
  148. # ['a', 'b', 'c']
  149. # [1, 2, 3]
  150. # 示例2: 与filter()结合进行过滤
  151. keys = ['a', 'b', 'a', 'c']
  152. values = [1, 2, 3, 4]
  153. # 使用filter()和lambda表达式过滤出键为'a'的元素对
  154. filtered_items = filter(lambda item: item[0] == 'a', zip(keys, values))
  155. # 将过滤后的迭代器转换为列表(如果需要)
  156. filtered_items_list = list(filtered_items)
  157. print(filtered_items_list)
  158. # [('a', 1), ('a', 3)]
  159. # 示例3: 与map()结合进行映射
  160. keys = ['a', 'b', 'c']
  161. values = [1, 2, 3]
  162. # 使用map()和lambda表达式将键和值相加(这里只是一个示例,通常键和值类型不同不会相加)
  163. # 但在实际应用中,你可以执行任何你需要的操作
  164. result = map(lambda item: item[0] + str(item[1]), zip(keys, values))
  165. # 将map对象转换为列表(如果需要)
  166. result_list = list(result)
  167. print(result_list)
  168. # ['a1', 'b2', 'c3']
  169. # 示例4: 与列表推导式结合使用
  170. keys = ['a', 'b', 'c']
  171. values = [1, 2, 3]
  172. # 使用列表推导式将键和值组合成字符串,并创建一个新列表
  173. combined = [f"{key}:{value}" for key, value in zip(keys, values)]
  174. print(combined)
  175. # ['a:1', 'b:2', 'c:3']
  176. # 应用六:数据预处理和转换
  177. # 示例1: 将两个列表中的元素合并成字典列表
  178. names = ['Myelsa', 'Bruce', 'Jimmy']
  179. ages = [18, 6, 15]
  180. # 使用 zip() 和列表推导式合并两个列表为字典列表
  181. people = [{'name': name, 'age': age} for name, age in zip(names, ages)]
  182. print(people)
  183. # [{'name': 'Myelsa', 'age': 18}, {'name': 'Bruce', 'age': 6}, {'name': 'Jimmy', 'age': 15}]
  184. # 示例2: 对两个列表中的元素进行数值转换
  185. prices = [100, 200, 300]
  186. discount_rates = [0.1, 0.15, 0.2]
  187. # 使用zip()和列表推导式计算折扣价格
  188. discounted_prices = [price * (1 - discount_rate) for price, discount_rate in zip(prices, discount_rates)]
  189. print(discounted_prices)
  190. # [90.0, 170.0, 240.0]
  191. # 示例3: 将两个列表中的字符串连接成新的字符串列表
  192. first_names = ['Myelsa', 'Bruce', 'Jimmy']
  193. last_names = ['Smith', 'Johnson', 'Brown']
  194. # 使用zip()和列表推导式连接字符串
  195. full_names = [first + ' ' + last for first, last in zip(first_names, last_names)]
  196. print(full_names)
  197. # ['Myelsa Smith', 'Bruce Johnson', 'Jimmy Brown']
  198. # 示例4: 合并多个列表为元组列表
  199. names = ['Myelsa', 'Bruce', 'Jimmy']
  200. ages = [18, 6, 15]
  201. cities = ['Guangzhou', 'Foshan', 'Los Angeles']
  202. # 使用zip()和列表推导式合并多个列表为元组列表
  203. person_info = [(name, age, city) for name, age, city in zip(names, ages, cities)]
  204. print(person_info)
  205. # [('Myelsa', 18, 'Guangzhou'), ('Bruce', 6, 'Foshan'), ('Jimmy', 15, 'Los Angeles')]
  206. # 应用七:文件操作
  207. # 文件名列表
  208. filenames = ['file.txt', 'test.txt']
  209. # 使用with open语句来确保文件在使用后正确关闭
  210. # 使用zip函数来同时读取每个文件的行
  211. with open(filenames[0], 'r') as file1, open(filenames[1], 'r') as file2:
  212. # 使用zip函数将两个文件对象(它们是可迭代的行)组合在一起
  213. for line1, line2 in zip(file1, file2):
  214. # 去除行尾的换行符(如果需要的话)
  215. line1 = line1.strip()
  216. line2 = line2.strip()
  217. # 打印或处理每对行
  218. print(f"从 file.txt 读取: {line1}")
  219. print(f"从 test.txt 读取: {line2}")
  220. print() # 打印一个空行以便区分不同的行对
  221. # 当 with 语句块结束时,文件将自动关闭
  222. # 从 file.txt 读取: 11
  223. # 从 test.txt 读取: 24
  224. #
  225. # 从 file.txt 读取: 22
  226. # 从 test.txt 读取: 32
  227. #
  228. # 从 file.txt 读取: 33
  229. # 从 test.txt 读取: 46
  230. import itertools
  231. filenames = ['file.txt', 'test.txt']
  232. with open(filenames[0], 'r') as file1, open(filenames[1], 'r') as file2:
  233. for line1, line2 in itertools.zip_longest(file1, file2, fillvalue=''):
  234. line1 = line1.strip() if line1 else '(无内容)'
  235. line2 = line2.strip() if line2 else '(无内容)'
  236. print(f"从 file1.txt 读取: {line1}")
  237. print(f"从 file2.txt 读取: {line2}")
  238. print()
  239. # 从 file1.txt 读取: 11
  240. # 从 file2.txt 读取: 24
  241. #
  242. # 从 file1.txt 读取: 22
  243. # 从 file2.txt 读取: 32
  244. #
  245. # 从 file1.txt 读取: 33
  246. # 从 file2.txt 读取: 46
  247. #
  248. # 从 file1.txt 读取: (无内容)
  249. # 从 file2.txt 读取: 58
  250. # 应用八:生成器表达式
  251. # 示例1: 合并两个迭代器并生成元组
  252. # 定义两个迭代器
  253. iter1 = range(1, 4)
  254. iter2 = range(10, 13)
  255. # 使用zip()和生成器表达式(这里实际上不需要,因为zip()已经是一个迭代器)
  256. zipped = zip(iter1, iter2)
  257. # 遍历结果
  258. for item in zipped:
  259. print(item)
  260. # (1, 10)
  261. # (2, 11)
  262. # (3, 12)
  263. # 示例2: 使用生成器表达式扩展zip()的结果
  264. # 定义两个迭代器
  265. iter1 = ['a', 'b', 'c']
  266. iter2 = [1, 2, 3]
  267. # 使用zip()和生成器表达式来转换结果
  268. formatted_items = (f"({item1}, {item2})" for item1, item2 in zip(iter1, iter2))
  269. # 遍历结果
  270. for item in formatted_items:
  271. print(item)
  272. # (a, 1)
  273. # (b, 2)
  274. # (c, 3)
  275. # 示例3: 处理不同长度的迭代器并填充缺失值
  276. import itertools
  277. # 定义两个不同长度的迭代器
  278. iter1 = ['a', 'b', 'c', 'd']
  279. iter2 = [1, 2, 3]
  280. # 使用itertools.zip_longest()和生成器表达式来处理不同长度的迭代器
  281. filled_items = (f"({item1 or 'None'}, {item2 or 'None'})" for item1, item2 in
  282. itertools.zip_longest(iter1, iter2, fillvalue='None'))
  283. # 遍历结果
  284. for item in filled_items:
  285. print(item)
  286. # (a, 1)
  287. # (b, 2)
  288. # (c, 3)
  289. # (d, None)
  290. # 应用九:代码简化
  291. # 示例1: 合并两个列表并解压为变量
  292. # 不使用zip()
  293. list1 = ['a', 'b', 'c']
  294. list2 = [1, 2, 3]
  295. for i in range(len(list1)):
  296. print(f"list1: {list1[i]}, list2: {list2[i]}")
  297. # 使用zip()简化
  298. for item1, item2 in zip(list1, list2):
  299. print(f"list1: {item1}, list2: {item2}")
  300. # list1: a, list2: 1
  301. # list1: b, list2: 2
  302. # list1: c, list2: 3
  303. # list1: a, list2: 1
  304. # list1: b, list2: 2
  305. # list1: c, list2: 3
  306. # 示例2: 合并多个列表为字典
  307. # 不使用zip()
  308. keys = ['a', 'b', 'c']
  309. values = [1, 2, 3]
  310. dictionary = {}
  311. for i in range(len(keys)):
  312. dictionary[keys[i]] = values[i]
  313. # 使用zip()简化
  314. dictionary = dict(zip(keys, values))
  315. print(dictionary)
  316. # {'a': 1, 'b': 2, 'c': 3}
  317. # 示例3: 交换列表中的元素位置
  318. # 原始列表
  319. list1 = ['a', 'b', 'c']
  320. list2 = [1, 2, 3]
  321. # 使用zip()交换元素位置(这里只是打印结果,实际并未交换列表)
  322. for item1, item2 in zip(list1, list2):
  323. print(f"Original: ({item1}, {item2}), Swapped: ({item2}, {item1})")
  324. # 如果真的想要交换两个列表的元素并存储到新的列表中
  325. swapped_list1, swapped_list2 = zip(*zip(list2, list1))
  326. swapped_list1, swapped_list2 = list(swapped_list1), list(swapped_list2)
  327. print(swapped_list1)
  328. print(swapped_list2)
  329. # Original: (a, 1), Swapped: (1, a)
  330. # Original: (b, 2), Swapped: (2, b)
  331. # Original: (c, 3), Swapped: (3, c)
  332. # [1, 2, 3]
  333. # ['a', 'b', 'c']
  334. # 示例4: 遍历多个列表并找出最长的字符串
  335. # 多个列表
  336. lists = [['apple', 'banana'], ['cat', 'dog', 'elephant'], ['fish']]
  337. # 使用zip()和max()找出每个列表中的最长字符串(但zip()在这里并不直接有用,因为它会截断到最短列表的长度)
  338. longest_strings = [max(lst, key=len) for lst in lists]
  339. print(longest_strings)
  340. # 如果我们确实想要用zip()来处理(尽管不推荐,因为会截断),可以这样做:
  341. # 注意:这只会给出最短列表中的最长字符串,因为zip()会停止在最短的迭代器结束处
  342. longest_in_zip = [max(tup, key=len) for tup in zip(*lists)]
  343. print(longest_in_zip)
  344. # ['banana', 'elephant', 'fish']
  345. # ['apple']
1-2、VBA:
略,待后补。
 2、推荐阅读:

2-1、Python-VBA函数之旅-enumerate()函数

Python算法之旅:Algorithms

Python函数之旅:Functions

个人主页:神奇夜光杯-CSDN博客
文章知识点与官方知识档案匹配,可进一步学习相关知识
算法技能树首页概览61139 人正在系统学习中
遨游码海,我心飞扬
微信名片
注:本文转载自blog.csdn.net的神奇夜光杯的文章"https://myelsa1024.blog.csdn.net/article/details/138850111"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top