python 缺省字节和元组

vuktfyat  于 2022-12-25  发布在  Python
关注(0)|答案(6)|浏览(131)

我想做以下事情:

d = defaultdict((int,float))
for z in range( lots_and_lots):
  d['operation one'] += (1,5.67)
  ...
  ...
  d['operation two'] += (1,4.56)

然后输出每个操作被调用的次数和浮点值的总和。

for k,v in d.items():
  print k, 'Called', v[0], 'times, total =', v[1]

但我不知道如何实现这一点,因为你不仅不能使用一个元组作为一个参数来默认,你不能添加一个元组到一个元组,并在元组中合计的值,你只是得到额外的值在你的元组。即:

>>> x = (1,0)
>>> x+= (2,3)
>>> x
(1, 0, 2, 3)

而不是

>>> x = (1,0)
>>> x+= (2,3)
>>> x
(3,3)

我怎样才能得到我想要的?

pb3skfrl

pb3skfrl1#

您可以使用 collections.Counter 来累计结果:

>>> from collections import Counter, defaultdict
>>> d = defaultdict(Counter)
>>> d['operation_one'].update(ival=1, fval=5.67)
>>> d['operation_two'].update(ival=1, fval=4.56)
ebdffaop

ebdffaop2#

defaultdict的参数必须是一个返回默认值的“可调用的”。定义你的默认dict如下:

d = defaultdict(lambda: (0, 0.0))

intfloat类型可以被调用并返回零的事实是一种便利,但对defaultdict的工作方式并不重要。
+=工作会引起一些麻烦;元组间的加法是元组的串联,所以你必须走很长的路:

left, right = d["key"]
d["key"] = (left + 2, right + 3)

**编辑:**如果你 * 必须 * 使用+=,你可以这样做,只要你有一个集合类型,它有你想要的操作。fileoffset suggests使用一个numpy数组类型,这可能是一个好主意,但是你可以通过子类化tuple并覆盖你需要的操作符来得到一个近似的结果:下面是其中一个的草图:

class vector(tuple):
    def __add__(self, other):
        return type(self)(l+r for l, r in zip(self, other))
    def __sub__(self, other):
        return type(self)(l-r for l, r in zip(self, other))
    def __radd__(self, other):
        return type(self)(l+r for l, r in zip(self, other))
    def __lsub__(self, other):
        return type(self)(r-l for l, r in zip(self, other))

from collections import defaultdict

d = defaultdict(lambda:vector((0, 0.0)))
for k in range(5):
    for j in range(5):
        d[k] += (j, j+k)

print d

我们不需要(或不想)重载+=运算符本身(拼写为__iadd__),因为tuple是不可变的。如果你提供加法,Python会正确地用新值替换旧值。

atmip9wb

atmip9wb3#

我假设您有太多的操作,以至于不能简单地在每个条目中存储值列表?

d = defaultdict(list)
for z in range(lots_and_lots):
  d['operation one'].append(5.67)
  ...
  ...
  d['operation two'].append(4.56)
for k,v in d.items():
  print k, 'Called', len(v), 'times, total =', sum(v)

您可以做的一件事是创建一个自定义增量器:

class Inc(object):
    def __init__(self):
        self.i = 0
        self.t = 0.0
    def __iadd__(self, f):
        self.i += 1
        self.t += f
        return self

然后

d = defaultdict(Inc)
for z in range(lots_and_lots):
  d['operation one'] += 5.67
  ...
  ...
  d['operation two'] += 4.56
for k,v in d.items():
  print k, 'Called', v.i, 'times, total =', v.t
q1qsirdb

q1qsirdb4#

编写一个可以传递到defaultdict中的类,在传递值时累加这些值:

class Tracker(object):
    def __init__(self):
        self.values = None
        self.count = 0

    def __iadd__(self, newvalues):
        self.count += 1
        if self.values is None:
            self.values = newvalues
        else:
            self.values = [(old + new) for old, new in zip(self.values, newvalues)]
        return self

    def __repr__(self):
        return '<Tracker(%s, %d)>' % (self.values, self.count)

这是对你原始文章中(int, float)的直接替换,改变你的输出循环,打印示例属性如下:

for k,v in d.items():
    print k, 'Called', v.count, 'times, total =', v.values

......你就完了!

5lhxktic

5lhxktic5#

如果你使用numpy数组,你可以得到想要的输出:
链接

hc8w905p

hc8w905p6#

试试这个:

a = (1,0)
b = (2,3)

res = tuple(sum(x) for x in zip(a,b)

例如:

d = defaultdict((int,float))
for z in range( lots_and_lots):
  d['operation one'] = tuple(sum(x) for x in zip(d['operation one'], (1,5.67))
  ...
  ...

相关问题