在下面的示例中,我无法为类__delitem__
定义Container
或类似方法。我该如何纠正?谢谢。
import numpy as np
import pandas as pd
class XLData(object):
def __init__(self, name):
self.name = name
self.data = pd.DataFrame({self.name: list("ASDF" * 2),
'x': np.random.randint(1, 100, 8) })
def __repr__(self):
return repr(self.data.head(2))
class Container(object):
def __init__(self):
self.counter = 0
self.items = []
def append(self, item):
self.counter += 1
self.items = self.items + [item]
def __delitem__(self, name):
for c in self.items:
print("element name:{}, to delete:{}".format(c.name, name))
if c.name == name:
pass #!
#del c
def __iter__(self):
for c in self.items:
yield c
a = XLData('a')
b = XLData('b')
c = XLData('c')
dl = Container()
dl.append(a)
dl.append(b)
dl.append(c)
del dl['b']
for c in dl:
print(c)
# 'b' is still in ..
答案 0 :(得分:2)
最好不要在循环本身中修改要循环的数组。因此,只需选择项目的索引并将其删除即可。
class Container(object):
def __init__(self):
self.counter = 0
self.items = {} # create a dict!
def append(self, item):
self.counter += 1
self.items[item.name] = item # add items to it, keyed under their names
def __delitem__(self, name):
del self.items[name] # this becomes *really* simple, and efficient
def __iter__(self):
for c in self.items.values: # loop over the dict's values to the items
yield c #
答案 1 :(得分:1)
您似乎已经知道,鉴于代码的注释,您无法在循环中执行del c
,因为这只会暂时从函数的本地名称空间中删除c
变量,而不会完全不更改列表结构。
有几种方法可以使它起作用。
一个想法是在循环列表中的值时使用enumerate
,这样当您需要从列表中删除项目时,手头就有索引:
for i, item in enumerate(self.items):
if item.name == name:
del self.items[i]
return
请注意,删除项目后我立即从函数返回。如果列表中可能同时存在多个具有相同名称的项目,则可能不是您想要的,但是此代码无法正确处理这种情况,因为一旦从列表中删除项目,迭代将无法正常进行(它可以让您继续迭代,但是会跳过一个值)。
一个更好的选择可能是使用列表理解来重建列表,使其仅包含要保留的值。
self.items = [item for item in self.items if item.name != name]
这很简洁,无论您要删除多少个名称,它都可以使用!
以上两种方法共有的一个缺点是,对于大型列表而言,它们的运行速度相当慢。他们需要遍历所有项目,他们无法提前告知要删除的项目存储在何处。一种替代方法是使用词典而不是列表来存储项目。如果您将商品名称用作键,则可以非常高效地查找它们。
这是一个实现的方法,尽管它只允许一个项目具有任何给定的名称(添加另一个将替换第一个):
class Container(object):
def __init__(self):
self.counter = 0
self.items = {} # create a dict!
def append(self, item):
self.counter += 1
self.items[item.name] = item # add items to it, keyed under their names
def __delitem__(self, name):
del self.items[name] # this becomes *really* simple, and efficient
def __iter__(self):
for c in self.items.values(): # loop over the dict's values to the items
yield c
答案 2 :(得分:1)
您实现它的方式,对于del
之类的操作来说将会很慢。并且,如果您想添加其他通过名称返回对象的方法,例如__getitem__()
,则通过遍历列表进行查找会很慢。您可能希望使用字典将XLData
对象保存在Container
内部。而且,由于Python的数据对象都具有length属性,因此您无需保留它们的数量。
class Container(object): # Python 3 doesn't require 'object' in class decls.
def __init__(self):
self._items = {}
def add(self, item):
# self._items.append(item) # Why create a new list each time.
# Just append.
self._items[item.name] = item
def __len__(self):
return len(self._items)
def __getitem__(self, name):
return self._items[name]
def __delitem__(self, name):
del self._items[name] # Simple.
def __iter__(self):
for c in self._items.values():
yield c
使用dict
可以同时获得列表和字典的好处:通过名称快速访问以及对项进行迭代等等。dict
跟踪键和键的顺序。项目已添加。如果确实需要单独的列表来进行排序和迭代,则可能有不止一种数据类型可以保存所包含对象的信息。您只需要同步dict
和list
。
想一想,如果您希望自己的班级支持sort()
操作,甚至只需要一点点创造力,甚至可以对没有列表的字典进行排序。
def sort(self, key=None):
self._items = {k: v for k, v in sorted(self._items.items(), key=key)}
我想我现在太过分了=)
答案 3 :(得分:1)
最好不要在循环本身中修改要循环的数组。因此,只需选择项目的索引并将其删除即可。
def __delitem__(self, name):
idx = -1
found = False
for c in self.items:
idx += 1
print("element name:{}, to delete:{}".format(c.name, name))
if c.name == name:
found = True
break
if found:
del self.items[idx]
答案 4 :(得分:1)
替代方法,将列表过滤器选项与def delitem 方法中的对象attr条件一起使用
import numpy as np
import pandas as pd
class XLData(object):
def __init__(self, name):
self.name = name
self.data = pd.DataFrame({self.name: list("ASDF" * 2),
'x': np.random.randint(1, 100, 8)})
def __repr__(self):
return repr(self.data.head(2))
class Container(object):
def __init__(self):
self.counter = 0
self.items = []
def append(self, item):
self.counter += 1
self.items = self.items + [item]
def __delitem__(self, name):
self.items = [x for x in self.items if x.name != name]
def __iter__(self):
for c in self.items:
yield c
a = XLData('a')
b = XLData('b')
c = XLData('c')
dl = Container()
dl.append(a)
dl.append(b)
dl.append(c)
del dl['b']
for c in dl:
print(c)
输出
a x
0 A 13
1 S 97
c x
0 A 91
1 S 17