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

功能测试代码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 = 3
def add_ab(a):
return a + b
add_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 + b
add_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 functions
numbers_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 functions
numbers_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 exp
new_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添加一行,而不是上面示例中的三行。

Woman writing mathematical functions on a whiteboard
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副作用,这使其功能不纯净。 但这没关系:您不必成为一个编程范例的奴隶。 取而代之的是,您可以充分利用每种技术的优势,以最大限度地提高生产力。

Man with laptop on black leather couch
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) # 0
next(lots_of_square_numbers) # 1
next(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.

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

Man sitting at table in front of laptop
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.mzph.cn/news/388267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

layou split 属性

layou split&#xff1a;true - 显示侧分栏 转载于:https://www.cnblogs.com/jasonlai2016/p/9764450.html

C#Word转Html的类

C#Word转Html的类/**//******************************************************************** created: 2007/11/02 created: 2:11:2007 23:13 filename: D:C#程序练习WordToChmWordToHtml.cs file path: D:C#程序练习WordToChm file bas…

分库分表的几种常见形式以及可能遇到的难题

前言 在谈论数据库架构和数据库优化的时候&#xff0c;我们经常会听到“分库分表”、“分片”、“Sharding”…这样的关键词。让人感到高兴的是&#xff0c;这些朋友所服务的公司业务量正在&#xff08;或者即将面临&#xff09;高速增长&#xff0c;技术方面也面临着一些挑战。…

线性回归和将线拟合到数据

Linear Regression is the Supervised Machine Learning Algorithm that predicts continuous value outputs. In Linear Regression we generally follow three steps to predict the output.线性回归是一种监督机器学习算法&#xff0c;可预测连续值输出。 在线性回归中&…

小米盒子4 拆解图解_我希望当我开始学习R时会得到的盒子图解指南

小米盒子4 拆解图解Customizing a graph to transform it into a beautiful figure in R isn’t alchemy. Nonetheless, it took me a lot of time (and frustration) to figure out how to make these plots informative and publication-quality. Rather than hoarding this …

蓝牙一段一段_不用担心,它在那里存在了一段时间

蓝牙一段一段You’re sitting in a classroom. You look around and see your friends writing something down. It seems they are taking the exam, and they know all the answers (even Johnny who, how to say it… wasn’t the brilliant one). You realize that your ex…

普通话测试系统_普通话

普通话测试系统Traduzido/adaptado do original por Vincius Barqueiro a partir do texto original “Writing Alt Text for Data Visualization”, escrito por Amy Cesal e publicado no blog Nightingale.Traduzido / adaptado由 VinciusBarqueiro 提供原始 文本“为数据可…

美国队长3:内战_隐藏的宝石:寻找美国最好的秘密线索

美国队长3:内战There are plenty of reasons why one would want to find solitude in the wilderness, from the therapeutic effects of being immersed in nature, to not wanting to contribute to trail degradation and soil erosion on busier trails.人们有很多理由想要…

Java入门第三季——Java中的集合框架(中):MapHashMap

1 package com.imooc.collection;2 3 import java.util.HashSet;4 import java.util.Set;5 6 /**7 * 学生类8 * author Administrator9 * 10 */ 11 public class Student { 12 13 public String id; 14 15 public String name; 16 17 public Set<…

动漫数据推荐系统

Simple, TfidfVectorizer and CountVectorizer recommendation system for beginner.简单的TfidfVectorizer和CountVectorizer推荐系统&#xff0c;适用于初学者。 目标 (The Goal) Recommendation system is widely use in many industries to suggest items to customers. F…

1.3求根之牛顿迭代法

目录 目录前言&#xff08;一&#xff09;牛顿迭代法的分析1.定义2.条件3.思想4.误差&#xff08;二&#xff09;代码实现1.算法流程图2.源代码&#xff08;三&#xff09;案例演示1.求解&#xff1a;\(f(x)x^3-x-10\)2.求解&#xff1a;\(f(x)x^2-1150\)3.求解&#xff1a;\(f…

Alex Hanna博士:Google道德AI小组研究员

Alex Hanna博士是社会学家和研究科学家&#xff0c;致力于Google的机器学习公平性和道德AI。 (Dr. Alex Hanna is a sociologist and research scientist working on machine learning fairness and ethical AI at Google.) Before that, she was an Assistant Professor at th…

安全开发 | 如何让Django框架中的CSRF_Token的值每次请求都不一样

前言 用过Django 进行开发的同学都知道&#xff0c;Django框架天然支持对CSRF攻击的防护&#xff0c;因为其内置了一个名为CsrfViewMiddleware的中间件&#xff0c;其基于Cookie方式的防护原理&#xff0c;相比基于session的方式&#xff0c;更适合目前前后端分离的业务场景&am…

Kubernetes的共享GPU集群调度

问题背景 全球主要的容器集群服务厂商的Kubernetes服务都提供了Nvidia GPU容器调度能力&#xff0c;但是通常都是将一个GPU卡分配给一个容器。这可以实现比较好的隔离性&#xff0c;确保使用GPU的应用不会被其他应用影响&#xff1b;对于深度学习模型训练的场景非常适合&#x…

django-celery定时任务以及异步任务and服务器部署并且运行全部过程

Celery 应用Celery之前&#xff0c;我想大家都已经了解了&#xff0c;什么是Celery&#xff0c;Celery可以做什么&#xff0c;等等一些关于Celery的问题&#xff0c;在这里我就不一一解释了。 应用之前&#xff0c;要确保环境中添加了Celery包。 pip install celery pip instal…

网页视频15分钟自动暂停_在15分钟内学习网页爬取

网页视频15分钟自动暂停什么是网页抓取&#xff1f; (What is Web Scraping?) Web scraping, also known as web data extraction, is the process of retrieving or “scraping” data from a website. This information is collected and then exported into a format that …

前嗅ForeSpider教程:创建模板

今天&#xff0c;小编为大家带来的教程是&#xff1a;如何在前嗅ForeSpider中创建模板。主要内容有&#xff1a;模板的概念&#xff0c;模板的配置方式&#xff0c;模板的高级选项&#xff0c;具体内容如下&#xff1a; 一&#xff0c;模板的概念 模板列表的层级相当于网页跳转…

django 性能优化_优化Django管理员

django 性能优化Managing data from the Django administration interface should be fast and easy, especially when we have a lot of data to manage.从Django管理界面管理数据应该快速简便&#xff0c;尤其是当我们要管理大量数据时。 To improve that process and to ma…

3D场景中选取场景中的物体。

杨航最近在学Unity3D&#xfeff;&#xfeff;&#xfeff;&#xfeff;在一些经典的游戏中&#xff0c;需要玩家在一个3D场景中选取场景中的物体。例如《仙剑奇侠传》&#xff0c;选择要攻击的敌人时、为我方角色增加血量、为我方角色添加状态&#xff0c;通常我们使用鼠标来选…

canva怎么使用_使用Canva进行数据可视化项目的4个主要好处

canva怎么使用(Notes: All opinions are my own. I am not affiliated with Canva in any way)(注意&#xff1a;所有观点均为我自己。我与Canva毫无关系) Canva is a very popular design platform that I thought I would never use to create the deliverable for a Data V…