使用Generator代替list.append

时间:2018-01-23 10:22:35

标签: python

我正在编写一段具有多个函数的代码,每个函数都将某些代码行附加到列表中,并且在代码的末尾迭代列表中的所有行并将其作为字符串连接然后打印它。

我对发电机的理解和使用感到相当舒服,但我不确定是否可以使用发电机实现这样的事情,这样我就不必用不断增长的清单来记忆。

以下是代码如何显示的示例

def get_huge_pages():
    """
    This function reports the total number of huge pages and the number of used huge pages
    """
    huge_pages = dict()
    files = (f for f in glob.iglob("/sys/devices/system/node/node*/hugepages/*/*") if "nr_" in f or "free_" in f)

    for FILE in files:
        fields = FILE.split('/')
        p_size = '1G' if int(re.sub('[-a-zA-Z]', '', fields[-2])) / 1024 == 1024 else '2M' if int(
            re.sub('[-a-zA-Z]', '', fields[-2])) / 1024 == 2.0 else str(
            int(re.sub('[-a-zA-Z]', '', fields[-2])) / 1024) + ' kB'

        key = fields[-4] + '.' + p_size + '.' + fields[-1]

        with open(FILE) as IF:
            huge_pages[key] = IF.read().strip()

    return huge_pages


def get_non_root_rt_processes():
    """
    Below function reports Real time process run by non-root users
    ps -eLo user,pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,comm|awk '$1 != "root" && $4 != "-" {print $0}'
    :return: dictionary with psr number as key and total processes on that core as value
    """
    ps = ['ps', '-eLo', 'user,pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,comm']
    awk = ['awk', '$1 != "root" && $4 != "-" {print $8}']
    total_processes = subprocess.Popen(ps, stdout=subprocess.PIPE)
    non_root_processes = subprocess.Popen(awk, stdin=total_processes.stdout, stdout=subprocess.PIPE)
    total_processes.stdout.close()
    procs_per_core = defaultdict(int)
    # remove the first header line from the output
    for line in non_root_processes.stdout:
        break

    for line in non_root_processes.stdout:
        procs_per_core[line.strip()] += 1
    non_root_processes.stdout.close()
    return procs_per_core

lines = []
huge_pages = get_huge_pages()
procs_per_core = get_non_root_rt_processes()

for key in sorted(huge_pages, reverse=True):
    lines.append('server.%s.%s.%s : %s' % (domain, node, key, huge_pages[key]))

for core in range(cpu_count()):
    lines.append('Non-root processes on Core %s : %s' % (core, procs_per_core.get(str(core), 0)))

message = '\n'.join(lines) + '\n'
print(message)

1 个答案:

答案 0 :(得分:0)

如果每个函数只将一个项目附加到列表中,则只能return该项目。然后在生成器表达式中调用函数并加入结果。

def func1():
    return 'some text'
def func2():
    return 'more text'
def func3():
    return 'even more text'

msg = '\n'.join(f() for f in (func1, func2, func3))
print(msg)

如果每个函数附加多个项目,则可以在整个函数中使用yield(或者只在结尾处的return项目列表中),并再次将结果连接到(嵌套)生成器表达式中

def func1():
    yield 'some'
    yield 'text'
def func2():
    yield 'more'
    yield 'text'
def func3():
    yield 'even'
    yield 'more'
    yield 'text'

msg = '\n'.join(x for f in (func1, func2, func3) for x in f())
print(msg)

此外,如果您只想打印一次该字符串,则根本不需要join它。相反,您可以在循环中使用print(*..., sep="\n")(或仅print):

print(*(x for f in (func1, func2, func3) for x in f()), sep="\n")