面向对象编程中创建列表和过滤不同结果的好方法是什么?

0 投票
4 回答
733 浏览
提问于 2025-04-18 11:01

我有一个方法可以创建一个目录下文件的列表,但我还有多个其他方法也能做到这一点,并且在循环中会进行一些额外的过滤。

我觉得这样做看起来很糟糕,我很想知道有没有更优雅的解决办法。

下面是我正在做的一个简单示例:

class foo(object):

    def read_files_in_dir(...)
        ....

    def filter_x(...):
        for file in read_files_in_dir(...):
            if file.startswith("x"):
                yield file

    def filter_y(....):
        for file in read_files_in_dir(...):
            if file.startswith("y"):
                yield file

    ...

我不想把所有的filter函数的结果合并在一起,因为每个结果的意义不同,因为我在读取不同的目录,而这些目录需要不同的过滤方式。

有没有办法可以有一个中心函数来处理循环,同时又能提供不同的过滤选项,而不需要把参数搞得复杂得不可思议?

// 编辑

现在我这样做:

class Something(object):

    @staticmethod
    def read_files_in_dir(self, directory, filter_func=lambda _: return True):
        for file in directory:
            if filter_func(file):
                yield file

    class Filters(object):

        @staticmethod
        def filter1(file):
            return True if *some_condition* else False

然后我运行类似这样的代码:

filtered = Something.read_files_in_dir(*directory*, Something.Filters.filter1)

有没有什么改进的建议?

4 个回答

0

Dologan的回答很好。 他的意思是把过滤器的值当作参数传给过滤函数。 不过,为了让过滤器更强大,我会使用一个过滤字典。 在这个字典里,你可以指定搜索的类型和对应的值: 比如说: filterList = {'start':'y',.....)

如果你想更高级一点,可以把过滤函数放在一个列表里,然后把字符串作为参数传进去。 比如说:

filename = 'try_me.py'
filterString = 't'
filterListA = [str.startswith]
filterListB = [str.endswith, str.startswith]
filterListC = [str.find]

def my filter(filterList, filterString):
       for filterFunc in filterList:
          print filterFunc(filename,filterString)
1

在构建一个过滤系统时,通常的思路是先创建一个数据集合,然后把这个集合里的每个项目都通过一系列的过滤函数来处理。每个过滤函数会接收一个项目,并返回一个布尔值(也就是“真”或“假”)。只有当所有的过滤器都返回“真”的时候,这个项目才会被保留下来。

下面是一个简单的例子,采用了函数式编程的风格。如果需要的话,也可以很容易地转换成面向对象的方式来使用:

def main():
    universe = read_files_in_dir()
    filters = [is_odd, larger_than_ten]

    for item in universe:
        if all(f(item) for f in filters):
            print item

def read_files_in_dir():
    return list(range(20))

def is_odd(item):
    return bool(item % 2)

def larger_than_ten(item):
    return item > 10

main()
1

在编程中,有时候我们会遇到一些问题,尤其是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,尤其是当我们刚开始学习编程的时候。比如,有人可能会在使用某个特定的功能时,发现它没有按照预期工作。这种情况很常见,尤其是当我们对这个工具还不够熟悉的时候。

在这种情况下,查看网上的讨论,比如StackOverflow上的帖子,通常能找到一些解决方案或者其他人的经验分享。很多时候,其他开发者会遇到类似的问题,他们会在网上寻求帮助,或者分享他们的解决办法。这些讨论可以帮助我们更好地理解问题的根源,以及如何解决它。

总之,遇到问题时,不要气馁,网上有很多资源和社区可以帮助你。记得多多查阅相关的讨论和解决方案,这样你会逐渐掌握更多的知识和技能。

predicates = [
  lambda x: x % 3 == 0,
  lambda x: x % 5 == 0
]

items = range(0, 100)

filtered = [
  item for item in items if
    all(predicate(item) for predicate in predicates)
  ]

print(filtered)
2

你的例子可能有点过于简单,不过下面的代码应该能做到和你的差不多的效果:

def read_files_in_dir(...)
   ...

def filter(self, param, ...):
    return (file for file in read_files_in_dir(...) if file.startswith(param)) 

如果你的过滤条件比一个测试能处理的要复杂,你可以创建更多的方法或函数,把文件实例传给它们,然后根据你需要的标准返回真或假。

撰写回答