在Python中构造函数调用

时间:2018-11-07 11:22:49

标签: python unit-testing functional-programming

我不知道如何构造函数调用。我知道“干净的代码规则”说函数只能做一件事,并且应该使它们尽可能的小。这样吧。

但是我不确定如何调用这些函数。我不知道如何命名这些概念,但是我正努力在“在函数内部调用函数”或“链接/管道函数”之间进行选择。在下面的示例中,我有一个非常基本的示例,但是我希望它可以使我所讨论的概念更清楚。

“链接/管道”使代码更易于单元测试,您无需模拟函数。但是,“调用内部函数”会使代码更短,更易读。

您如何选择一种方式?

顺便说一句,如果有人可以指出我的好消息来源,那我将很难找到概念之间的差异。

# Calling inside a function

def sum_of_squares(numbers):
    return sum([square(num) for num in numbers])

def square(num):
    return num*num

numbers = [2,3,4]
square_sum = sum_of_squares(numbers))

print(square_sum) # prints 29

-----

# Chaining/Piping

def sum_of_squares(squares):
    return sum(squares)

def square(num):
    return num*num

numbers = [2,3,4]
squares = [ square(num) for num in numbers ]
square_sum = sum_of_squares(squares))

print(square_sum) # prints 29

3 个答案:

答案 0 :(得分:0)

基本上,两种类型的声明都是好的和可用的。 您可以根据要实现的目标和上下文来选择一个或另一个。 最重要的方面之一是代码的透明度可读性。 您总是应该在两种类型的声明之间找到权衡

如果您使用一个(或几个)函数编写代码,则代码的主流将非常透明和清晰,但是,如果有人(或仅您自己)需要阅读和解释您的代码,您将拥有总是跳回到函数声明,然后,如果在该函数中有另一个函数调用,则继续进行下去,依此类推,这可能非常不方便,并且很可能在一段时间后丢失该行。

另一方面,如果您像第二种方法那样“链接”了许多函数调用,那么前半部分,即代码的主要流将增长,并且一段时间后将变得不那么透明。我的主要经验法则是始终“掌握”真正足以使您最近理解您的代码,并始终选择一些简单的不言自明的函数命名约定,以便以后可以更好地阅读您的代码。

另一方面,如果要使用相同的代码序列,则应在函数中执行。在这种情况下,您显然会首选第一种方式。

我希望这会有所帮助。

答案 1 :(得分:0)

在我看来,干净的代码的意思是保持代码的一致性和可读性。我认为这将使代码清晰易读。

  

任何没有编写代码或没有先验知识的人   关于代码的功能应该能够理解最终的结果   结果代码将在运行时给出,而您不必   向他们解释您的代码的作用。

因此,对我来说,平方函数是不必要的。 number * number不言自明。

所以我的平方和将是

numbers = [2, 3, 4]
square_sum = sum(number * number for number in numbers)

或者如果需要平方函数或者

numbers = [2, 3, 4]
sqaureFunction = lambda number: number * number
square_sum = sum(map(sqaureFunction, numbers))

在这样的小型程序中,这没关系,您不应该花时间在干净的代码上,因为该程序没有做太多事情。所以,我将举一个更大的例子来说明这一点...

想象一下,您正在使用漂亮的汤来编写HTML解析器,以从网站中提取信息,这就是我的用例。这就是您的算法抽象的样子。

  • 从网站下载HTML。
  • 将其提供给bs4或lxml之类的HTML解析器。
  • 浏览HTML汤中的每个标签并提取信息。
  • 存储它。

现在是详细部分,

HTML解析的第1部分:提取

  • 首先,首先获取要提取的网站网址
  • 收集信息是必需的标头和发布数据以获取实际信息
  • 使用必要的标题和有效载荷向网站提出请求,该请求会带回HTML
  • 将HTML写入文件,以便您可以重复使用它而无需在每次测试时都发出多个请求。

HTML解析的第二部分:解析器

  • 从文件加载HTML
  • 浏览HTML并获取所需数据
  • 将信息存储在数据库或文件中。

最后,代码:

我将在此处编写提取部分的代码。请参阅 makeHttpRequest函数的文档,以了解简洁的代码概念

def makeGetRequest(url, headers = []):
    # You may want to preprocess. Add default headers, etc ... which are specific to the site.
    response = requests.get(url, headers=headers, params=payload)
    return response

def makeHttpRequest(url, method = "GET", headers = [], payload = {}):
    """
    This function makes an HTTP request.

    You may wanna do several requests before getting the actual information.
    But every time you're going to call make request because it does one thing i.e. Making a request. 
    There can be 101 things that can happen inside this function. 
    But on the outlook, it is just making a single request which can considered as 1 task.
    """
    # You may wanna do POST, PUT, PATCH. But this is just for giving general idea
    if method == "GET":
        response = makeGetRequest(url, headers=headers)
        return response.text
    return None

def extractor(storageFilename):
    """
    This function will make HTTP request and get HTML data.
    After getting HTML data it will store it in a file.
    """
    (url, headers, payload) = loadRequestInformation()
    html = makeHttpRequest(url, headers=headers, payload=payload)
    with open(storageFilename) as htmlFileHandle:
        htmlFileHandle.write(html)

答案 2 :(得分:0)

首先,您应该准备好要进行链接/管道连接的功能,然后可以使用另一个包装所有功能的功能来完成为调用者提供更高级别抽象的特定任务。