Заставить пользовательский класс вести себя как набор

Я пытаюсь создать класс, содержащий имена файлов в папке. Но я хочу, чтобы он вел себя как набор. Теперь у меня есть это:

class Files():

    def __init__(self, in_dir):
        self.in_dir = in_dir
        self.files = set(map(os.path.basename, glob.glob(self.in_dir + "/*.txt")))

    def __add__(self, other):
        return self.files + other.files    

    def __or__(self, other):
        return self.files | other.files

    def __and__(self, other):
        return self.files & other.files

    def __xor__(self, other):
        return self.files ^ other.files

Эта работа, и я могу сделать это так:

f1 = Files(inDir1)
f2 = Files(inDir2)

diff_files = f1 ^ f2 % this give files that are in f1 or f2 folder but not in both  folders

Это нормально, но проблема в том, что diff_files не является экземпляром Files. Как изменить мой класс, чтобы он вел себя как в python 3.x?


person user3654650    schedule 09.06.2014    source источник
comment
По какой причине вы не используете set напрямую? Я предполагаю, что есть еще код, который вы не показываете, но в его нынешнем виде я бы взял код, который у вас есть в __init__, и просто сделал его функцией, которая возвращает набор.   -  person Ismail Badawi    schedule 09.06.2014
comment
это небольшой пример. Я хочу, чтобы у файлов были пользовательские функции, такие как удаление файлов в self.files.   -  person user3654650    schedule 09.06.2014


Ответы (2)


Во-первых, сделайте аргумент in_dir необязательным:

def __init__(self, in_dir=None):
    if in_dir:
        self.in_dir = in_dir
        self.files = set(map(os.path.basename, glob.glob(self.in_dir + "/*.txt")))

Затем измените __xor__():

def __xor__(self, other):
    instance = Files()
    instance.files = self.files ^ other.files
    return instance

Кроме того, я не вижу причин сохранять in_dir в качестве переменной экземпляра. Вы можете упростить __init__():

def __init__(self, in_dir=None):
    if in_dir:
        self.files = set(map(os.path.basename, glob.glob(in_dir + "/*.txt")))

В качестве альтернативы вы можете разрешить инициализацию Files, передав набор files:

def __init__(self, in_dir=None, files=None):
    if in_dir:
        self.files = set(map(os.path.basename, glob.glob(in_dir + "/*.txt")))
    if files:
        self.files = files

Тогда метод __xor__() будет еще проще:

def __xor__(self, other):
    return Files(files=self.files ^ other.files)
person alecxe    schedule 09.06.2014
comment
Спасибо. Я также думаю о расширении набора классов, но не знаю, как это сделать. Это лучше, чем сейчас? - person user3654650; 09.06.2014
comment
@user3654650 user3654650 Меня вполне устраивает ваш подход. Но в любом случае взгляните: stackoverflow.com/questions/798442/ и itmaybeahack.com/book/python-2.6/html/p03/p03c04_extending.html. Надеюсь, это поможет. - person alecxe; 09.06.2014

Я не уверен, что понимаю, что вы подразумеваете под «ведет себя как набор», но я понимаю, что вы хотите вернуть экземпляр Files, а не только «diff», поэтому для этого:

сдача:

def __xor__(self, other):
        return self.files ^ other.files

to:

def __xor__(self, other):
        result = Files()
        result.in_dir = self.in_dir
        result.files = self.files ^ other.files
        return result
person Nir Alfasi    schedule 09.06.2014