2009-01-27 91 views
0

我有一個名爲HashedDir的模塊(實際上是一個.py文件)。我的課堂如何表現得像一個靜態課程?

當我導入該類的文件和instanciate 2實例時,當我檢查對象的字段時,它們始終是相同的,即使這兩個對象應該不同。

如:

h1 = HashedDir('/path/to/dir') 
print h1.getList()['files'] # /path/to/dir 
h2 = HashedDir('some/other/path') 
print h1.getList()['files'] # some/other/path 
print h2.getList()['files'] # some/other/path 

任何想法?

這是類:

from os import walk 
from os import path 
from hashlib import md5 
import re 

class HashedDir: 
    """ 
    A list of files with associated md5 hashes generated retrieving thou 
    a recursive walk in the directory tree starting from a provided root 
    directory. Also stores the dirs in each dir 
    """ 

    # {'files': [ 
    # ('/path/to/file1', '52bc309e11259af15e4623c7a0abc28c'), 
    # ('/path/to/file2', '52bc309e11259af15e4623c7a0abc28c'), 
    # ('/path/to/dir/file3', '52bc309e11259af15e4623c7a0abc28c') 
    # ], 
    # 'dirs': ['/path/to/dir1', '/path/to/dir2'] 
    # } 
    fileList = {'files': [], 'dirs': []} 
    ignoreList = [] 

    def __init__(self, rootDir, ignoreList=[]): 
     """ 
     ignoreList is a list of regular expressions. If a file or a dir matches 
     that regular expression, don't count it 
     """ 
     self.ignoreList = ignoreList 

     for dirpath, dirnames, filenames in walk(rootDir): 
      for fileName in filenames: 
       completeName = path.join(dirpath,fileName) 
       hash = md5(open(completeName).read()).hexdigest() 
       relativePath = self._relativePath(completeName, rootDir) 
       if not self._toBeIgnored(relativePath): 
        self.fileList['files'].append((relativePath, hash)) 
      for dirName in dirnames: 
       completeName = path.join(dirpath, dirName) 
       relativePath = self._relativePath(completeName, rootDir) 
       if not self._toBeIgnored(relativePath): 
        self.fileList['dirs'].append(relativePath) 

    def _relativePath(self, path, base): 
     return path.replace(base, '') 

    def _toBeIgnored(self, path): 
     for regex in self.ignoreList: 
      if re.compile(regex).search(path) != None: 
       return True 
     return False 

    def getList(self): 
     return self.fileList 

在此先感謝

+0

你shoul d發佈該課程的代碼。 – Corey 2009-01-27 11:43:07

+0

你的代碼沒有寫作的意義。你已經導入/重命名os.walk,os.path,md5.md5並沒有提到。一旦糾正,我們發現HashedDir的實例不具有* .value attirbute(從上面的代碼可以看出)。 – bendin 2009-01-27 12:18:11

+0

>>> a = HashedDir(「/ home/smithma/tmp」);打印a.value中 回溯(最近通話最後一個): 文件「」,1號線,在 AttributeError的:HashedDir實例沒有屬性「值」 – bendin 2009-01-27 12:18:58

回答

10

一類中有兩種變量:

  • 類變量,在類級定義,並且通用於所有實例

  • 實例變量,一個類的方法(通常爲__init__)中定義和由實例(通常self.)合格。

class SomeClass(object): 
    classVariable = 0 
    def __init__(self): 
     self.instanceVariable= 0 

命名classVariable該變量是類的一部分,共同爲所有實例。由於Python搜索的方式,它可以作爲self.classVariable以及SomeClass.classVariable的成員提供。

名爲instanceVariable的變量是實例的一部分(self.),並且對於每個實例都是唯一的。

注意。還有第三種,全球的,但這不是你問的。

6

難道文件清單:你在說什麼?你有它作爲一個類變量,使其成爲一個實例變量,你需要做的:

self.fileList = {'files': [], 'dirs': []} 

在你__ init __函數。

1

如果您在類的主體內聲明您的變量超出類方法,它們將變爲「類變量」並對所有類實例通用。要獲取實例變量,請在init函數內聲明它們,並將它們綁定到當前實例的處理程序「self」。

0

如果您可以發佈完整工作(或失敗!)示例,這可能會很有用。

如果我做我認爲是必要的(即,在級HashedDir(對象)包裹這樣的:並設置self.fileList = { '文件':[], '顯示目錄':[]}內初始化然後它似乎工作

你指的是self.value的哪些項目?根據sykora的上一篇文章,您需要區分針對每個實例運行的代碼(在init中)和代碼

2

class塊中聲明的事物是類屬性,類屬性也可以通過實例訪問。 (實際上,這個原則就是如何綁定方法。)不僅如此,而且函數的默認參數僅在函數定義時才被評估。因此,給予說明這兩個點的例子:

class C(object): 
    list_a = [] 
    def __init__(self, list_b=[]): 
     self.list_b = list_b 

    def __str__(self): 
     return '%r %r' % (self.list_a, self.list_b) 

c1 = C() 
c2 = C() 
c2.list_a = [] 
c3 = C([]) 

c1.list_a.append(1) 
c1.list_b.append(2) 
print c1 
print c2 
print c3 

這個輸出是:

[1] [2] 
[] [2] 
[1] [] 

C1和C3共享相同的list_a因爲它是一個類屬性;它不會被c2中的實例屬性遮蔽。 c1和c2共享相同的list_b,因爲__init__中只有一個list_b默認值;每次調用該函數時都不會創建新的列表,而是傳遞您自己的新列表。

1

正如其他人指出的,你的問題是fileList是一個你變異的類變量。

但是它值得一提的代碼中的另一個潛在的缺陷,可能導致類似的問題(儘管它在你的具體的例子不一樣):

def __init__(self, rootDir, ignoreList=[]): 

謹防傳遞可變參數(如該名單)作爲默認參數。這個列表只會創建一次(當你定義__init__函數時,這意味着使用默認構造的類的所有實例將使用相同的列表)

在你的例子中,列表永遠不會被修改,所以這不會有任何影響,但是如果(如你對fileList所做的)追加到self.ignoreList,那麼這將影響所有這些實例,導致類似的問題到您看到的那個。這是一個非常常見的初學者疑難雜症 - 爲了避免這種情況,最好編寫如下代碼:

def __init__(self, rootDir, ignoreList=None): 
    if ignoreList is None: 
     ignoreList = [] # This will create a new empty list for every instance.