Look, this "function" is called python

osc_4yp05nbl 2020-11-09 13:44:10
look function python

Python The actual combat community

Java The actual combat community

Long press to identify the QR code below , Add as needed

Scan code, pay attention to add customer service

Into the Python community ▲

Scan code, pay attention to add customer service

Into the Java community

In machine learning , We often need to use classes and functions to define parts of the model , For example, define a function to read data 、 Functions that preprocess data 、 Model architecture and training process functions and so on . So what kind of function is beautiful 、 What about the nice code ? In this paper ,Jeff Knupp This paper discusses how to develop wonderful functions from naming to code amount .

Like most modern programming languages , stay Python in , Function is one of the basic methods of abstraction and encapsulation . You may have written hundreds of functions at the development stage , But not every function is created equal . Write 「 Perishing 」 Functions directly affect the readability and maintainability of the code . that , What kind of function is 「 Perishing 」 Function? ? what's more , How to write 「 well 」 Function? ?

Brief review

Mathematics is full of functions , Although we may not remember them . First of all, let's recall our favorite topic —— Differential and integral calculus . You may remember this equation :f(x) = 2x + 3. This one is called 「f」 Function of , There is an unknown number x,「 return 」2*x+3. This function may be related to us in Python It's not the same , But its basic idea is the same as the function in computer language .

Function has a long history in mathematics , But in computer science, it's more magical . For all that , There are still some defects in the function . Next we'll talk about what is 「 well 」 function , And what kind of symptoms do we need to refactor the function .

The key to a function is

well Python Function and lameness Python What is the difference between functions ?「 good 」 It's amazing how many functions are defined . For our purposes , I'll take care of it Python Functions are defined as functions that conform to most of the rules in the following listing ( Some are more difficult to implement ):

  • The name is reasonable

  • With a single function

  • Include document comments

  • Returns a value

  • Code no more than 50 That's ok

  • idempotent , As pure as possible

For many people , This list may be a little too strict . But I promise , If your function follows these rules , Your code will look beautiful . I'll explain the rules step by step , Then sum up how these rules make up a 「 good 」 function .


On this question , One of my favorite words ( come from Phil Karlton, Always be mistaken for Donald Knuth Yes ) yes :

There are only two problems in computer science : Cache invalidation and naming problems .

It sounds a little weird , But the whole nice naming is really hard . Here's a bad function name :

def get_knn(from_df):

I've seen bad naming almost everywhere , But this example comes from data science ( Or say , machine learning ), Practitioners are always in Jupyter notebook Write the code , And then try to turn those different units into an understandable program .

The first problem with naming this function is the use of acronyms / Abbreviations . Compared with acronyms and less popular acronyms , Complete English words will be better . The only reason to use abbreviations is to save typing time , But modern editors have automatic completion function , So you just type in your full name once . The reason why abbreviations are a problem , It's because they're usually used only in specific areas . In the code above ,knn Refer to 「K-Nearest Neighbors」,df refer to 「DataFrame」—— omnipresent Pandas data structure . If another programmer who is not familiar with these abbreviations is reading the code , that TA You'll be confused .

About the function name , There are two other small problems : word 「get」 Be of no great importance . For most well named functions , Obviously, the function will return something , Its name will reflect that .from_df It's also unnecessary . If the name description of the parameter is not clear enough , The function's document comment or type comment will describe the parameter type .

So how do we rename this function ? for example :

def k_nearest_neighbors(dataframe):

Now? , Even the layman knows what this function is calculating , Name of parameter (dataframe) It also clearly tells us what kind of parameters we should pass .

Single function principle

「 Single function principle 」 come from Bob Martin「 uncle 」 A Book of , Not only for classes and modules , The same applies to functions (Martin The original goal ). The principle emphasizes , Functions should have 「 A single function 」. in other words , A function should do only one thing . A big reason for this is : If each function does only one thing , So only if the way a function does that has to change , This function needs to be changed . When a function can be deleted , It's easy : If something else changes , The single function of this function is no longer needed , So just delete it .

Take an example to explain . Here's more than one 「 things 」 Function of :

def calculate_and print_stats(list_of_numbers):
 sum = sum(list_of_numbers) 
 mean = statistics.mean(list_of_numbers) 
 median = statistics.median(list_of_numbers) 
 mode = statistics.mode(list_of_numbers) 
 print('SUM: {}'.format(sum) print('MEAN: {}'.format(mean)
 print('MEDIAN: {}'.format(median) 
 print('MODE: {}'.format(mode)

This function does two things : Calculate a set of statistics about a list of numbers , And print them to STDOUT. This function violates the principle that only one reason can make a function change . There are obviously two reasons why this function can change : New or different data needs to be calculated or the format of output needs to be changed . It's best to write the function as two independent functions : One is used to execute and return the calculation result ; The other is used to receive the results and print them out . A fatal flaw in a function's versatility is that the function name contains the word 「and」

This separation can also simplify testing for function behavior , And they are not only separated into two functions in a module , It may also exist in different modules where appropriate . This makes the test Cleaner 、 Easier maintenance .

Functions that do only two things are very rare . More often, a function is responsible for many, many tasks . Again , For readability 、 For testability , We should put these 「 Versatile 」 Functions are divided into small functions , Each small function is responsible for only one task .

Documentation Comments

quite a lot Python Developers know that PEP-8, It defines the Python Programming style guide , But very few people know what defines the style of document annotation PEP-257. I'm not going to go into detail here PEP-257, Readers can read the document annotation style stipulated in the guide in detail .

  • PEP-8:https://www.python.org/dev/peps/pep-0008/

  • PEP-257:https://www.python.org/dev/peps/pep-0257/

First of all, document annotations are defining modules 、 function 、 The first string declaration of a class or method , This string should describe the function clearly 、 Input parameters and return parameters, etc .PEP-257 The main information is as follows :

  • Each function needs a document description ;

  • Use proper grammar and punctuation , Write complete sentences ;

  • At the beginning, we need to summarize the main function of the function in one sentence ;

  • Use prescriptive language instead of descriptive language .

When writing a function , It's easy to follow these rules . We just need to get into the habit of writing documentation notes , And finish them before actually writing the function body . If you can't clearly describe what this function does , So you need to think more about why you write this function .

Return value

Function can and should be treated as a separate applet . They take some input in the form of parameters , And return some output values . Of course , Parameters are optional , But from Python In terms of internal mechanism , The return value is not optional . Even if you try to create a function that doesn't return a value , We also cannot choose not to use return values internally , because Python The interpreter of will force a return of None. Unbelievable readers can test it with the following code :

* python3
Python 3.7.0 (default, Jul 23 201820:22:55)
[Clang 9.1.0 (clang-902.0.39.2)] on darwin
Type "help""copyright""credits" or "license" *for *more information.
>>def add(a, b):
... print(a + b)
>>> b = add(12)
>>> b
>>> b is None

Run the above code , You'll see b The value of is really None. So even if we write one that doesn't contain return Function of statement , It still returns something . But functions should also return something , Because it's also a small program . How much use will a program without output , How do we test it ?

I would even like to make the following statement : Every function should return a useful value , Even if this value can only be used to test . The code we write should need to be tested , It's hard to test a function without a return value , The above function may require redirection I/O To get the test . Besides , The return value can change the method call , The following code shows this concept :

with open('foo.txt''r'as input_file:
 for line in input_file:
 if line.strip().lower().endswith('cat'):
 # ... do something useful with these lines

Lines of code if line.strip().lower().endswith('cat') Be able to function , Because string methods (strip(), lower(), endswith()) Will return a string as a result of the call function .

Here are some common reasons people give when asked why they write functions that don't return values :

「 What the function does is similar to I/O The operation of , For example, saving a value to a database , This function does not return useful output .」

I don't agree with that , Because when the operation is successfully completed , The function can return True.

「 I need to return multiple values , Because returning only one value doesn't represent anything .」

Of course, you can also return a tuple containing multiple values . In short , Even in the existing code base , It must be a good idea to return a value from a function , And it's unlikely to destroy anything .

Function length

The length of the function directly affects the readability , This will affect maintainability . So make sure your function is short enough .50 The line function is a reasonable length for me .

If the function follows the single function principle , Generally speaking, its length will be very short . If the function is pure or idempotent ( We'll talk about ), It will also be shorter in length . These ideas are very helpful for building concise code .

So what if a function is too long ? Code refactoring (refactor)! Code refactoring is probably what you've been doing when you write code , Even if you're not familiar with the term . It means : Changing the structure of a program without changing its behavior . So extracting a few lines of code from a long function and converting it to a function belonging to that function is also a kind of code refactoring . This is also the fastest and most common way to shorten long functions . As long as these new functions are properly named , The code will become easier to read .

Idempotency and function purity

Idempotent function (idempotent function) Given the same set of variable parameters, the same value is returned , No matter how many times it's called . The result of a function does not depend on nonlocal variables 、 The variability of the parameters or from any I/O Stream data . Following add_three(number) Functions are idempotent :

def add_three(number):
 """Return *number* + 3."""
 return number + 3

Whenever called add_three(7), Its return values are all 10. Here is an example of a non idempotent function :

def add_three():
 """Return 3 + the number entered by the user."""
 number = int(input('Enter a number: '))
 return number + 3

This function is not idempotent , Because the return value of a function depends on I/O, That is, the number entered by the user . Every time this function is called , It can all return different values . If it's called twice , Then the user can enter... For the first time 3, Second input 7, Make right add_three() The call to return 6 and 10.

Why idempotent is important ?

Testability and maintainability . Idempotent functions are easy to test , Because they return the same result with the same parameters . Testing is to check whether the values returned by different calls to a function are as expected . Besides , Testing idempotent functions is quick , This is in unit testing (Unit Testing) It's very important , But it's often overlooked . It's also very simple to reconstruct idempotent functions . No matter how you change the code outside the function , The values returned by calling a function with the same parameters are the same .

What is? 「 pure 」 function ?

In functional programming , If the function is idempotent and has no obvious side effects (side effect), Then it's a pure function . remember , An idempotent function means that it always returns the same result for a given set of parameters , No external factors can be used to calculate the result . however , This does not mean that idempotent functions cannot affect nonlocal variables (non-local variable) or I/O stream etc. . for example , If add_three(number) The idempotent version of outputs the result before returning it , It's still idempotent , Because it visited I/O stream, This does not affect the return value of the function . call print() It's a side effect : In addition to the return value , Interaction with the rest of a program or system .

Let's expand add_three(number) This example . We can use the following code snippet to see add_three(number) Number of times the function was called :

add_three_calls = 0
def add_three(number):
 """Return *number* + 3."""
 global add_three_calls
 print(f'Returning {number + 3}')
 add_three_calls += 1
 return number + 3
def num_calls():
 """Return the number of times *add_three* was called."""
 return add_three_calls

Now we output the results to the console ( One side effect ), And modify the nonlocal variable ( Another side effect ), But because these side effects don't affect the return value of the function , So the function is still idempotent .

Pure functions have no side effects . It doesn't just use any 「 External data 」 To calculate the value , It's not about the system / Other parts of the program interact , In addition to calculating and returning values . therefore , Despite our new definition of add_three(number) It's still idempotent , But it's no longer a pure function .

Pure functions do not record statements or print() call , No database or Internet connection , Do not access or modify nonlocal variables . They don't call any other impure functions .

All in all , Pure functions cannot ( In the context of Computer Science ) Do what Einstein said 「 Ghostly telepresence 」(spooky action at a distance). They don't modify the rest of the program or system in any way . In command programming ( Write Python Code is imperative programming ), They are the safest functions . They are very easy to test and maintain , Even better than pure idempotent functions in this respect . Testing pure functions is almost as fast as executing them . And the test is simple : No database connection or other external resources , There is no requirement to set the code , There's no need to clean up after the test .

obviously , Idempotent and pure functions are the icing on the cake , But it's not necessary . namely , Because of the above advantages , We like to write pure functions or idempotent functions , But it's not always possible to write them . The key lies in , We instinctively want to eliminate side effects and external dependencies when we start deploying code . This makes every line of code we write easier to test , Even if you don't write pure functions or idempotent functions .


The secret of writing good functions is no longer a secret . Just follow some well-established best practices and rules of thumb . I hope this article can help you .

Link to the original text :


 Programmer column   Scan code and pay attention to customer service   Press and hold to recognize the QR code below to enter the group
Recent highlights are recommended :    My girlfriend thinks the annual salary is 50 Ten thousand is the average level , What do I do ?  The sexy goddess of the biggest straight men forum in China overturned  IntelliJ IDEA Fully optimized settings , Efficiency bars !  Very useful Python skill
Here's a good article to share with more people ↓↓

  1. 利用Python爬虫获取招聘网站职位信息
  2. Using Python crawler to obtain job information of recruitment website
  3. Several highly rated Python libraries arrow, jsonpath, psutil and tenacity are recommended
  4. Python装饰器
  5. Python实现LDAP认证
  6. Python decorator
  7. Implementing LDAP authentication with Python
  8. Vscode configures Python development environment!
  9. In Python, how dare you say you can't log module? ️
  10. 我收藏的有关Python的电子书和资料
  11. python 中 lambda的一些tips
  12. python中字典的一些tips
  13. python 用生成器生成斐波那契数列
  14. python脚本转pyc踩了个坑。。。
  15. My collection of e-books and materials about Python
  16. Some tips of lambda in Python
  17. Some tips of dictionary in Python
  18. Using Python generator to generate Fibonacci sequence
  19. The conversion of Python script to PyC stepped on a pit...
  20. Python游戏开发,pygame模块,Python实现扫雷小游戏
  21. Python game development, pyGame module, python implementation of minesweeping games
  22. Python实用工具,email模块,Python实现邮件远程控制自己电脑
  23. Python utility, email module, python realizes mail remote control of its own computer
  24. 毫无头绪的自学Python,你可能连门槛都摸不到!【最佳学习路线】
  25. Python读取二进制文件代码方法解析
  26. Python字典的实现原理
  27. Without a clue, you may not even touch the threshold【 Best learning route]
  28. Parsing method of Python reading binary file code
  29. Implementation principle of Python dictionary
  30. You must know the function of pandas to parse JSON data - JSON_ normalize()
  31. Python实用案例,私人定制,Python自动化生成爱豆专属2021日历
  32. Python practical case, private customization, python automatic generation of Adu exclusive 2021 calendar
  33. 《Python实例》震惊了,用Python这么简单实现了聊天系统的脏话,广告检测
  34. "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system in Python
  35. Convolutional neural network processing sequence for Python deep learning
  36. Python data structure and algorithm (1) -- enum type enum
  37. 超全大厂算法岗百问百答(推荐系统/机器学习/深度学习/C++/Spark/python)
  38. 【Python进阶】你真的明白NumPy中的ndarray吗?
  39. All questions and answers for algorithm posts of super large factories (recommended system / machine learning / deep learning / C + + / spark / Python)
  40. [advanced Python] do you really understand ndarray in numpy?
  41. 【Python进阶】Python进阶专栏栏主自述:不忘初心,砥砺前行
  42. [advanced Python] Python advanced column main readme: never forget the original intention and forge ahead
  43. python垃圾回收和缓存管理
  44. java调用Python程序
  45. java调用Python程序
  46. Python常用函数有哪些?Python基础入门课程
  47. Python garbage collection and cache management
  48. Java calling Python program
  49. Java calling Python program
  50. What functions are commonly used in Python? Introduction to Python Basics
  51. Python basic knowledge
  52. Anaconda5.2 安装 Python 库(MySQLdb)的方法
  53. Python实现对脑电数据情绪分析
  54. Anaconda 5.2 method of installing Python Library (mysqldb)
  55. Python implements emotion analysis of EEG data
  56. Master some advanced usage of Python in 30 seconds, which makes others envy it
  57. python爬取百度图片并对图片做一系列处理
  58. Python crawls Baidu pictures and does a series of processing on them
  59. python链接mysql数据库
  60. Python link MySQL database