0

我今天遇到了一个奇怪的问题,这是一些示例代码

from collections import defaultdict

class Counter:
    hits = 0
    visitors = set()

    def addHit(self, ip):
        self.hits += 1
        self.visitors.add(ip)

d = defaultdict(Counter)
d['a'].addHit('1.1.1')
d['a'].addHit('2.2.2')
d['b'].addHit('3.3.3')

print d['a'].hits, d['a'].visitors
print d['b'].hits, d['b'].visitors

预期结果:

2 set(['1.1.1', '2.2.2'])
1 set(['3.3.3'])

实际结果:

2 set(['1.1.1', '3.3.3', '2.2.2'])
1 set(['1.1.1', '3.3.3', '2.2.2'])

为什么访问者集在我认为应该是 Counter 类的单独实例之间共享数据。每个输入不应该指向一个特定的实例吗?

使这更难理解的是,命中计数器似乎工作正常并且将事物分开。

谁能帮助我了解这里发生了什么或如何解决它?

4

2 回答 2

5

我怀疑您的访问者集是类变量而不是实例变量。

与 defaultdicts 行为无关。

尝试:

class Counter:
    def __init__(self):
        self.hits = 0
        self.visitors = set()

    def addHit(self, ip):
        self.hits += 1
        self.visitors.add(ip)

编辑:与您的问题无关,只是一些如何扩展计数器的想法:

#! /usr/bin/python3.2

class Counter:
    def __init__(self):
        self.__hits = 0
        self.__visitors = {}

    def addHit(self, ip):
        self.__hits += 1
        if ip not in self.__visitors:
            self.__visitors [ip] = 0
        self.__visitors [ip] += 1

    @property
    def hits (self):
        return self.__hits

    @property
    def uniqueHits (self):
        return len (self.__visitors)

    @property
    def ips (self):
        return (ip for ip in self.__visitors)

    def __getitem__ (self, ip):
        return 0 if ip not in self.__visitors else self.__visitors [ip]

c = Counter ()

c.addHit ('1.1.1.1')
c.addHit ('1.1.1.1')
c.addHit ('1.1.1.1')
c.addHit ('1.1.1.1')
c.addHit ('1.1.1.2')
c.addHit ('1.1.1.2')
c.addHit ('1.1.1.3')

print (c.hits)
print (c.uniqueHits)
for ip in c.ips:
    print (ip, c [ip] )
于 2013-02-03T03:07:22.827 回答
2

这与Python 对象的多个实例表现得像同一个实例完全相同的问题

您正在使用类级别变量。将其更改为

class Counter:
    def __init__(self):
        self.hits = 0
        self.visitors = set()

    def addHit(self, ip):
        self.hits += 1
        self.visitors.add(ip)
于 2013-02-03T03:07:33.430 回答