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 に答える