我正在尝试结合Python学习一点mapreduce。
现在,我从我正在做的教程中运行了以下代码。
from mrjob.job import MRJob
class SpendByCustomer(MRJob):
def mapper(self, _, line):
(customerID, itemID, orderAmount) = line.split(',')
yield customerID, float(orderAmount)
def reducer(self, customerID, orders):
yield customerID, sum(orders)
if __name__ == '__main__':
SpendByCustomer.run()
它应执行以下操作。
当我打!python SpendByCustomers.py customer-orders.xls > test.txt
它应该读取.xls
文件,映射并减少它,然后将输出写入test.txt
。
一切正常,我基本上理解它。但是,我真的很想获得有关以下内容的更多见解:
在
def mapper(self, _, line):
_
在这里做什么?在
if __name__ == '__main__': SpendByCustomer.run()
这个函数到底在做什么?
在 Python 中,字母、数字和下划线可用于变量名称。(变量名称不能以数字开头。 下划线是不使用的值的常用变量名称。 例如,如果我想打印"hello"5 次,我可以执行以下操作:
for _ in range(5):
print("hello")
在这个例子中,_
并没有真正做任何事情;它之所以存在,是因为我们必须在那里放置一些变量名称,但是使用该变量名称是向查看代码的其他程序员传达的信息,即该变量不会被使用。 对于函数,这是因为通常使用三个参数调用mapper
方法,但在mapper
方法中,该参数未使用。 至于第二个问题,SpendByCustomer.run()
是在mrjob.job.MRJob
类中定义的方法。 正如你可能已经从它的名字中猜到的那样,它运行MapReduce作业。 它使用您的mapper()
方法和reducer()
方法来执行此操作。
在
def mapper(self, _, line):
_
在这里做什么?
MRJob.mapper
具有方法签名MRJob.mapper(key, value)
如果在派生类中重新定义它(就像您所做的那样),则必须保留兼容的签名,因此必须接受两个参数。调用您的函数时,将某个键作为第一个参数,使用一些值作为第二个参数。文档指出"如果你不弄乱协议",你将被调用的密钥将是None
,所以它不是特别有趣。因此,您对该方法的重新定义不会对它执行任何操作。
在 Python 中,通常使用名称 _
作为签名中必须具有的参数,以保持与接口的兼容性。从技术上讲,这个参数名称没有什么特别之处。它只是一个单字符名称,使用标识符允许的字符之一。选择它主要是因为它的视觉外观(看起来有点像未填充的字段),以告诉人类读者您的代码:我在这里被传递了一个值,但我不在乎它是什么(并且不会在我的实现中使用它)。
在
if __name__ == '__main__': SpendByCustomer.run()
这个函数到底在做什么?
对于if __name__ == '__main__':
部分,请参阅如果__name__=="__main__":做什么?
有关.run()
部分,请参阅 MRJob 文档。