功能测试代码python

Functional programming has been getting more and more popular in recent years. Not only is it perfectly suited for tasks like data analysis and machine learning. It’s also a powerful way to make code easier to test and maintain.

近年来,函数式编程越来越流行。 它不仅非常适合数据分析和机器学习等任务。 这也是使代码更易于测试和维护的强大方法。

The trend is easy to see: Even though they’re still in a bit of a niche, purely functional languages like Elm and Haskell are gaining traction. Languages that are somewhat functional, like Scala and Rust, are taking off. And popular languages like C++ and Python are adding more and more pieces of functional programming to their repertoire.

趋势很容易看出:尽管它们仍然处于利基市场,但是像Elm和Haskell这样的纯函数式语言正逐渐受到关注。 具有某种功能的语言(例如Scala和Rust )正在兴起。 诸如C ++和Python之类的流行语言正在为其功能表添加越来越多的功能编程。

If you’ve used to object-oriented code, writing functional programs can seem scary at first. The good news is that you can mix-and-match functional and object-oriented code pretty well. A few tweaks from functional programming are often enough to reap some benefits. So let’s get to it!

如果您已经习惯了面向对象的代码,那么一开始编写功能程序似乎很恐怖。 好消息是您可以很好地混合和匹配功能和面向对象的代码。 函数式编程的一些调整通常足以获得一些好处。 因此,让我们开始吧!

纯功能 (Pure functions)

The pesky thing with non-functional programming is that functions can have side effects. That is, they make use of variables that don’t necessarily appear in the declaration of the function.

非函数式编程的烦人之处在于函数可能会产生副作用。 也就是说,它们利用了不一定出现在函数声明中的变量。

Consider this simple example, where we’re adding two numbers:

考虑这个简单的示例,我们在其中添加两个数字:

b = 3def add_ab(a):    return a + badd_ab(5)

The global variable b doesn’t appear in the declaration of add_ab, so if you want to debug it, you’ll have to check that b is in fact used. Sounds simple, but it can get tedious with bigger programs. We can fix this easily by being honest about what we’re putting into the function:

全局变量b不会出现在add_ab的声明中,因此,如果要调试它,则必须检查b是否确实已使用。 听起来很简单,但是在大型程序中可能会变得乏味。 我们可以通过诚实地对待函数中所包含的内容来轻松解决此问题:

def add_ab_functional(a, b):    return a + badd_ab_functional(5, 3)

This is just a dumb little example. But with larger programs, you’ll notice how much easier you can understand and debug the code when you don’t need to worry about side-effects.

这只是一个愚蠢的小例子。 但是对于大型程序,您无需担心副作用,就会注意到可以轻松理解和调试代码。

高阶函数 (Higher-order functions)

In functional programming, you can nest functions: either you design a function that takes another function as an argument, or you code a function that returns another function.

在函数式编程中,您可以嵌套函数:设计一个将另一个函数作为参数的函数,或者编写一个返回另一个函数的函数。

As an example for a function that takes another function, consider that you have an array of numbers and you’d like to calculate the sine, cosine, and exponential of that array. You could, in theory, write it like this (numpy is a Python package for maths):

作为使用另一个函数的函数的示例,请考虑您有一个数字数组,并且想要计算该数组的正弦,余弦和指数。 从理论上讲,您可以这样写( numpy是用于数学的Python包):

import numpy as np# make a list of numbers as input values for functionsnumbers_list = np.arange(0, 2*np.pi, np.pi/10).tolist()# calculate sinedef do_sin(numbers):    return np.sin(numbers)sin_list = do_sin(numbers_list)# calculate cosinedef do_cos(numbers):    return np.cos(numbers)cos_list = do_cos(numbers_list)# calculate exponentialdef do_exp(numbers):    return np.exp(numbers)exp_list = do_exp(numbers_list)

This is nice and simple, but it’s kind of annoying to write three different functions with the exact same structure. Instead, we can write a function that takes the other functions like so:

这是很好而且很简单,但是用完全相同的结构编写三个不同的函数有点烦人。 相反,我们可以编写一个采用其他功能的函数,如下所示:

import numpy as np# make a list of numbers as input values for functionsnumbers_list = np.arange(0, 2*np.pi, np.pi/10).tolist()# calculate with some functiondef do_calc(numbers, function):    return function(numbers)# calculate sin, cos, and expnew_sin_list = do_calc(numbers_list, np.sin)new_cos_list = do_calc(numbers_list, np.cos)new_exp_list = do_calc(numbers_list, np.exp)

Not only is this more concise and nicer to read. It’s also easier to expand because you only need to add one line for a new function, instead of three in the example above.

这不仅更简洁,而且更易于阅读。 扩展起来也更容易,因为您只需为新function添加一行,而不是上面示例中的三行。

One key concept of functional programming is nesting functions into one another. Photo by ThisisEngineering RAEng on Unsplash
函数式编程的一个关键概念是函数之间的嵌套。 ThisisEngineering RAEng在Unsplash上拍摄的照片

You can also turn the concept of a function in a function upside down: Not only can you make a function take another function as an argument; you can also make it return an argument.

您也可以颠倒一个函数的概念:不仅可以使一个函数接受另一个函数作为参数,还可以使另一个函数成为参数。 您还可以使其返回参数。

Imagine you have an array of numbers, and you need to increment each element of the array by 2:

假设您有一个数字数组,并且需要将数组的每个元素增加 2:

def add2(numbers):         incremented_nums = []         for n in numbers:                 incremented_nums.append(n + 2)             return incremented_numsprint(add2([23, 88])) # returns [25, 90]

If you want to increment the elements of an array by something else, you could, of course, copy-paste this function and replace the 2 by that increment. But there’s a more elegant solution: we can write a function that takes any increment and returns another function that performs what add2 does, but for whichever increment.

如果您想以其他方式增加数组的元素,则可以复制粘贴此函数,并以该增量替换2 。 但是,还有一个更优雅的解决方案:我们可以编写一个函数,该函数可以任意递增,并返回另一个函数,该函数执行add2所做的事情,但无论递增多少。

def add_num(increment):    def add_inc(numbers):        incremented_nums = []        for n in numbers:            incremented_nums.append(n + increment)        return incremented_nums    return add_incadd5_25 = add_num(5.25)print(add5_25([23.37,88.93])) # returns [28.62, 94.18]

With this routine, each new function takes one line to define instead of five. And like the function that takes a function, the function returning a function is easier to debug: if you had a bug in add_num, you’d only have to fix that. You don’t need to go back and fix add2 and whichever other function you might have defined in the same way. The bigger programs get, more this pays off.

使用此例程,每个新函数只需要一行定义,而不是五行。 与采用函数的函数一样,返回函数的函数更易于调试:如果在add_num存在错误, add_num只需对其进行修复。 您无需返回并修复add2以及可能以相同方式定义的任何其他函数。 获得更大的程序,更多的回报。

Note that even though add_num is written in a functional style, it isn’t purely functional. It has one side effect, numbers, which makes it an impure function. But that’s okay: you don’t need to be a slave to one programming paradigm; instead, you can get the best of each to maximize your productivity.

请注意,即使add_num是按功能样式编写的,也不是纯粹功能。 它具有numbers副作用,这使其功能不纯净。 但这没关系:您不必成为一个编程范例的奴隶。 取而代之的是,您可以充分利用每种技术的优势,以最大限度地提高生产力。

Decorators can make your code more elegant. Photo by Fernando Hernandez on Unsplash
装饰器可以使您的代码更加优雅。 费尔南多·埃尔南德斯在Unsplash上的照片

装饰工 (Decorators)

Of course you can combine the two approaches from above and write a function that not only takes a function as an argument, but returns a function as well. Consider this code, where we’re expanding on the add_num function from above:

当然,您可以从上面结合两种方法并编写一个函数,该函数不仅将函数作为参数,而且还返回一个函数。 考虑下面的代码,我们从上面扩展add_num函数:

def add_num(message):    def add_inc(increment, numbers):        message()        incremented_nums = []        for n in numbers:            incremented_nums.append(n + increment)        return incremented_nums    return add_incdef message1():    print("Doing something...")message1 = add_num(message1)print(message1(5, [28,93]))# Doing something...# [33, 98]

One difference to the example above is that you can customize the message that is output on the screen. In a bigger program, you could expand that to account for different error messages, for example.

与上面的示例的不同之处在于,您可以自定义屏幕上输出的消息。 例如,在更大的程序中,您可以扩展它以解决不同的错误消息。

The line message1 = add_num(message1) is where the magic happens: the name message1 now points to the inner layer of add_num, i.e., to add_inc. This is called a decoration.

message1 = add_num(message1)是其中魔法发生:名称message1现在指向的内层add_num ,即, add_inc 。 这称为装饰。

The other difference is that the argument increment has been pushed downwards; this just makes it easier to handle the next step.

另一个区别是自变量increment已被向下推; 这只会使下一步操作变得更容易。

We can make the decoration even nicer with the @ syntax (the def add_num part will stay the same):

我们可以使用@语法使修饰更好( def add_num部分将保持不变):

@add_numdef message1():    print("Doing something...")print(message1(5, [28,93]))

In effect, this is just an even neater way of writing a decoration. Note that using decorators doesn’t imply that your code is functional. Rather, decorators are inspired by functional programming, just like nested functions are. The above example isn’t purely functional since it contains two side-effects, but it’s inspired by functional programming nevertheless.

实际上,这只是编写装饰的一种更整洁的方式。 请注意,使用装饰器并不意味着您的代码可以正常工作。 相反,装饰器是受函数编程启发的,就像嵌套函数一样。 上面的示例并不是纯函数式的,因为它包含两个副作用,但是它仍然受到函数式编程的启发。

生成器表达式和列表推导 (Generator expressions and list comprehensions)

List comprehensions and generator expressions are concepts that Python copied from Haskell, a purely functional programming language. Consider the following example, where we’re trying to calculate a few square numbers:

列表推导和生成器表达式是Python从Haskell(一种纯函数式编程语言)复制的概念。 考虑下面的示例,我们试图计算一些平方数:

numbers = [0, 1, 2, 3, 4]square_numbers = []for x in range(5):    square_numbers.append(x**2)square_numbers # [0, 1, 4, 9, 16]

That’s quite clunky since we need to define two arrays and write a for loop. A much more concise and elegant way is to do this with a list comprehension:

这很笨拙,因为我们需要定义两个数组并编写一个for循环。 一种更简洁,更优雅的方法是通过列表理解来做到这一点:

square_numbers = [x**2 for x in range(5)]square_numbers # [0, 1, 4, 9, 16]

You can select only particular elements by adding an if condition. For example, let’s say we only want those square numbers that are even:

您可以通过添加if条件来仅选择特定元素。 例如,假设我们只想要偶数个平方数:

even_square_numbers = [x**2 for x in range(5)    if x%2 == 0]even_square_numbers # [0, 4, 16]

List comprehensions store all values of a list in the memory. That’s wonderful for small objects, but they would make your program rather sluggish if you’re dealing with large lists. That’s where generator expressions come into play:

列表推导将列表的所有值存储在内存中。 对于小型对象而言,这很棒,但是如果您要处理大型列表,它们会使您的程序变慢。 这就是生成器表达式的作用:

lots_of_square_numbers = (x**2 for x in range(10000))lots_of_square_numbers # <generator object <genexpr> at 0x1027c5c50>

Generator expressions don’t evaluate the objects immediately. That’s why you just see a funny expression if you try to call them (the exact form of the output depends on your OS). However, they make them accessible for later. You can call an element of a generator expression like this:

生成器表达式不会立即评估对象。 这就是为什么您尝试调用它们时会看到一个有趣的表达式的原因(输出的确切形式取决于您的操作系统)。 但是,它们使它们可供以后使用。 您可以像这样调用生成器表达式的元素:

next(lots_of_square_numbers) # 0next(lots_of_square_numbers) # 1next(lots_of_square_numbers) # 4...

Or you could create a list of the first few elements in the generator expression like so:

或者,您可以像这样在生成器表达式中创建前几个元素的列表:

[next(lots_of_square_numbers) for x in range(10)]# [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

As with the other tricks, this doesn’t automatically make your code purely functional. It’s just a concept borrowed from functional programming that can be useful in many situations.

与其他技巧一样,这不会自动使您的代码纯粹起作用。 这只是从函数式编程中借用的一个概念,在许多情况下都可能有用。

Lambda expressions can be a neat alternative to regular function definitions. Photo by NESA by Makers on Unsplash
Lambda表达式可以替代常规函数定义。 由NESS 由Makers在Unsplash上拍摄

小函数和lambda表达式 (Small functions and the lambda expression)

If you want to write a small function, there is nothing wrong in writing it like this:

如果要编写一个小函数 ,则编写这样的东西没有错:

def add_ab(a, b):    return a + b

However, you could also use a lambda-expression:

但是,您也可以使用lambda -expression:

add_ab2 = lambda a, b: a + b

It’s practically the same length, and it’s pretty readable once you’ve got used to the syntax. Whether you use it or not really depends on your personal taste. But as we’ll see below, it can be quite handy in certain situations.

它的长度几乎相同,一旦您习惯了语法,就很容易阅读。 是否使用它实际上取决于您的个人品味。 但是,正如我们将在下面看到的,在某些情况下它可能非常方便。

Like with the above, using lambda-expressions won’t necessarily make your code functional, even though they are a key idea of functional programming.

与上述类似,即使使用lambda -expressions也不一定会使您的代码正常工作,即使它们是函数式编程的关键思想。

内置Python函数 (Built-in Python functions)

地图() (map())

The function map() basically returns generator expressions. This is a simple example:

map()函数基本上返回生成器表达式。 这是一个简单的示例:

numbers = [0, 1, 2, 3, 4]squared_numbers_map = list(map(lambda x: x**2, numbers))print(squared_numbers_map)# [0, 1, 4, 9, 16]

As you saw earlier, you can do the same thing with a list comprehension. Sometimes your code can be a bit more readable, however, when you use the map() function.

如前所述,您可以通过列表理解来做同样的事情。 有时候,当您使用map()函数时,您的代码可能更具可读性。

过滤() (filter())

This is analogous to a list comprehension with an if clause, for example like so:

这类似于带有if子句的列表理解,例如:

squared_numbers_map_even = list(filter(lambda x: x%2 == 0, squared_numbers_map))print(squared_numbers_map_even)# [0, 4, 16]

You can also nest map() and filter() like so:

您还可以像这样嵌套map()filter()

squared_numbers_map_even_new = list(filter(lambda x: x%2 == 0, list(map(lambda x: x**2, numbers))))print(squared_numbers_map_even_new)# [0, 4, 16]

枚举() (enumerate())

If you’re looping through a list and you need to keep track of the indexes, enumerate() is a good option:

如果要遍历列表,并且需要跟踪索引,那么enumerate()是一个不错的选择:

for num in enumerate(squared_numbers_map_even):    print(num)# (0, 0)# (1, 4)# (2, 16)

压缩() (zip())

If you need to create tuples from two lists, you can use zip():

如果需要从两个列表创建元组,则可以使用zip()

list(zip(['a', 'b', 'c'], (1, 2, 3)))# [('a', 1), ('b', 2), ('c', 3)]

The list() is wrapped around this expression because zip() only returns iterables like generator expressions do.

list()围绕此表达式包装,因为zip()仅返回生成器表达式一样的可迭代对象。

functools模块 (The functools module)

Sometimes you’ll have a function that takes a few arguments, but you need to fix a few. Consider this simple example:

有时,您会有一个带有一些参数的函数,但是您需要修复一些参数。 考虑以下简单示例:

import functoolsdef add_lots_of_numbers(a, b, c, d):    return a + b + c + dadd_a_and_b_27 = functools.partial(add_lots_of_numbers, c=18, d=9)add_a_and_b_27(1,2) # 30

There are a few more functions apart from functools.partial() in this module, but this is by far the most important one. As before, partial() doesn’t always lead to functional code, but it’s a neat concept that’s borrowed from functional programming.

除了functools.partial() ,此模块中还有其他一些功能,但这是迄今为止最重要的功能。 和以前一样, partial()并不总是会生成功能代码,但这是从功能编程中借来的一个简洁的概念。

一些简单的技巧可以帮助您 (A few simple tricks can go a long way)

When you started out coding, you probably heard a lot about object-oriented programming, and not very much about functional programming. That does make sense, since object-oriented programming is extremely useful.

在开始编码时,您可能会听到很多有关面向对象的编程的知识,而关于功能编程的知识则不是很多。 这确实是有道理的,因为面向对象的编程非常有用。

But in recent years, we’ve been encountering more and more problems that are easier to crack when you have some skills in functional programming.

但是近年来,我们遇到了越来越多的问题,当您具备一些函数式编程技能时,这些问题就更容易破解。

You don’t need to learn a functional programming language like Elm or Haskell right away. Instead, you can take the most useful aspects of them and use them directly in your Python code.

您不需要立即学习像Elm或Haskell这样的函数式编程语言。 相反,您可以利用它们中最有用的方面,并直接在Python代码中使用它们。

Once you know the tricks, you’ll see opportunities to use them all over the place. Happy coding!

一旦知道了窍门,您将发现在各地使用它们的机会。 编码愉快!

翻译自: https://towardsdatascience.com/how-to-make-your-python-code-more-functional-b82dad274707

功能测试代码python


http://www.taodudu.cc/news/show-994877.html

相关文章:

  • 普通话测试系统_普通话
  • 动漫数据推荐系统
  • Alex Hanna博士:Google道德AI小组研究员
  • python度量学习_Python的差异度量
  • 网页视频15分钟自动暂停_在15分钟内学习网页爬取
  • django 性能优化_优化Django管理员
  • ai驱动数据安全治理_JupyterLab中的AI驱动的代码完成
  • python中定义数据结构_Python中的数据结构—简介
  • 数据质量提升_合作提高数据质量
  • 删除wallet里面登机牌_登机牌丢失问题
  • 字符串操作截取后面的字符串_对字符串的5个必知的熊猫操作
  • 数据科学家访谈录 百度网盘_您应该在数据科学访谈中向THEM提问。
  • power bi函数_在Power BI中的行上使用聚合函数
  • 大数定理 中心极限定理_中心极限定理:直观的遍历
  • 探索性数据分析(EDA)-不要问如何,不要问什么
  • 安卓代码还是xml绘制页面_我们应该绘制实际还是预测,预测还是实际还是无关紧要?
  • 云尚制片管理系统_电影制片厂的未来
  • t-sne原理解释_T-SNE解释-数学与直觉
  • js合并同类数组里面的对象_通过同类群组保留估算客户生命周期价值
  • com编程创建快捷方式中文_如何以编程方式为博客创建wordcloud?
  • 基于plotly数据可视化_如何使用Plotly进行数据可视化
  • 用Python创建漂亮的交互式可视化效果
  • php如何减缓gc_管理信息传播-使用数据科学减缓错误信息的传播
  • 泰坦尼克号 数据分析_第1部分:泰坦尼克号-数据分析基础
  • vba数组dim_NDArray — —一个基于Java的N-Dim数组工具包
  • python算法和数据结构_Python中的数据结构和算法
  • python dash_Dash是Databricks Spark后端的理想基于Python的前端
  • 在Python中查找子字符串索引的5种方法
  • 趣味数据故事_坏数据的好故事
  • python分句_Python循环中的分句,继续和其他子句

功能测试代码python_如何使您的Python代码更具功能性相关推荐

  1. python可以调试吗_调试-有什么好的方法可以使我的Python代码首次运行?

    调试-有什么好的方法可以使我的Python代码首次运行? 我的代码中出现了很多错误. 因此,我希望能够在一开始就将它们最小化,或者在执行代码之前看到尽可能多的错误. 这可能吗,如果可以,我该怎么做? ...

  2. python代码打好了怎么运行-python代码是怎样运行的

    python作为一种动态语言,其实是一个解释器软件包.当Python运行脚本时,在代码开始进行处理之前,Python还会执行一些步骤.第一步是编译成所谓的"字节码",如果Pytho ...

  3. latex附录中放python代码_在Latex中插入Python代码

    这里指的插入是指最终能在生成的pdf中显示高亮的Python代码. 在Latex中插入Python代码,需要一个第三发的宏包pythonhighlight: https://github.com/ol ...

  4. python代码写好了怎么运行-python代码是怎样运行的

    python作为一种动态语言,其实是一个解释器软件包.当Python运行脚本时,在代码开始进行处理之前,Python还会执行一些步骤.第一步是编译成所谓的"字节码",如果Pytho ...

  5. 水仙花数python代码for_水仙花数如何用python代码表示?

    水仙花数如何用python代码表示? 水仙花数的python代码为: 水仙花数是指一个3位正整数,它的每个位上的数字的3次幂之和等于它本身.(例如:1^3 + 5^3+ 3^3 = 153) 下面用一 ...

  6. sphinx python_如何使用Sphinx记录Python代码

    sphinx python Python代码可以在其源代码中包含文档. 这样做的默认方式取决于docstrings ,它以三引号格式定义. 尽管文档的价值是有据可查的,但似乎似乎太普遍了,以至于没有足 ...

  7. 9个技巧使你的Python代码更Pythonic

    目录 前言 01 product() 使用 product() 函数避免嵌套的Python循环 02 海象操作符 赋值表达式的一个可爱技巧 03 三元条件运算符 用一行写一个简单的If-Else结构 ...

  8. studio python 格式快捷键_ubuntu下visual studio 怎么使一段python代码代码格式化

    展开全部 感觉有了visual studio code之后,不管编写什么语言的代码都可以,简单安装对e69da5e887aa62616964757a686964616f31333363396433应的 ...

  9. python代码_如何使用 Sphinx 给 Python 代码写文档

    最好将文档作为开发过程的一部分.Sphinx 加上 Tox,让文档可以轻松书写,并且外观漂亮.-- Moshe Zadka(作者) Python 代码可以在源码中包含文档.这种方式默认依靠 docst ...

最新文章

  1. 专访博世王红星:大数据和AI将是中国制造业升级新动力
  2. php 日志处理工具 SeasLog 的使用
  3. 网站漏洞检测针对区块链网站安全分析
  4. [转载] java虚拟机 jvm 出入java栈 栈空间内存分配
  5. 再谈拍照,OPPO这次拿什么和iPhone7拼?
  6. php去掉关联数组,大家都应该掌握的PHP关联数组使用技巧
  7. gflags的使用实例(转载)
  8. 我的github教程
  9. 【入门二】格式化输入/输出
  10. 详解java定时任务
  11. php 日期函数大全,php日期函数
  12. 关于海康相机ip地址无法更改问题
  13. 手机百度未能链接到服务器,北京地区用户“无法连接服务器” 百度:运营商问题...
  14. NShape(开源矢量图形编辑器) 入门(一)
  15. 交换机二/三层转发原理
  16. 计算机专业基础综合408备考经验分享
  17. 卡诺图最简化SOP/POS表达式
  18. IMU参数对比(未完待续)
  19. 服务器访问时502 Server dropped connection 错误解决方法
  20. 一个关于SDWAN单臂部署方案验证的实验

热门文章

  1. BZOJ2818-莫比乌斯反演/欧拉函数
  2. Unity(一)必然事件
  3. Mysql(三) Mysq慢查询日志
  4. 线程系列3--Java线程同步通信技术
  5. 读书笔记--模板与泛型编程
  6. ZOJ2930 The Worst Schedule(最小割)
  7. iOS-数据持久化-第三方框架FMDB的使用
  8. Android 网络通信架构学习
  9. C#基础加强_泛型的基本原理
  10. python学习笔记:遍历目录