Path 使用装饰器在Python中行走路径

Path 使用装饰器在Python中行走路径,path,decorator,python,Path,Decorator,Python,我很好奇decorators是如何工作的,所以我想看看它是否适合在路径中放置泛型函数。我想返回路径下以空格分隔的文件中最长的整数段(然后返回这个值或可能打印它)。这可能吗 我试图把东西倒回去,但没有成功。然后我很好奇,如果我把它放在函数外,它将如何工作。装饰师是否仅用于打印,或者您能否从他们那里返回以使此示例正常运行 def walkPath(fn): def wrapper(*args, **kwargs): outside = None for dir

我很好奇decorators是如何工作的,所以我想看看它是否适合在路径中放置泛型函数。我想返回路径下以空格分隔的文件中最长的整数段(然后返回这个值或可能打印它)。这可能吗

我试图把东西倒回去,但没有成功。然后我很好奇,如果我把它放在函数外,它将如何工作。装饰师是否仅用于打印,或者您能否从他们那里返回以使此示例正常运行

def walkPath(fn):
    def wrapper(*args, **kwargs):
        outside = None
        for dirname, dirnames, filenames in os.walk(args[0]):
            for filename in filenames:
                fn(filename, dirname, outside, *args, **kwargs)
    return wrapper

@walkPath
def countL(filename, dirname, outside, path, extension = '.wrd'):
    if (filename[-4:]  == extension):
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            if (int(temp[1]) - int(temp[0]) > longest):                
                outside = int(temp[1]) - int(temp[0])
这解释了我在没有decorator的情况下所做的事情,然后只是看看是否可以获得相同的功能,但使其通用。这意味着它不一定是一组文件中最长的单词,但可能是一组文件名中带有“s”的文件。只是不知道如何正确处理外部变量,或者是否可以使用装饰器

def countLength(path, extension = '.wrd'):
    longest = 0
    for dirname, dirnames, filenames in os.walk(path):
        for filename in filenames:
            if (filename[-4:]  == extension):
                with open(os.path.join(dirname, filename), 'r') as input:
                    data = input.readlines()
                for i in range(len(data)):
                    temp = data[i].split()
                    if (int(temp[1]) - int(temp[0]) > longest):
                        longest = int(temp[1]) - int(temp[0])
    return longest

您的问题是,您正试图拆分为外部循环及其主体,但在循环中有一个局部变量(
longest
)来比较数字。因此,您需要做的是使您的内部函数聚合结果。这意味着walkPath循环需要保存每次调用
fn
的结果,并将其交给下一次调用,以便您可以在
fn
中进行比较。最后,它应该吐出最后一次呼叫返回的内容。我想这就是你试图用
外部
所做的。我还从
countL
中删除了
path
参数,因为它没有做任何事情。您的示例应如下所示:

def walkPath(fn):
    def wrapper(outside, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(args[0]):
            for filename in filenames:
                outside = fn(outside, filename, dirname, *args, **kwargs)
        return outside
    return wrapper

@walkPath
def countL(outside, filename, dirname, extension = '.wrd'):
    if (filename[-4:]  == extension):
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            if (int(temp[1]) - int(temp[0]) > outside):                
                outside = int(temp[1]) - int(temp[0])
    return outside

然后必须调用类似于
countL(0)
的函数

您的问题是,您正试图拆分为外部循环及其主体,但在循环中有一个局部变量(
longest
)来比较数字。因此,您需要做的是使您的内部函数聚合结果。这意味着walkPath循环需要保存每次调用
fn
的结果,并将其交给下一次调用,以便您可以在
fn
中进行比较。最后,它应该吐出最后一次呼叫返回的内容。我想这就是你试图用
外部
所做的。我还从
countL
中删除了
path
参数,因为它没有做任何事情。您的示例应如下所示:

def walkPath(fn):
    def wrapper(outside, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(args[0]):
            for filename in filenames:
                outside = fn(outside, filename, dirname, *args, **kwargs)
        return outside
    return wrapper

@walkPath
def countL(outside, filename, dirname, extension = '.wrd'):
    if (filename[-4:]  == extension):
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            if (int(temp[1]) - int(temp[0]) > outside):                
                outside = int(temp[1]) - int(temp[0])
    return outside

然后必须调用类似于
countL(0)
的函数

您必须决定要聚合到哪里以及如何返回数据。我会这样做:

def walkPath(fn):
    def wrapper(walkroot, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(walkroot):
            for filename in filenames:
                res = fn(filename, dirname, *args, **kwargs)
                if res is not None: yield res
    return wrapper

@walkPath
def countL(filename, dirname, extension='.wrd'):
    if os.path.splitext(filename)[1] == extension:
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            return int(temp[1]) - int(temp[0])
现在,
walkPath()
的调用者获得一个生成器,该生成器从每个文件中生成一个“增量值”。因此,您可以使用
max(步行路径(…)

此外,我将扩展比较改为

if os.path.splitext(filename)[1] == extension:
如果您在某处导入操作系统


停下来。重新阅读代码后,我必须问:

一个文件中是否可能有多个值对?如果是这样,我们必须使
countL()
返回一个生成器

@walkPath
def countL(filename, dirname, extension='.wrd'):
    if os.path.splitext(filename)[1] == extension:
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            yield int(temp[1]) - int(temp[0])
现在,修饰后的
countL()
返回一个生成器,该生成器生成生成器,因此我们必须执行以下操作

max(value for filegen in countL(...) for value in filegen)
或者,我们可以将
walkPath()
更改为

def walkPath(fn):
    def wrapper(walkroot, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(walkroot):
            for filename in filenames:
                for item in fn(filename, dirname, *args, **kwargs):
                    yield item
    return wrapper
因此,它将生成对
fn()
的每次调用的项目。这还不够

max(countL(...))

再次说明。

您必须决定要聚合到哪里以及如何返回数据。我会这样做:

def walkPath(fn):
    def wrapper(walkroot, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(walkroot):
            for filename in filenames:
                res = fn(filename, dirname, *args, **kwargs)
                if res is not None: yield res
    return wrapper

@walkPath
def countL(filename, dirname, extension='.wrd'):
    if os.path.splitext(filename)[1] == extension:
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            return int(temp[1]) - int(temp[0])
现在,
walkPath()
的调用者获得一个生成器,该生成器从每个文件中生成一个“增量值”。因此,您可以使用
max(步行路径(…)

此外,我将扩展比较改为

if os.path.splitext(filename)[1] == extension:
如果您在某处导入操作系统


停下来。重新阅读代码后,我必须问:

一个文件中是否可能有多个值对?如果是这样,我们必须使
countL()
返回一个生成器

@walkPath
def countL(filename, dirname, extension='.wrd'):
    if os.path.splitext(filename)[1] == extension:
        with open(os.path.join(dirname, filename), 'r') as input:
            data = input.readlines()
        for i in range(len(data)):
            temp = data[i].split()
            yield int(temp[1]) - int(temp[0])
现在,修饰后的
countL()
返回一个生成器,该生成器生成生成器,因此我们必须执行以下操作

max(value for filegen in countL(...) for value in filegen)
或者,我们可以将
walkPath()
更改为

def walkPath(fn):
    def wrapper(walkroot, *args, **kwargs):
        for dirname, dirnames, filenames in os.walk(walkroot):
            for filename in filenames:
                for item in fn(filename, dirname, *args, **kwargs):
                    yield item
    return wrapper
因此,它将生成对
fn()
的每次调用的项目。这还不够

max(countL(...))

再次说明。

但是您实际上没有在
包装中返回任何内容
…您也没有在
countL
中返回任何内容…我试图提供一个有用的示例,但我无法从这个问题中看出您真正想要什么。我想你应该给出一两个目录结构的例子,其中的文件,以及你想要生成的输出。但是你实际上没有在
wrapper
中返回任何东西……你也没有在
countL
中返回任何东西……我试图提供一个有用的例子,但我无法从这个问题中看出你真正想要什么。我想你应该给出一个或两个目录结构的例子,其中的文件,以及你想要生成的输出。我想这就是我想要的。我必须稍后再尝试一下,让你知道。基本上,生成器可以返回任何东西,例如一个类,然后从外部处理您特别想要的东西,比如在本例中的max。@J Spen。基本上,decorator将返回值的函数转换为生成器,生成在遍历过程中找到的每个文件的值。无论我如何尝试,我都无法让它像这样正常工作。生成器只能调用next()一次。我做了一些更改:a)使参数传递更干净,b)使用
splitext()
和c)抑制
None
返回值,这些值来自
countL()
中不存在的
else
if
部分的
if
。我已经创建了2个文件,它现在对我来说很有用…如果一个文件可以包含多个值对,我已经添加了一个替代实现(好的,实际上是2)。我想这就是我想要的。我必须稍后再尝试一下,让你知道