使用 Python 函数进行模块化

使用 Python 函数来很大程度地减少重复任务编码工作量。 你是否对函数、类、方法、库和模块等花哨的编程术语感到困惑?你是否在与变量作用域斗争?无论你是自学成才的还是经过正式培训的程序员,代码的模块化都会令人困惑。 2019-09-02 10:51:59 Python脚本语言程序员 Redis基本类型及其数据结构 以前在使用Redis的时候,只是简单地使用它提供的基本数据类型和接口,并没有深入研究它底层的数据结构。最近打算重新学习梳理一下Redis方面的知识,所以打算从介绍Redis的基本类型及其数据结构入手。 2019-09-02 09:48:39 Redis数据结构对象 MySQL 进行 Docker 容器化之体验与感悟 Docker 的使用原则是所有容器化的应用程序都应该是无状态的 ,即容器内部只跑业务逻辑,容器应用的所有配置文件、日志文件和持久化数据 都应该挂载到宿主机文件系统,不应该存储在容器内部,以免容器被误删或自身出现问题导致数据丢失。 2019-09-02 09:11:58 MySQLDocker数据 用Cython加速Python代码,速度溜到飞起 如果你曾用Python编写代码,那么你可能花了更多的时间等待某些代码块的执行,而不是你想要的。虽然有一些方法可以使您的代码更有效,但它很可能仍然比C代码慢。这主要归结为Python是一种动态编程语言,并将许多东西移动到C语言编译期间处理的运行时。 2019-09-02 08:58:27 Python编译器编程语言 华为方舟编译器深入解读:已有45款第三方应用 8月31日,华为方舟编译器(OpenArkCompiler)正式开源,官网已上线,源代码包、二进制包已提供下载,相关文档、演示等资料也一应俱全。 2019-09-02 00:06:36 华为开发者开源 除了程序猿,开发人员还是设计师、建筑师…… 编程领域不仅仅关乎代码。许多企业一开始都认为开发人员只需要学习编程语言就可以了。但是,要想让开发人员效率更高,企业还必须了解代码的细微差别及其与编码内容的关系。 2019-09-01 23:48:59 开发代码编程 TensorFlow与PyTorch之争,哪个框架最适合深度学习 谷歌的 Tensorflow 与 Facebook 的 PyTorch 一直是颇受社区欢迎的两种深度学习框架。那么究竟哪种框架最适宜自己手边的深度学习项目呢?本文作者从这两种框架各自的功能效果、优缺点以及安装、版本更新等诸多方面给出了自己的建议。

使用 Python 函数来很大程度地减少重复任务编码工作量。 你是否对函数、类、方法、库和模块等花哨的编程术语感到困惑?你是否在与变量作用域斗争?无论你是自学成才的还是经过正式培训的程序员,代码的模块化都会令人困惑。

你是否对函数、类、方法、库和模块等花哨的编程术语感到困惑?你是否在与变量作用域斗争?无论你是自学成才的还是经过正式培训的程序员,代码的模块化都会令人困惑。但是类和库鼓励模块化代码,因为模块化代码意味着只需构建一个多用途代码块集合,就可以在许多项目中使用它们来减少编码工作量。换句话说,如果你按照本文对 Python 函数的研究,你将找到更聪明的工作方法,这意味着更少的工作。

[[275550]]

本文假定你对 Python 很熟(LCTT 译注:稍微熟悉就可以),并且可以编写和运行一个简单的脚本。如果你还没有使用过 Python,请首先阅读我的文章: Python 简介 。

函数

函数是迈向模块化过程中重要的一步,因为它们是形式化的重复方法。如果在你的程序中,有一个任务需要反复执行,那么你可以将代码放入一个函数中,根据需要随时调用该函数。这样,你只需编写一次代码,就可以随意使用它。

以下一个简单函数的示例:

  1. #!/usr/bin/envpython3
  2. importtime
  3. defTimer():
  4. print("Timeis"+str(time.time()))

创建一个名为 mymodularity 的目录,并将以上函数代码保存为该目录下的 timestamp.py。

除了这个函数,在 mymodularity 目录中创建一个名为 __init__.py 的文件,你可以在文件管理器或 bash shell 中执行此操作:

  1. $touchmymodularity/__init__.py

现在,你已经创建了属于你自己的 Python 库(Python 中称为“模块”),名为 mymodularity。它不是一个特别有用的模块,因为它所做的只是导入 time 模块并打印一个时间戳,但这只是一个开始。

要使用你的函数,像对待任何其他 Python 模块一样对待它。以下是一个小应用,它使用你的 mymodularity 软件包来测试 Python sleep() 函数的准确性。将此文件保存为 sleeptest.py,注意要在 mymodularity 文件夹 之外,因为如果你将它保存在 mymodularity 里面,那么它将成为你的包中的一个模块,你肯定不希望这样。

  1. #!/usr/bin/envpython3
  2. importtime
  3. frommymodularityimporttimestamp
  4. print("TestingPythonsleep()...")
  5. #modularity
  6. timestamp.Timer()
  7. time.sleep(3)
  8. timestamp.Timer()

在这个简单的脚本中,你从 mymodularity 包中调用 timestamp 模块两次。从包中导入模块时,通常的语法是从包中导入你所需的模块,然后使用 模块名称 + 一个点 + 要调用的函数名(例如 timestamp.Timer())。

你调用了两次 Timer() 函数,所以如果你的 timestamp 模块比这个简单的例子复杂些,那么你将节省大量重复代码。

保存文件并运行:

  1. $python3./sleeptest.py
  2. TestingPythonsleep()...
  3. Timeis1560711266.1526039
  4. Timeis1560711269.1557732

根据测试,Python 中的 sleep 函数非常准确:在三秒钟等待之后,时间戳成功且正确地增加了 3,在微秒单位上差距很小。

Python 库的结构看起来可能令人困惑,但其实它并不是什么魔法。Python 被编程 为一个包含 Python 代码的目录,并附带一个 __init__.py 文件,那么这个目录就会被当作一个包,并且 Python 会首先在当前目录中查找可用模块。这就是为什么语句 from mymodularity import timestamp 有效的原因:Python 在当前目录查找名为 mymodularity 的目录,然后查找 timestamp.py 文件。

你在这个例子中所做的功能和以下这个非模块化的版本是一样的:

  1. #!/usr/bin/envpython3
  2. importtime
  3. frommymodularityimporttimestamp
  4. print("TestingPythonsleep()...")
  5. #nomodularity
  6. print("Timeis"+str(time.time()))
  7. time.sleep(3)
  8. print("Timeis"+str(time.time()))

对于这样一个简单的例子,其实没有必要以这种方式编写测试,但是对于编写自己的模块来说,优秀的实践是你的代码是通用的,可以将它重用于其他项目。

通过在调用函数时传递信息,可以使代码更通用。例如,假设你想要使用模块来测试的不是 系统 的 sleep 函数,而是 用户自己实现 的 sleep 函数,更改 timestamp 代码,使它接受一个名为 msg 的传入变量,它将是一个字符串,控制每次调用 timestamp 时如何显示:

  1. #!/usr/bin/envpython3
  2. importtime
  3. #更新代码
  4. defTimer(msg):
  5. print(str(msg)+str(time.time()))

现在函数比以前更抽象了。它仍会打印时间戳,但是它为用户打印的内容 msg 还是未定义的。这意味着你需要在调用函数时定义它。

Timer 函数接受的 msg 参数是随便命名的,你可以使用参数 m、message 或 text,或是任何对你来说有意义的名称。重要的是,当调用 timestamp.Timer 函数时,它接收一个文本作为其输入,将接收到的任何内容放入 msg 变量中,并使用该变量完成任务。

以下是一个测试测试用户正确感知时间流逝能力的新程序:

  1. #!/usr/bin/envpython3
  2. frommymodularityimporttimestamp
  3. print("PresstheRETURNkey.Countto3,andpressRETURNagain.")
  4. input()
  5. timestamp.Timer("Startedtimerat")
  6. print("Countto3...")
  7. input()
  8. timestamp.Timer("Yousleptuntil")

将你的新程序保存为 response.py,运行它:

  1. $python3./response.py
  2. PresstheRETURNkey.Countto3,andpressRETURNagain.
  3. Startedtimerat1560714482.3772075
  4. Countto3...
  5. Yousleptuntil1560714484.1628013

函数和所需参数

新版本的 timestamp 模块现在 需要 一个 msg 参数。这很重要,因为你的第一个应用程序将无法运行,因为它没有将字符串传递给 timestamp.Timer 函数:

  1. $python3./sleeptest.py
  2. TestingPythonsleep()...
  3. Traceback(mostrecentcalllast):
  4. File"./sleeptest.py",line8,in<module>
  5. timestamp.Timer()
  6. TypeError:Timer()missing1requiredpositionalargument:'msg'

你能修复你的 sleeptest.py 应用程序,以便它能够与更新后的模块一起正确运行吗?

变量和函数

通过设计,函数限制了变量的范围。换句话说,如果在函数内创建一个变量,那么这个变量 只 在这个函数内起作用。如果你尝试在函数外部使用函数内部出现的变量,就会发生错误。

下面是对 response.py 应用程序的修改,尝试从 timestamp.Timer() 函数外部打印 msg 变量:

  1. #!/usr/bin/envpython3
  2. frommymodularityimporttimestamp
  3. print("PresstheRETURNkey.Countto3,andpressRETURNagain.")
  4. input()
  5. timestamp.Timer("Startedtimerat")
  6. print("Countto3...")
  7. input()
  8. timestamp.Timer("Yousleptfor")
  9. print(msg)

试着运行它,查看错误:

  1. $python3./response.py
  2. PresstheRETURNkey.Countto3,andpressRETURNagain.
  3. Startedtimerat1560719527.7862902
  4. Countto3...
  5. Yousleptfor1560719528.135406
  6. Traceback(mostrecentcalllast):
  7. File"./response.py",line15,in<module>
  8. print(msg)
  9. NameError:name'msg'isnotdefined

应用程序返回一个 NameError 消息,因为没有定义 msg。这看起来令人困惑,因为你编写的代码定义了 msg,但你对代码的了解比 Python 更深入。调用函数的代码,不管函数是出现在同一个文件中,还是打包为模块,都不知道函数内部发生了什么。一个函数独立地执行它的计算,并返回你想要它返回的内容。这其中所涉及的任何变量都只是 本地的:它们只存在于函数中,并且只存在于函数完成其目的所需时间内。

Return 语句

如果你的应用程序需要函数中特定包含的信息,那么使用 return 语句让函数在运行后返回有意义的数据。

时间就是金钱,所以修改 timestamp 函数,以使其用于一个虚构的收费系统:

  1. #!/usr/bin/envpython3
  2. importtime
  3. defTimer(msg):
  4. print(str(msg)+str(time.time()))
  5. charge=.02
  6. returncharge

现在,timestamp 模块每次调用都收费 2 美分,但最重要的是,它返回每次调用时所收取的金额。

以下一个如何使用 return 语句的演示:

  1. #!/usr/bin/envpython3
  2. frommymodularityimporttimestamp
  3. print("PressRETURNforthetime(costs2cents).")
  4. print("PressQRETURNtoquit.")
  5. total=0
  6. whileTrue:
  7. kbd=input()
  8. ifkbd.lower()=="q":
  9. print("Youowe$"+str(total))
  10. exit()
  11. else:
  12. charge=timestamp.Timer("Timeis")
  13. total=total+charge

在这个示例代码中,变量 charge 为 timestamp.Timer() 函数的返回,它接收函数返回的任何内容。在本例中,函数返回一个数字,因此使用一个名为 total 的新变量来跟踪已经进行了多少更改。当应用程序收到要退出的信号时,它会打印总花费:

  1. $python3./charge.py
  2. PressRETURNforthetime(costs2cents).
  3. PressQRETURNtoquit.
  4. Timeis1560722430.345412
  5. Timeis1560722430.933996
  6. Timeis1560722434.6027434
  7. Timeis1560722438.612629
  8. Timeis1560722439.3649364
  9. q
  10. Youowe$0.1

内联函数

函数不必在单独的文件中创建。如果你只是针对一个任务编写一个简短的脚本,那么在同一个文件中编写函数可能更有意义。唯一的区别是你不必导入自己的模块,但函数的工作方式是一样的。以下是时间测试应用程序的最新迭代:

  1. #!/usr/bin/envpython3
  2. importtime
  3. total=0
  4. defTimer(msg):
  5. print(str(msg)+str(time.time()))
  6. charge=.02
  7. returncharge
  8. print("PressRETURNforthetime(costs2cents).")
  9. print("PressQRETURNtoquit.")
  10. whileTrue:
  11. kbd=input()
  12. ifkbd.lower()=="q":
  13. print("Youowe$"+str(total))
  14. exit()
  15. else:
  16. charge=Timer("Timeis")
  17. total=total+charge

它没有外部依赖(Python 发行版中包含 time 模块),产生与模块化版本相同的结果。它的优点是一切都位于一个文件中,缺点是你不能在其他脚本中使用 Timer() 函数,除非你手动复制和粘贴它。

全局变量

在函数外部创建的变量没有限制作用域,因此它被视为 全局 变量。

全局变量的一个例子是在 charge.py 中用于跟踪当前花费的 total 变量。total 是在函数之外创建的,因此它绑定到应用程序而不是特定函数。

应用程序中的函数可以访问全局变量,但要将变量传入导入的模块,你必须像发送 msg 变量一样将变量传入模块。

全局变量很方便,因为它们似乎随时随地都可用,但也很难跟踪它们,很难知道哪些变量不再需要了但是仍然在系统内存中停留(尽管 Python 有非常好的垃圾收集机制)。

但是,全局变量很重要,因为不是所有的变量都可以是函数或类的本地变量。现在你知道了如何向函数传入变量并获得返回,事情就变得容易了。

总结

你已经学到了很多关于函数的知识,所以开始将它们放入你的脚本中 —— 如果它不是作为单独的模块,那么作为代码块,你不必在一个脚本中编写多次。在本系列的下一篇文章中,我将介绍 Python 类。

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月5日 07:48
下一篇 2023年5月5日 07:48

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信