2009-01-27 90 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.