【问题标题】:Chaining output between diffrent functions在不同功能之间链接输出
【发布时间】:2019-10-20 14:02:52
【问题描述】:

我正在寻找一个过程的名称,该过程在其他几个函数中处理一个函数的输出(试图为我的问题找到更好的词)。一些伪/实际代码将非常有帮助。

我写了以下代码:

def read_data():
    read data from a file
    create df
    return df

def parse_data():
    sorted_df = read_data()
    count lines
    sort by date
    return sorted_df

def add_new_column(): 
    new_column_df = parse_data()
    add new column
    return new_column_df

def create_plot():
    plot_data = add_new_column()
    create a plot
    display chart

我想了解的是如何跳过一个函数,例如创建以下链read_data() -> parse_data() -> create_plot()

由于代码现在看起来(由于所有返回值以及它们在函数之间传递的方式),它需要我更改最后一个函数中的输入数据,create_plot()

我怀疑我正在创建逻辑错误的代码。

有什么想法吗?

原码:

import pandas as pd
import matplotlib.pyplot as plt

# Read csv files in to data frame
def read_data():
    raw_data = pd.read_csv('C:/testdata.csv', sep=',', engine='python', encoding='utf-8-sig').replace({'{':'', '}':'', '"':'', ',':' '}, regex=True)
    return raw_data

def parse_data(parsed_data):
    ...
    # Convert CreationDate column into datetime
    raw_data['CreationDate'] = pd.to_datetime(raw_data['CreationDate'], format='%Y-%m-%d %H:%M:%S', errors='coerce')
    raw_data.sort_values(by=['CreationDate'], inplace=True, ascending=True)
    parsed_data = raw_data
    return parsed_data

raw_data = read_files()
parsed = parsed_data(raw_data)

【问题讨论】:

标签: python


【解决方案1】:

传递数据而不是有效地“嵌套”所有内容。理想情况下,函数需要的任何数据都应作为参数传递给函数:

def read_data():
    read data from a file
    create df
    return df

def parse_data(sorted_df):
    count lines
    sort by date
    return sorted_df

def add_new_column(new_column_df):
    add new column
    return new_column_df

def create_plot(plot_data):  
    create a plot
    display chart

df = read_data()
parsed = parse_data(df)
added = add_new_column(parsed)
create_plot(added)

尽量确保函数只处理它们直接负责的事情。知道数据来自哪里或生成数据不是parse_data 的工作,所以它不应该担心这一点。让调用者处理。

我在这里设置事物的方式通常被称为“管道”或“线程”。信息从一个功能“流动”到下一个功能。在像 Clojure 这样的语言中,这可以写成:

(-> (read-data)
    (parse-data)
    (add-new-column)
    (create-plot))

使用线程宏-> 让您无需手动处理数据传递。不幸的是,Python 没有内置任何东西来执行此操作,尽管可以使用external modules 来实现。


另请注意,由于数据帧似乎是可变的,因此您实际上并不需要从函数中返回已更改的数据帧。如果您只是直接改变参数,您可以按顺序将相同的数据帧传递给每个函数,而不是将其放在像parsedadded 这样的中间变量中。我在这里展示的方式是一种通用的设置方式,但可以根据您的具体用例进行更改。

【讨论】:

  • 我正在尝试重做代码,但遇到了local variable sorted_df referenced before before assignment 的一些问题。我将您的答案标记为解决方案,我想我现在太累了。
  • @ToreDjerberg 我需要查看导致该错误的代码才能帮助解决这个问题。
  • 我认为问题出在parse_data 函数中。解析数据时,我使用以下代码 sn-p(伪):def parse_data(): df['Column1'] = df['Column1'].convert_to_date。执行时,df 在赋值前被标记为引用。
  • @ToreDjerberg 请注意,我表明需要使用参数传入数据。再次查看我的 parse_data 函数并注意我是如何调用它的。
  • @ToreDjerberg 只是一个错字。您创建了一个名为data (data = read_files()) 的变量,但随后您尝试将其称为raw_data (parse_data(raw_data))。只需使用data:parse_data(data)
【解决方案2】:

使用类来包含您的代码

class DataManipulation:
    def __init__(self, path):
        self.df = pd.DataFrame()
        self.read_data(path)

    @staticmethod
    def new(file_path):
        return DataManipulation(path)

    def read_data(self, path):
        read data from a file
        self.df = create df

    def parse_data(self):
        use self.df
        count lines
        sort by date
        return self

    def add_new_column(self):
        use self.df
        add new column
        return self

    def create_plot(self):
        plot_data = add_new_column()
        create a plot
        display chart
        return self

然后,

 d = DataManipulation.new(filepath).parse_data().add_column().create_plot()

【讨论】:

  • 为什么是.new?只是DataManipulation(filepath) 会做同样的事情。使用必须按特定顺序调用其方法的类并不是一个好主意。如果不调用parse_data,其余方法将不会执行任何操作。一直明确返回self 是……值得怀疑的。如果你想要一个流畅的界面,没关系,但这似乎不是一个流畅的界面的好用例。
  • python中有不同的设计模式。其中之一是非常流行的构建器模式。这个答案的灵感来自该模式。在实际模式中,当您执行 new() 时,该函数会返回一个隐藏属性并添加功能的构建器对象。类本身没有指定任何顺序。它具有返回self 以实现链接的函数。如果您需要示例pandas itself uses it。 @deceze @Tore Djerberg
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 2012-01-15
相关资源
最近更新 更多