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]为键。注意:键需要初始化。键在使用之前一定要初始化,一层一层的初始化:

`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()函数逐个获取。

my_iterator = iter([1, 2, 3])
for element in my_iterator:
    print(element)
 # 1, 2,3
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__()

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(追求无序)
def f(*args, **kargs):
    pass
f(1,2,3, Name='xx', age='yy')
# args = (1,2,3)
# kargs = {'Name': xx, 'age': yy}

* & ** 的其他用法

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

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.....)

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

a, b, *c = 1,2,3,4
#c:[3,4]

四、

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

你可能感兴趣的:(数据结构,python,list)