Python函数式编程之面向过程面向对象及函数式简

编辑: admin 分类: python 发布时间: 2021-12-03 来源:互联网
目录
  • Python 函数式编程
  • 同一案例的不同写法,展示函数式编程
    • 面向过程的写法
    • 面向对象的写法
    • 接下来进入正题,函数式编程的落地实现
  • Python 函数式编程的特点
    • 纯函数

      Python 函数式编程

      Python 不是纯粹的函数式语言,但你可以使用 Python 进行函数式编程

      典型的听君一席话,如听一席话,说白了就是 Python 具备函数式编程的特性,

      so,可以借用函数式语言的设计模式和编程技术,把代码写成函数式编程的样子

      一般此时我会吹嘘一下,函数式代码比较简洁和优雅~

      好了,已经吹嘘完了。

      以上内容都属于讲道理的范围,那在 Python 中有哪些适合函数式编程的技能点

      又有哪些不适的点呢?

      下述 2 点先有个印象就行

      优点:生成器表达式,这个后面咱会反复提及,具备很多高阶函数,例如 reducemapfilter 三巨头。

      缺点:没有无限递归等~

      如果你去百度 “什么是函数式编程”,很多地方会给出答案

      函数式编程:允许把函数本身作为参数传入另一个函数,还允许返回一个函数。

      有道理!

      其实函数式编程就是在函数中定义表达式和实现表达式的求职,说白了就是用函数落地你的代码。

      看起来好像是废话,它还有一个补充的说明,在函数式编程中要避免状态变化和使用可变对象。

      其中避免状态变化 重点要关注赋值语句以及它如何改变状态,因此你在函数式编程中,不会看到 globalnolocal 等内容。

      同一案例的不同写法,展示函数式编程

      概念与原理都是比较抽象的,咱还是少说概念,这个留到未来你自己总结就好,直接展示源码差异。

      计算 1~100 内,计算 5 与 7 的倍数之和

      面向过程的写法

      count = 0
      for num in range(1, 101):
          if num % 5 == 0 or num % 7 == 0:
              count += num
      print(count)
      

      在面向过程的写法中,逻辑都是从上向下进行运行的,例如 num 从 1 数到 100,如果对 5 或者对 7 取余等于 0,那表示可以整除,然后将 count 与对应的 num 相加,得到最后的余数。

      这种思路是纯面向过程的写法,一般我们学习编程时,首先学会的就是该类写法。

      面向对象的写法

      该类写法有两种,一种是使用 Python 内置的列表实现,一种是自己声明一个类来实现。

      第一种写法:

      count = list()
      for num in range(1, 101):
          if num % 5 == 0 or num % 7 == 0:
              count.append(num)
      print(sum(count))
      

      在上述写法中,变量 count 声明一个 list,即列表对象,但是整理看起来还是有些过程式编程语言的影子。

      例如最后的 sum(count) 的使用就有些奇怪,看不出来面向对象的影子。

      接下来,咱们创建一个自定义的类,进行逻辑实现。

      class My_List_Sum(list):
          def sum(self):
              count = 0
              for n in self:
                  count += n
              return count
      count = My_List_Sum()
      for num in range(1, 101):
          if num % 5 == 0 or num % 7 == 0:
              count.append(num)
      print(count.sum())
      

      上述代码,我们自行实现了一个 My_List_Sum 类,让它继承自 list,此时你应该明白,list 就是一个类名,然后在类的内部实现了 sum 方法,再调用该对象的 sum 方法,完美的应用了面向对象的写法。

      接下来进入正题,函数式编程的落地实现

      在正式编写前,需要回忆一些基础知识,例如 lambda 表达式以及列表相加。

      判断一个数字是 5 或者 7 的倍数, lambda 写法如下:

      multiple = lambda x: x % 5 == 0 or x % 7 == 0
      a = multiple(3) # False
      b = multiple(5) # True
      c = multiple(7) # False
      print(a, b, c)
      

      列表相加代码如下:

      print([1]+[2]) # [1,2]
      

      有了上述内容,可以编写一个递归函数,实现对应的逻辑,代码的说明已经添加到注释中。

      def tool(n: int, end: int, filter_func) -> list:
          """返回一个筛选之后的列表
          :param n: 起始值
          :param end: 终止值
          :param filter_func: 判断表达式
          """
          # 如果到达上限,直接返回空列表
          if n == end: return []
          # 如果满足过滤条件,返回该值与下一个值组成的列表
          if filter_func(n):
              return [n] + tool(n + 1, end, filter_func)
          else:
              # 不满足过滤条件,直接返回下一个值
              return tool(n + 1, end, filter_func)
      # 测试代码
      ret = tool(1, 101, lambda x: x % 5 == 0 or x % 7 == 0)
      print(ret)
      print(sum(ret))
      

      上述代码即为求和的函数式实现,其中部分逻辑如下:

      • 给定初始值与上限值,当迭代的值等于上限值时,返回空列表,即运行结束;
      • 传入一个判断条件,本案例中为一个 lambda 表达式,用于判断 5 和 7 的倍数;
      • 当满足条件时,进行的是相加+迭代工作,当不满足条件时,直接进入下一次迭代。

      当然还有一种函数式编程的写法,代码如下:

      print(sum(n for n in range(1, 101) if n % 5 == 0 or n % 7 == 0))
      

      这里用到的生成器后文会进行说明。

      Python 函数式编程的特点

      在 Python 中,函数即对象,例如声明一个函数之后,你可以调用其属性。

      下述代码展示的即为函数对象的属性,其余内容可以自行再做测试。

      def my_func(var1, var2, **kw):
          return var1 + var2
      print(type(my_func))  # <class 'function'>
      print(my_func.__code__)
      print(my_func.__dict__)
      print(my_func.__code__.co_code)
      print(my_func.__code__.co_filename)
      print(my_func.__code__.co_argcount)
      

      函数式编程之所以高效,其中一个很重要的原因就是延迟计算,也叫做惰性求值,这些在后面都将逐步展开,现在依旧是接收一下印象概念。

      正是因为函数即对象,所有才有本文开篇那段对函数式编程的定义。

      函数可以使用其它函数作为参数,或者返回另一个函数,所以在实际编码过程中,我们将会把函数转换成其它代码中的 “对象”,从而实现函数式编程。

      接下来咱们要接触一下 Python 中的纯函数概念以及应用。

      纯函数

      纯函数是一个概念,也就是让函数不会对函数外作用域产生影响,即作用域为本地。

      说简单点,就是在函数内部避免赋值操作,当然类似 global 等关键字也避免使用。

      针对此,lambda 表达式就是纯函数。

      首先查看一个纯函数的例子:

      def my_func(num: int) -> int:
          return num * 100
      

      上述代码中函数的返回值仅与 num 有关,满足下面两个条件:

      • 没有改变全局变量;
      • 没有更新可变数据结构,例如列表,字典。

      接触完毕纯函数概念之后,下面了解一下函数作为对象的落地应用。

      在 Python 中声明一个类,默认会携带部分内置的方法,例如:

      from typing import Callable
      # 声明一个类,该类无意义,仅测试使用
      class Ext:
          # 传入的函数,可携带1~2个参数
          def __init__(self, test_demo: Callable[[int], int]) -> None:
              self.func = test_demo
          # 返回结果扩大2倍
          def __call__(self, arg: int) -> int:
              return self.func(arg) * 2
      def one_func(var):
          return var + 1
      def two_func(var):
          return var * 3
      def three_func(var):
          return var
      a = Ext(one_func)
      print(a(3))  # 8
      b = Ext(two_func)
      print(b(3))  # 18
      c = Ext(three_func)
      print(c(3))  # 6
      

      上述代码使用了一个新的模块 typing,该模块是 Python 3.5 之后新增的模块,主要为 Python 提供静态类型的检查 。

      本案例中导入的是回调函数 Callable,格式如下:

      Callable[[Arg1Type, Arg2Type],ReturnType]
      

      其中内部中括号 Arg1Type 是参数类型,ReturnType 为返回值类型。

      上述三个函数的签名都与 Callable 定义的一致,所以都可以作为 test_demo 参数的值去传递。

      以上就是Python函数式编程之面向过程面向对象及函数式简析的详细内容,更多关于Python函数式编程面向过程面向对象及函数式的资料请关注hwidc其它相关文章!

      【本文由:http://www.1234xp.com/cdn.html 提供,感谢支持】