Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python,用于迭代文件或其他行生成器的函数_Python_Csv_Generator - Fatal编程技术网

Python,用于迭代文件或其他行生成器的函数

Python,用于迭代文件或其他行生成器的函数,python,csv,generator,Python,Csv,Generator,我有许多函数需要CSV文件的路径,或者可以转换为CSV行生成器的源,例如标准输入或列表(用于执行测试) 我编写了这个函数: def进程\文档\行(行\源): 如果isinstance(行/源,str): #使用csv读取器打开文件 将open(rows\u source)作为csvf: 流程\单据\行的收益率(csvf) 返回 elif isinstance(行/源,io.TextIOBase): #这包括stdin rows\u source=csv.reader(rows\u source,

我有许多函数需要CSV文件的路径,或者可以转换为CSV行生成器的源,例如标准输入或列表(用于执行测试)

我编写了这个函数:

def进程\文档\行(行\源):
如果isinstance(行/源,str):
#使用csv读取器打开文件
将open(rows\u source)作为csvf:
流程\单据\行的收益率(csvf)
返回
elif isinstance(行/源,io.TextIOBase):
#这包括stdin
rows\u source=csv.reader(rows\u source,分隔符=“\t”)
源行的产量
我可以这样调用:

def进程行(行/src):
l=0;res=“”;
对于流程中的行\u文档\u行(行\u src):
打印(“L:%d,姓名:%s,姓氏:%s”%(L,第[0]行,第[1]行)
l+=1
处理行(“/path/to/file.tsv”)
过程行([“约翰”、“史密斯”]、[“卡尔”、“马克思”]、[“伊曼纽尔”、“康德”])
进程行(sys.stdin)
现在,我的问题是:我是在重新发明轮子吗?是否有任何实用程序可以实现同样的功能,并且我不必重写

编辑 多亏了。旧版本是:

def进程\文档\行(行\源):
如果(类型(行\源)为str):
#使用csv读取器打开文件
将open(rows\u source)作为csvf:
对于流程中的行\文档\行(csvf):
产量行
返回
elif isinstance(行\源,io.TextIOWrapper):
#这包括stdin
rows\u source=csv.reader(rows\u source,分隔符=“\t”)
elif isinstance(行\源,Iterable)或isinstance(行\源,迭代器):
行\源=(e表示行\源中的e)
elif isinstance(行\源,类型.GeneratorType):
raise TypeError(“此函数需要一个文件或类似CSV的生成器”)
#我们必须这样做,以避免回报和收益的混合
对于行中的行\u源:
产量行
是否有任何实用程序可以实现同样的功能,并且我不必重写

事实并非如此,API通常试图比“文件名、文件对象或迭代器”定义得更多,尽管我希望那些以这种方式工作的API也能处理它

但是,您的系统过于复杂(而且是错误的):iterable、迭代器和生成器都是iterable,您可以将它们留给最终的循环(这也是不必要的,因为
yield from
会处理这个问题)

还有一个您没有处理的复杂性,即并非所有类似文件的对象都是TextIOWrapper,例如
StringIO
。我建议要么检查,要么寻找
read
方法(尽管这不是
csv.reader
实际寻找的,而且允许使用原始IO对象)

def get_行(行源):
“”“从输入中获取行迭代器:
*假定字符串是文件路径,并作为TSV文件读取
*类似文件的对象被解析为TSV
*其他iterables按原样返回
"""
如果isinstance(行/源,str):
将open(rows\u source,encoding=“utf-8”)作为csvf:
流程\单据\行的收益率(csvf)
返回
elif isinstance(行\源,io.TextIOBase):
rows\u source=csv.reader(rows\u source,delimiter=“\t”)
源行的产量

如果函数在继续之前必须检查其参数的类型,那么它做的工作太多了。您的函数应该专注于迭代和处理iterable的每个元素

def process_rows(rows):
    for row in rows:
        process_row(row))


with open("foo.csv") as f:
    process_rows(csv.reader(f))
另一个函数可以处理将每行拆分为字段的操作:

def process_csv_rows(rows):
    process_rows(csv.reader(rows))


with open("foo.csv") as f:
    process_csv_rows(f)
甚至可以为您打开文件:

def process_csv_file(filename):
    with open(filename) as f:
        process_csv_rows(f)


process_csv_file("foo.csv")

“如果您的函数在继续之前必须检查其参数的类型,那么它做的工作太多了”=>这就是为什么我希望助手将输入转化为我可以迭代的内容,这有利于许多需要这样做的函数。process\u csv\u行不够好,因为我需要为这些函数编写相同的行(另外,Python不允许方法/函数重载,但这是另一回事)。这是一个明确说明您正在做什么的问题。作为程序员,您知道何时向函数传递文件名而不是行数,因此只需将其作为参数传递给正确的函数即可。(如果您不知道某个特定变量的值是文件名还是iterable或行,那么您可能需要担心更大的设计问题。)不,我为库编写的许多函数将以不同的形式接收值:文件路径、stdin(即文件处理程序)、测试列表。他们不会事先知道程序员需要发送什么,我正试图避免为每个xxx编写xxx+xxx\u csv+xxx\u文件。我是说,让程序员的工作来指定它。对他们来说,使用正确的函数让你试着猜测会更容易、更简洁。对不起,但我认为你没有抓住重点。我正在写那个库,我不知道我会得到什么。因此,要么我将那些xxx_csv和xxx_文件函数编写几十次(相同的转换代码重复几十次),要么我让调用程序处理相同的问题(即,他/她将不得不编写这些相同的转换几十次)
process\u doc\u rows()
是我将其分解到一个地方,让xxx只处理行生成器的方法。啊,你是对的,一开始,我没有在最后使用收益率,这就是我编写这些ifs的原因。我不知道来自的收益率,谢谢!我已经按照你提议的方式重写了。