SOP/详解*和**/python数据结构(iter,list,tuple,dict)/ 解包

一、错误解决合集

1 .

====> combined_seq.named_children()
2 .

isinstance 2th parameter : must be a type or tuple of types ====> 改为tuple,不要用列表。改为 LLLayer = (nn.Conv2d,nn.Linear)

3 .

File "test.py", line 90, in calculate_fin_fout

print("hi", seq[k].weight.shape[0], layers_fin_fout["fout"][module])

KeyError: ScaledNeuron(

(neuron): IFNode(

v_threshold=1.0, v_reset=None, detach_reset=False

(surrogate_function): Sigmoid(alpha=1.0, spiking=True)

)

)
KeyError:

试图在字典中查找不存在的

试图通过属性访问或键索引获取对象的属性或字典中的键,但对象或字典中不存在这样的键或属性。

可能在使用类似字典的数据结构时,由于使用了无效的键或索引导致查找失败。
这里是键不存在的问题!首先要搞清楚什么是键?layers_fin_fout["fout"][module]为键。注意:键需要初始化。键在使用之前一定要初始化,一层一层的初始化:

python 复制代码
`layers_fin_fout["fout"] = {}
layers_fin_fout["fout"][module] = 0

二、

1、什么是拆包(解包)和封包:

拆包就是将列表(list)、元组(tuple)、字典(dict)三种类型的元素,全部提炼出来的过程;或者是使用变量去接收函数返回值的过程

封包是将多个值赋值给一个变量时,python会自动将这些值封装成元组,这个特性称之为封包;或者函数返回多个值时,也会进行封包

2、拆包的注意事项:

拆包时,接收返回数据的变量一定要与列表(list)、元组(tuple)、字典(dict)中的元素个数相同,否则会导致程序异常

三、数据结构:迭代器和集合的配合

这里的集合指:list,dict,tuple,set

基础

Python 中的集合类和迭代器是两个不同的概念,它们并没有继承关系。Python 中的集合类并不是继承自迭代器接口,而是通过实现特定的协议和方法来支持迭代器行为。在 Python 中,实现了迭代器接口的对象必须具有__iter__()__next__()方法反过来说,在 Python 中,迭代器是一种用于遍历可迭代对象的工具,它提供了 __iter__()__next__() 方法。当一个对象实现了这两个方法时,它就是一个迭代器,可以通过iter()函数获得。 也就是说对象可以支持迭代器行为。
__iter__() 方法返回迭代器对象自身,而 __next__() 方法用于获取迭代器的下一个元素。集合类可以实现这两个方法来支持迭代器行为,使得它们可以被iter()函数返回对应的迭代器,并支持使用 next() 方法来遍历元素。

a.Iterator迭代器

迭代器(Iterator)并不像列表(List)那样可以直接输出(打印)所有元素 。迭代器是一种按需生成元素的对象,每次只生成一个元素。要从迭代器中获取元素,必须使用for循环或next()函数逐个获取。

python 复制代码
my_iterator = iter([1, 2, 3])
for element in my_iterator:
    print(element)
 # 1, 2,3
python 复制代码
my_iterator = iter([1, 2, 3])
print(next(my_iterator))  # 输出:1
print(next(my_iterator))  # 输出:2
print(next(my_iterator))  # 输出:3

b.集合list,dict,tuple,set

集合可以直接print输出。且所有集合实现了 __iter__()__next__() 方法,那么他就是一个可迭代对象 。从而,你可以直接隐式的遍历 集合,因为他可迭代,实际是调用的内部实现的__iter__()

python 复制代码
my_list = [1, 2, 3, 4, 5]
for element in my_list:
    print(element)

当你需要索引时用emumerate函数 生成索引,enumerate函数返回的也是一个迭代器 (index, content),所以你可以遍历。

所以,综上所述,for 循环的语法是 f o r for for e l e m e n t element element i n in in i t e r a b l e iterable iterable,iterable可以是:

  • 序列类型:例如列表(list)、元组(tuple)、字符串(str)等。
  • 集合类型:例如集合(set)和字典(dict)。
  • 文件对象:例如使用 open() 函数打开的文件对象。
  • 迭代器:例如使用 iter() 函数获得的迭代器。

c.区分:

  1. __iter__()
    __iter__() 是一个特殊的方法名,用于在 Python 类中定义一个对象的迭代器。当我们在一个类中定义了__iter__()方法时,这个类的实例就成为了可迭代的对象,即支持迭代操作。
    __iter__() 方法应该返回一个迭代器对象,通常是 self 本身,或者是实现了 __next__() 方法的对象。这个迭代器对象可以用于在 for 循环中遍历对象的元素。
  2. iter()
    iter() 是一个内置函数 ,在 Python 中用于获取一个可迭代对象的迭代器。它的参数可以是任何可迭代对象,比如列表、元组、集合、字典等。
    iter() 函数返回指定对象的迭代器。如果对象本身已经实现了 __iter__() 方法,iter() 函数会直接调用该方法来获取迭代器;否则,它会尝试使用其他方式创建一个迭代器 ,例如对于序列类型,返回一个索引逐个遍历元素的迭代器。
    具体过程如下:
    首先,iter() 函数会检查传入的对象是否实现了 iter () 方法。如果该对象有实现 iter () 方法,那么 iter() 函数会调用该方法,将返回的迭代器对象作为结果返回。
    如果对象没有实现 iter () 方法,iter() 函数会尝试查找对象是否实现了 getitem () 方法。如果对象有实现 getitem () 方法,那么 iter() 函数会创建一个简单的索引迭代器,通过索引逐个访问对象的元素。
    如果对象既没有实现 iter () 方法,也没有实现 getitem() 方法,那么 iter() 函数会抛出 TypeError,表示该对象不可迭代。

四、详解*与**,*args,**kargs

*args,**kargs:

前置知识提要:

  1. list 是有序可变 的数据类型,元素在列表中的顺序由其添加的顺序决定。用.append添加。列表一般不会作为参数直接传入。

    dict 是无序可变 的数据类型,元素以键-值对的形式存储。有序的dict称为collections.OrderedDict。直接添加dic["w"] = 2

    tuple是有序不可变的数据类型。

  2. 函数的参数可以分为两种类型:位置参数和关键字参数。位置参数按照定义时的顺序进行传递,并且每个参数的值与传入时的位置一一对应。关键字参数在函数调用时指定了参数的名称,并且可以在任意顺序下传递。

通过上述的数据结构特性,可以得出,作为函数参数时:

  • * 用于收集和传递位置参数,返回类型为tuple(追求有序不可变)
  • ** 用于收集和传递关键字参数,返回类型为dict(追求无序)
python 复制代码
def f(*args, **kargs):
    pass
f(1,2,3, Name='xx', age='yy')
# args = (1,2,3)
# kargs = {'Name': xx, 'age': yy}

* & ** 的其他用法

在函数调用或列表拼接等情况下,* 号可以用于解包列表。

python 复制代码
my_list = [1, 2, 3]
print(*my_list)
# 1 2 3

*my_list 将会把列表 my_list 中的元素解包,作为单独的参数 传递给print()函数。这样,print(*my_list) 就等价于 print(1, 2, 3)

按照上面的思想我们可以完成下面的代码:
children()返回的是iterator,用list()转为转为列表相加。
nn.Sequential接受的参数必须是nn.Module的子类,也就是说你不能把一个列表传给这个类,[nn.ReLU,nn.linear...]
torch.nn.Sequential(*args: Module),且sequential是有顺序要求的,利用解包操作一个个传入。

解包之后原式 = nn.Sequential(nn.ReLU,nn.linear.....)

python 复制代码
combined_seq = nn.Sequential()
snn_model = model
for name, module in snn_model.named_modules():
   if isinstance(module, nn.Sequential):
    combined_seq = nn.Sequential(*(list(combined_seq.children()) + list(module.children())))

序列解包运算,也就是把一段不定长数据转换成list,注意这里不是tuple了,而是List

python 复制代码
a, b, *c = 1,2,3,4
#c:[3,4]

四、

注意缩进。尤其在Python里的缩进。。。

相关推荐
ZZZ_O^O22 分钟前
二分查找算法——寻找旋转排序数组中的最小值&点名
数据结构·c++·学习·算法·二叉树
代码雕刻家1 小时前
数据结构-3.9.栈在递归中的应用
c语言·数据结构·算法
FreakStudio2 小时前
全网最适合入门的面向对象编程教程:56 Python字符串与序列化-正则表达式和re模块应用
python·单片机·嵌入式·面向对象·电子diy
丶21362 小时前
【CUDA】【PyTorch】安装 PyTorch 与 CUDA 11.7 的详细步骤
人工智能·pytorch·python
Kalika0-03 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch3 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j
代码雕刻家3 小时前
课设实验-数据结构-单链表-文教文化用品品牌
c语言·开发语言·数据结构
一个闪现必杀技3 小时前
Python入门--函数
开发语言·python·青少年编程·pycharm
小鹿( ﹡ˆoˆ﹡ )3 小时前
探索IP协议的神秘面纱:Python中的网络通信
python·tcp/ip·php
卷心菜小温4 小时前
【BUG】P-tuningv2微调ChatGLM2-6B时所踩的坑
python·深度学习·语言模型·nlp·bug