在开始介绍函数之前,请大家回顾一下之前的两篇教程:多多教Python:Python 基本功: 5. 数据序列化zhuanlan.zhihu.com多多教Python:Python 基本功: 6. 第一个完整的程序zhuanlan.zhihu.com
在跟着上面两篇教程完成了第一个完整的程序,并且成功运行之后,现在我们来开始真正的学习 Python 这一门语言。计算机语言是一门艺术,而 Python 的艺术魅力从函数(Function) 开始展开。
教程需求:Mac OS (Windows, Linux 会略有不同)
安装了 Python 3.0 版本以上, PyCharm
函数 Function
首先介绍一下什么是Python中的函数,其实很简单,看一段代码就明白了:一个 python 函数 fun
一个 Python 函数有以下元素,和上图代码一一对应:Define (定义): 第一行 def 关键词就是用来定义一个函数的名字,名字叫 "fun"。
Parameters (参数): a, b 是函数的两个参数。
Scope (范围): 实现函数具体内容的区间,在第一行的冒号 ":" 之后开始,以 return 结束。
Description (介绍): 这个是可有可无的,具体的对函数的介绍,之后会详细讲到如何写。
Implementation (实现): 这是函数具体做的事情,在上图就是第8,9行,函数把a, b两个参数相加,并且回复。
Return (回复): 函数结束之后回复的内容,可以不回复,默认回复 None。
Python 函数还有其他元素,当然在基础篇里了解这几个就足够了。那为什么我们需要函数,而不是直接实现其内部的方法呢?比较下面:
c = a + b
同样的把两个数值相加,不用函数可以一行写完,但是用了函数却要9行,显得很麻烦。但是我们来看下面这个例子:
def fun(a, b):
if a + b == 0:
return 0
else:
return a * (a - b) / (a + b)
c = fun(1, -1) + fun(10, -9)
这里函数做的事情是先比较 a+b 是不是等于0,如果等于0回复0,否则回复一个复杂的计算。这里虽然我们还没有讲到 Python 的逻辑方法,但是 if...else... 语句我相信还是很明了的。这里的函数做的事情是把一个比较冗长的事情囊括起来,然后提供了一个简明的界面(Interface) 来传入参数并且支持反复调用。不过记得如果要调用一个函数,这个函数需要在调用之前已经被定义并且实现。这句话可能现在难以理解,不需要担心,在之后的关于 抽象函数 (Abstract Function) 就会再次讲解。
函数还是变量?
函数可以是变量,但是只有函数可以被调用,而变量不可以,但是变量可以索引 (之后会讲到):
( )
[ ]
现在我们来看之前学过的字典,参考多多教Python:Python 基本功: 3. 数据类型 和这里新学的函数做一个比较:
def fun_abc(date):
return len(str(date))
fun_dict = {'2019/10/21': 122}
fun_abc('2019/10/21')
fun_dict['2019/10/21']
这里先定义了一个函数 fun_abc, 这个函数数传入的 date 参数在转换成字符串以后有多少个字符,返回的是一个整数。而后创建了一个字典,里面的 Key 是字符串的日期,Value 是价格。在调用函数 fun_abc 的时候,用的是 "( )" 并且传入参数,而字典变量虽然也传入了同样的参数,但是用的是字典的索引 "[ ]"。你可以尝试替换 "( )" 和 “[ ]” ,看看 Python 的报错结果。
函数在定义完了之后,也可以当做一个变量传入另一个函数中。这句话比较绕口,但是我们来举个例子就明白了:
def fun_add(a, b):
return a+b
def fun_subtract(a, b):
return a-b
def fun_non_negative(a, b, operation):
ret = operation(a, b)
return max(0, ret)
c = fun_non_negative(-9, -8, fun_subtract)
# c = ???
这里 c 是多少呢? 答案是 0,现在我们来解释一下:一开始,我们定义了一个加法函数, fun_add,比较简单。
随后,我们定义了一个减法函数,fun_subtract, 同样也不复杂。
然后我们定义了一个新的函数, non negative 的意思是没有负数。这个函数传入三个参数,第一第二个是数值,第三个是一个可以通过 "()" 调用的函数,函数内部的第一行就是通过 "()" 传入了a, b 两个参数。整个函数做的事情就是先对a, b 进行运算,然后在回复之前确保数值是大于0的,否则回复0。
给 __main__ 添加函数
现在我们回到上一个教程,多多教Python:Python 基本功: 6. 第一个完整的程序, 在写完的第一个程序里利用函数把核心逻辑囊括起来,看看是否在程序结构上显得更加清晰:
# file: intro_to_function.py
# author: DDTeachPython
from datetime import datetime
import json
import sys
def report_daily_price(ticker, input_file, report_date=""):
"""汇报每日价格:param ticker: 股票符号:param input_file: 读取文件:param report_date: 汇报日期:return: ret_dict: 回复一个字典数据"""
ret_dict = dict()
with open(input_file, 'r') as file_to_read:
for line in file_to_read.readlines():
# 逗号是分隔符,Delimiter
date_str, price_str = line.split(',')
# 读取的字符串,转换成对应的数据类型
dt = datetime.strptime(date_str, '%m/%d/%Y')
price = float(price_str)
# 数据存入字典,以之后调用
ret_dict[dt] = price
# 计算高低价格,回报率
max_price = max(ret_dict.values())
min_price = min(ret_dict.values())
ret_pcnt = (ret_dict[datetime(2019, 7, 18)] - ret_dict[datetime(2019, 7, 10)]) / ret_dict[datetime(2019, 7, 18)]
# 创建报告字典
output_dict = dict()
output_dict['Title'] = ticker + " Price Report"
output_dict['Max Price'] = str(max_price)
output_dict['Min Price'] = str(min_price)
output_dict['Return %'] = "{:.2f}".format(ret_pcnt * 100) + "%"
# 写入文件
report_file = ticker + '_report' + "_" + report_date + '.json'
with open(report_file, 'w') as file_to_write:
json.dump(output_dict, file_to_write)
return ret_dict
if __name__ == '__main__':
# 报告文件名
if len(sys.argv) > 1:
report_date = sys.argv[1]
else:
report_date = ""
abc_file = 'abc_date_price.txt'
abc_dict = report_daily_price(ticker='ABC', input_file=abc_file, report_date=report_date)
print(abc_dict)
这里大部分代码逻辑和前文是一样的,只是创建了一个新的函数,然后把逻辑搬到了函数内部。这里的函数 report daily price 里的第三个参数有一个默认数值为空 report_date=""。意思是如果在运行程序的时候参入的参数为空,那么函数就会默认给 report_date 一个空的字符串。在 PyCharm 里运行程序的时候,通过下面这个方法传入参数:PyCharm 传入参数
点右上方的 intro_to_python 的文件名,然后下拉 edit configuration, 进入之后在红框中的 Parameters 栏里填上传入的日期,就可以在每次运行的时候传入这个参数。
虽然这么操作并没有优化处理数据的方式,而且大部分代码只是转移到了函数内部。但是在大多数 Python 程序中,进入 main() 之后会有6大步骤 (见下图),而通过把核心逻辑函数区分开定义,你就可以更加专注于定义不同的核心逻辑上面,然后在 main() 函数里替换调用就可以了。函数的一个很大的好处就是不用重复写核心逻辑代码
小结
虽然 Python 本身不是函数式编程 (Functional Programming), 但是Python 的函数用得好可以非常6。这里函数只是简单的介绍了一下,还有很多深入的概念将在之后的教程中提到,有兴趣的小伙伴可以先去外部链接学习一下:
外部的一篇教程,里面例子比较多:菜鸟 Python 函数www.runoob.com
抽象函数的细节,比较深入:abc - Abstract Base Classes - Python 3.8.0 documentationdocs.python.org