一览函数式编程

文章目录

    • 一、 什么是函数式编程
      • 1.1 编程范式
        • 1.1.1 命令式编程(Imperative Programming)范式
        • 1.1.2 声明式编程(Declarative Programming)范式
        • 1.1.3 函数式编程(Functional Programming)范式
        • 1.1.4 面向对象编程(Object-Oriented Programming)范式
        • 1.1.5 元编程(Metaprogramming)范式
      • 1.2 数学函数
      • 1.3 函数是一等公民(Functions are first-class citizens)
        • 1.3.1 函数可以被赋值给变量或者数据结构中的元素
        • 1.3.2 函数可以作为参数传递给其他函数
        • 1.3.3 函数可以作为其他函数的返回值
        • 1.3.4 函数可以在运行时动态创建和定义
      • 1.4 不可变性(immutability)和无副作用
    • 二、函数式编程的基础
      • 2.1 纯函数(pure function)
      • 2.2 闭包(closure)
      • 2.3 Lambda
      • 2.4 高阶函数
      • 2.5 偏函数(Partial)
      • 2.6 柯里化(Currying)
        • 柯里化转换
        • 优势
    • 三、函数式编程的进阶
      • 3.1 函数组合(composition)
      • 3.2 Pipeline
      • 3.3 PointFree
      • 3.4 惰性求值(Lazy evaluation)
      • 3.5 尾递归(Tail recursion)
      • 3.6 MapReduce
        • 3.6.1 多线程
    • 四、总结
      • 4.1 优缺点
        • 4.1.1 优点
        • 4.1.2 缺点

一、 什么是函数式编程

函数式编程是一种编程范式,它将计算视为数学函数的求值过程。在函数式编程中,函数是一等公民,可以像其他值一样被传递、组合和操作。函数式编程强调不可变性和无副作用,即函数的执行不会改变程序状态或外部环境。这使得函数式编程更容易进行推理和测试,并且可以更好地支持并发和并行计算。

1.1 编程范式

编程范式是一种编程思想或方法,它定义了如何组织和结构化计算机程序。不同的编程范式有不同的方法和规则,以解决不同类型的问题。
同一门语言,同一个问题,来看一下不同的范式,会写出什么样的代码

问题:计算一个整数数组中所有元素的平均值。

1.1.1 命令式编程(Imperative Programming)范式

命令式编程范式是一种基于语句的编程范式,它通过一系列指令来改变程序状态。在命令式编程中,程序员需要指定每个步骤的操作,以便计算出所需的结果。

img

1.1.2 声明式编程(Declarative Programming)范式

声明式编程范式是一种基于表达式的编程范式,它通过表达式来描述计算机程序的行为。在声明式编程中,程序员只需要描述所需的结果,而不需要指定每个步骤的操作。

img

1.1.3 函数式编程(Functional Programming)范式

函数式编程范式是一种基于函数的编程范式,它将计算机程序视为一系列函数的组合。在函数式编程中,程序员只需要定义函数的输入和输出,而不需要指定每个步骤的操作。

img

1.1.4 面向对象编程(Object-Oriented Programming)范式

面向对象编程范式是一种基于对象的编程范式,它将计算机程序视为一组相互作用的对象。在面向对象编程中,程序员定义对象的属性和方法,并使用这些对象来执行计算机程序的操作。

img

1.1.5 元编程(Metaprogramming)范式

元编程范式是一种编程范式,它允许程序员在运行时创建、修改和操作程序的结构和行为。元编程范式的目的是使程序更加灵活和可扩展,因为它允许程序在运行时自我修改和适应。

img

1.2 数学函数

假设有一个数学函数 f(x) = x^2,它将一个数 x 映射到它的平方。在函数式编程中,我们可以定义一个函数 square(x),它也将一个数 x 映射到它的平方。这个函数可以用如下的方式定义:

img

这个函数与数学中的函数 f(x) = x^2 有很多相似之处。它们都将一个输入映射到一个输出,而且输出只取决于输入,不会受到外部状态的影响。在函数式编程中,我们也可以将这个函数作为另一个函数的参数,或者将它的输出作为另一个函数的输入,这也是函数式编程中常见的操作。

另外,函数式编程中的函数也具有不可变性和纯函数性质。这意味着函数的输出只取决于输入,不会受到外部状态的影响。例如,如果我们调用 square(2) 函数,它的输出始终为 4,不会受到任何外部状态的影响。这与数学中的函数也有很多相似之处,因为数学中的函数的输出也只取决于输入,不会受到外部环境的影响。

1.3 函数是一等公民(Functions are first-class citizens)

是指在编程语言中,函数可以像其他数据类型一样被传递、赋值、作为参数和返回值使用。
具体来说,函数作为一等公民具有以下特点:

1.3.1 函数可以被赋值给变量或者数据结构中的元素

img

1.3.2 函数可以作为参数传递给其他函数

img

1.3.3 函数可以作为其他函数的返回值

img

1.3.4 函数可以在运行时动态创建和定义

img

1.4 不可变性(immutability)和无副作用

不可变性是指在程序执行过程中,某个对象的状态不会发生改变。在函数式编程中,不可变性是一个重要的概念,因为它可以避免副作用和竞态条件等问题。在不可变性的约束下,函数的执行结果只取决于输入参数,而不会受到外部环境的影响。这使得函数更容易进行推理和测试,并且可以更好地支持并发和并行计算。在实现不可变性时,可以使用一些技术,例如使用不可变数据结构、避免共享可变状态、使用纯函数等。

img

反之

img

带来的问题

  1. 副作用:在使用可变性的情况下,我们直接修改了sum_of_numbers变量的值,这可能会导致副作用。副作用是指函数或程序对外部环境产生的影响,例如修改全局变量、打印输出等。副作用可能会使程序更难以理解和调试,因为它们使程序的行为不可预测。
  2. 竞态条件:如果在计算平均值的过程中,有其他线程或进程也在修改sum_of_numbers变量的值,那么可能会导致计算结果不正确。竞态条件是指多个线程或进程同时访问共享资源时,由于访问顺序不确定,导致程序的行为不可预测。
  3. 可读性和可维护性:如果我们在程序的其他地方也使用了sum_of_numbers变量,那么可能会导致代码的可读性和可维护性下降。因为我们不知道sum_of_numbers变量的值是在哪里修改的,也不知道它的值是否正确。

因此,使用可变性来计算平均值可能会带来一些问题。相比之下,使用不可变性可以避免这些问题,使程序更容易理解和调试。

二、函数式编程的基础

2.1 纯函数(pure function)

纯函数是指在相同的输入下,总是返回相同的输出,并且没有任何副作用的函数。具体来说,纯函数满足以下两个条件:

  1. 相同的输入总是返回相同的输出。
  2. 函数执行过程中没有对外部环境产生任何影响,也就是没有副作用。

纯函数的好处在于它们更容易进行测试和调试,因为它们的行为是可预测的。此外,纯函数还可以更容易地进行并行化和优化,因为它们不依赖于外部状态。
例如,下面是一个纯函数的例子:

img

这个函数总是返回相同的输出,而且没有任何副作用。无论何时调用它,它都只是简单地将两个数字相加并返回结果。

Question:这是一个纯函数吗?

img

2.2 闭包(closure)

闭包是指一个函数和它所引用的外部变量的组合。在函数式编程中,闭包通常用于创建高阶函数,这些函数可以接受其他函数作为参数或返回函数作为结果。
闭包可以捕获外部变量的状态,并在函数调用之间保留它。这使得闭包可以实现一些有趣的功能,如记忆化和延迟计算。
例如,以下代码创建了一个闭包,它返回一个函数,该函数可以访问外部变量x:

img

在这个例子中,createAdder函数返回一个函数,该函数可以访问外部变量x。我们可以使用createAdder(5)创建一个新的函数add5,它将5添加到它的参数中。由于add5是一个闭包,它可以记住x的值,并在每次调用时使用它。

2.3 Lambda

Lambda是一种匿名函数,它可以在需要时被创建和调用,而不需要给它们命名。在JavaScript中,Lambda函数可以使用箭头函数语法来定义。

img

2.4 高阶函数

高阶函数是指能够接收一个或多个函数作为参数,并且/或者返回一个新函数的函数。函数是一等公民,因此函数可以像其他值一样被传递和操作。高阶函数是利用这种特性来实现更加灵活和抽象的编程方式。
以下是一些JavaScript中的高阶函数示例:

  1. **Array.prototype.map():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个新数组,其中包含每个元素应用该函数的结果。

img

  1. **Array.prototype.filter():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个新数组,其中包含满足该函数条件的元素。

    img

  2. **Array.prototype.reduce():**接收一个函数作为参数,该函数将应用于数组中的每个元素,并返回一个累加器的值。

    img

  3. 使用多个函数作为参数

img

2.5 偏函数(Partial)

偏函数是指将一个多参数函数转化为一个只有部分参数的函数,即固定函数的一些参数,使得这个新函数只需要传入剩余的参数即可完成调用。这样做的好处是可以简化函数的调用,减少重复代码的编写,提高代码的可读性和可维护性。

img

2.6 柯里化(Currying)

柯里化是一种函数式编程技术,它将一个接受多个参数的函数转换为一系列只接受单个参数的函数。这些单参数函数可以被组合在一起,以便在后续的计算中使用。
例如,假设有一个接受两个参数的函数 add(x, y),我们可以使用柯里化将其转换为一系列只接受一个参数的函数:

img

现在,我们可以使用这些单参数函数来进行计算:

img

这里,我们首先使用 add(1) 创建了一个新的函数 add_1,它只接受一个参数 y,并将其与 1 相加。然后,我们使用 add(2) 创建了另一个新的函数 add_2,它也只接受一个参数 y,并将其与 2 相加。最后,我们使用这些新函数来计算 add_1(3) 和 add_2(3),得到了正确的结果。
柯里化可以使代码更加简洁和可读,同时也可以提高代码的复用性和灵活性。

柯里化转换

下面是一个使用 JavaScript 实现柯里化的函数:

img

这个函数接受一个函数 fn 作为参数,并返回一个新的函数 curried,这个新函数可以接受任意数量的参数,并将它们逐步累积起来,直到收集到足够的参数后再调用原始函数 fn。
具体来说,当 curried 函数接收到的参数数量大于或等于 fn 函数的参数数量时,它会直接调用 fn 函数,并将收集到的参数传递给它。否则,它会返回一个新的函数,这个新函数可以接受更多的参数,并将它们与之前收集到的参数合并起来,然后递归调用 curried 函数,直到收集到足够的参数后再调用 fn 函数。
下面是一个使用 curry 函数实现柯里化的例子:

img

在这个例子中,我们定义了一个接受三个参数的函数 add(x, y, z),然后使用 curry 函数将它转换为一个柯里化函数 curriedAdd。最后,我们使用 curriedAdd 函数来计算 add(1, 2, 3),add(1, 2, 3),add(1, 2, 3) 和 add(1, 2, 3),得到了正确的结果。

优势
  1. 延迟执行:柯里化可以将一个函数的执行延迟到后续的计算中,这样可以避免不必要的计算和资源浪费。例如,在上面的例子中,我们可以先使用 add(1) 和 add(2) 创建两个新函数,然后在需要计算时再传递参数,这样可以避免重复计算和资源浪费。

  2. 函数组合:柯里化可以将多个函数组合在一起,以便在后续的计算中使用。例如,我们可以将多个只接受单个参数的函数组合在一起,形成一个新的函数,这个新函数可以接受多个参数,并将它们依次传递给这些单参数函数,从而得到最终的结果。

    img

柯里化是将一个接受多个参数的函数转换为一系列只接受单个参数的函数,这些单参数函数可以被组合在一起,以便在后续的计算中使用。柯里化的目的是为了提高代码的复用性和灵活性,使得代码更加简洁、可读和灵活。
偏函数是将一个接受多个参数的函数转换为一个接受部分参数的函数,这个部分参数是在转换时就已经确定的。偏函数的目的是为了简化函数调用,避免重复传递相同的参数,提高代码的可读性和可维护性。

三、函数式编程的进阶

3.1 函数组合(composition)

函数组合是一种将多个函数组合在一起以形成新函数的技术,可以帮助我们更好地组织和重用代码。
在函数组合中,我们将一个函数的输出作为另一个函数的输入,以此类推,直到我们得到最终的输出。这种方法可以让我们将多个简单的函数组合成一个更复杂的函数,从而使代码更加模块化和可读性更高。
例如,假设我们有两个函数 f(x) 和 g(x),我们可以将它们组合成一个新函数 h(x) = f(g(x))。这个新函数 h(x) 将先应用 g(x),然后将其结果传递给 f(x)。
函数组合还可以用于构建管道,其中每个函数都是前一个函数的输出。这种方法可以让我们轻松地将多个函数链接在一起,以便在数据流中进行转换和处理。

img

3.2 Pipeline

pipeline 是一种将多个函数组合在一起,形成一个数据处理流程的编程模式。它的核心思想是将数据从一个函数传递到另一个函数,每个函数都对数据进行一些操作,最终得到最终结果。
在函数式编程 pipeline 中,通常会使用一些高阶函数,如 map、filter、reduce 等,来对数据进行处理。这些函数可以接受一个函数作为参数,并将其应用于数据中的每个元素。
下面是一个简单的函数式编程 pipeline 的示例:

img

3.3 PointFree

函数式编程中的 pointfree 是一种编程风格,它的核心思想是尽可能地避免使用命名参数,而是通过组合函数来实现代码的复用和简化。
在 pointfree 风格中,函数的定义不会显式地引用它的参数,而是通过组合其他函数来实现其功能。这种风格的优点在于可以使代码更加简洁、可读性更高,并且可以更容易地进行代码重构和测试。

JavaScript

img

Scala

img

Go

img

3.4 惰性求值(Lazy evaluation)

惰性求值是一种计算策略,它只在需要时才计算表达式的值。这意味着,如果一个表达式的值从未被使用,那么它将永远不会被计算。相反,它只有在需要时才会被计算,这可以节省计算资源和提高程序的效率。
在函数式编程语言中,函数可以作为参数传递给其他函数,也可以从其他函数中返回。惰性求值可以使这些函数更加灵活和高效。只在需要时才计算表达式的值,可以提高程序的效率和灵活性。

img

在这个例子中,lazyAdd 函数返回一个函数,这个函数会在需要时才计算 a + b 的值。当我们调用 lazyAdd(2, 3) 时,它并不会立即计算 2 + 3 的值,而是返回一个函数。当我们调用这个函数时,它才会计算 2 + 3 的值并返回。
这种方式可以避免不必要的计算,提高程序的效率。例如,如果我们有一个很大的数组,我们可以使用惰性求值来避免不必要的遍历:

img

在这个例子中,lazyFilter 函数返回一个生成器函数,这个函数会在需要时才遍历数组并返回符合条件的元素。当我们调用 lazyFilter(arr, x => x % 2 === 0) 时,它并不会立即遍历数组,而是返回一个生成器函数。当我们使用 for…of 循环遍历这个生成器函数时,它才会遍历数组并返回符合条件的元素。这种方式可以避免不必要的遍历,提高程序的效率。

3.5 尾递归(Tail recursion)

递归

img

在这个实现中,递归调用发生在函数的中间,每次递归调用都需要等待下一层递归的返回值才能继续执行。这种形式的递归可能会导致栈溢出等问题,因为每次递归调用都会在栈中创建一个新的帧,如果递归层数太多,就会导致栈溢出。
尾递归
指一个函数在调用自身之后,不再有其他操作需要执行,直接返回结果。这种形式的递归可以被优化为迭代,从而避免栈溢出等问题。
在尾递归中,递归调用发生在函数的最后一步,而且递归调用的返回值直接被当前函数返回,不再进行其他操作。这种形式的递归可以被编译器或解释器优化为迭代,从而避免栈溢出等问题。
例如,下面是一个阶乘函数的尾递归实现:

img

在这个实现中,递归调用发生在函数的最后一步,而且递归调用的返回值直接被当前函数返回,不再进行其他操作。这种形式的递归可以被优化为迭代,从而避免栈溢出等问题。

3.6 MapReduce

在函数式编程中,Map和Reduce是两个常用的高阶函数。Map函数接受一个函数和一个列表作为输入,将该函数应用于列表中的每个元素,并返回一个新的列表。Reduce函数接受一个函数和一个列表作为输入,将该函数应用于列表中的每个元素,并返回一个单一的值。
在MapReduce中,Map函数将数据集分成小块,并将每个块映射到一个键值对。Reduce函数将相同键的所有值组合在一起,并将它们合并成一个单一的值。这个过程可以在分布式计算环境中并行执行,从而加快处理速度。

img

3.6.1 多线程

img

四、总结

4.1 优缺点

4.1.1 优点
  1. 简洁性:函数式编程通常比命令式编程更简洁,因为它们不需要维护状态或副作用。这使得代码更容易理解和维护。
  2. 可读性:函数式编程通常更容易阅读,因为它们的代码更加模块化和组合化。这使得代码更容易理解和修改。
  3. 可扩展性:函数式编程通常更容易扩展,因为它们的代码更加模块化和组合化。这使得代码更容易重用和修改。
  4. 可靠性:函数式编程通常更可靠,因为它们不依赖于共享状态或副作用。这使得代码更容易测试和调试。
  5. 并行性:函数式编程通常更容易并行化,因为它们的代码不依赖于共享状态或副作用。这使得代码更容易利用多核处理器和分布式系统。
4.1.2 缺点
  1. 性能:函数式编程通常比命令式编程更慢,因为它们需要更多的内存和计算资源来处理数据。这使得函数式编程不适合处理大规模数据或高性能应用程序。
  2. 学习曲线:函数式编程通常比命令式编程更难学习,因为它们需要更多的数学和抽象思维。这使得函数式编程不适合初学者或非技术人员。
  3. 可读性:函数式编程通常比命令式编程更难阅读,因为它们的代码更加抽象和符号化。这使得函数式编程不适合所有人,特别是那些不熟悉函数式编程的人。
  4. 可维护性:函数式编程通常比命令式编程更难维护,因为它们的代码更加抽象和符号化。这使得函数式编程不适合所有人,特别是那些不熟悉函数式编程的人。
  5. 工具支持:函数式编程通常比命令式编程缺乏工具支持,因为它们需要更多的数学和抽象思维。这使得函数式编程不适合所有人,特别是那些需要使用工具来提高生产力的人。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3017919.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

初始C++(一)

目录 前言: 命名空间: 总结: 前言: C语言学好了,现在当然要进阶了,那么就是从C开始。 C兼容C,支持其中90%的语法。可能有很多同学听说过C#,C#和C没有关系,是微软研究出…

☺☺☺☺☺☺☺栈的应用习题:有效的括号☺☺☺☺☺☺☺

目录 一解题思路: 二对解答代码分析: 三解答代码展示: 即浅学栈的创建后,可以简单利用其性质(先进后出,后进先出)来完成对一些题目的解答 如: 一解题思路: 这里我们可…

sql优化思路

sql的优化经验 这里解释一下SQL语句的优化的原理 1.指明字段名称,可以尽量使用覆盖索引,避免回表查询,因此可以提高效率 2.字面意思,无需过多赘述。索引就是为了提高查询效率的。 3.图中两条sql直接可以使用union all 或者 uni…

LeetCode 234.回文链表

题目描述 给你一个单链表的头节点 head ,请你判断该链表是否为 回文链表 。如果是,返回 true ;否则,返回 false 。 示例 1: 输入:head [1,2,2,1] 输出:true示例 2: 输入&#xff…

Jmeter页面汉化和字体显示过小调整

在频繁解压使用Jmeter的时候,经常会遇到需要将页面的英文调整为中文,页面文字和编辑区域内容文字显示较小的问题,记录一下方便以后查阅。 1.页面汉化 Jmeter在解压启动之后页面显示是英文,如果需要修改为中文,可以修改…

STM32单片机ADC功能详解

文章目录 1. ADC概述 2. ADC结构图 3. 引脚定义 4. 转换模式 5. 数据对齐 6. 转换时间 7. 硬件电路 8. STM32使用ADC单/多通道检测数据 1. ADC概述 功能:ADC是一个将模拟信号(如电压)转换为数字信号的设备。在微控制器中&#xff0c…

我用 GitHub 9.8k 的 Go 语言 2D 游戏引擎写了个游戏

前言 hi,大家好,这里是白泽。今天给大家分享一个 GitHub 🌟9.8k 的 Go 语言 2D 游戏引擎。 https://github.com/hajimehoshi/ebiten 引擎的贡献者依旧在积极维护,是一个兼具学习 & 娱乐的项目! 为此我也用这个…

vue组件传参数

在使用vue3进行开发的时候,我们一定绕不开的一个技术栈,就是组件传参。接下来我将介绍在vue3中如何运用这项技术。 在组件传参数中,分为两类,父传子参,或子传父参。需要了解的两个方法就是defineProps和defineEmits。…

顺序表的实现(迈入数据结构的大门)

什么是数据结构 数据结构是由:“数据”与“结构”两部分组成 数据与结构 数据:如我们所看见的广告、图片、视频等,常见的数值,教务系统里的(姓名、性别、学号、学历等等); 结构:当…

Debian是什么?有哪些常用命令

目录 一、Debian是什么? 二、Debian常用命令 三、Debian和CentOS的区别 四、Debian和CentOS的优缺点 五、Debian和CentOS的运用场景 一、Debian是什么? Debian是一种流行的开源Linux操作系统。 Debian是一个以Linux内核为基础的操…

测试平台开发:Django开发实战之注册界面实现(下)

1、 评论和用户建立关联 1)修改model: 软关联还是硬关联默认值是什么关联方被删除怎么办如何根据评论找到用户如何根据用户找到评论 然后执行命令: pdm run M pdm run init 这样在表里面就会多一个user_id的字段 2)修改视图&#xf…

Study--Oracle-02-单实例部署Oracle19C

一、CentOS 7 环境准备 1、软件准备 操作系统:CentOS 7 数据库版本: Oracle19C 2、操作系统环境配置 关闭selinux ,编辑 /etc/selinux/config文件,设置SELINUX enforcing 为SELINUXdisabled [rootoracle ~]# grep SELINUX /etc/seli…

「Dasha and Photos」Solution

简述题意 给定一个 n m n \times m nm 的方格,每个格子里有一个小写英文字母。 现在你有 k k k 个 n m n \times m nm 的方格,这些方格都是给定方格的基础上将左上角为 ( a i , b i ) (a_i,b_i) (ai​,bi​),右下角为 ( c i , d i ) …

免费思维13招之一:体验型思维

思维01:体验型思维 第一大战略:体验型思维。 体验型思维是免费思维中最简单的思维,我们先从最简单的讲起,由简入繁,简单的我们少讲,复杂的我们多讲。 那么,什么是体验型思维呢? 很简单,就是先让客户进行体验,再进行成交的方式。这一种思维,具体的可以分为两种:…

Spring Boot集成Swagger快速入门Demo

1.什么是Swagger? Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。 主要作用: 使得前后端分离开发更加方便,有利于团队协作。(实际开发中,接口文档的内容会不停的…

【LAMMPS学习】八、基础知识(5.11)磁自旋

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语,以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

VBA技术资料MF151:单元格注释标识数字化

我给VBA的定义:VBA是个人小型自动化处理的有效工具。利用好了,可以大大提高自己的工作效率,而且可以提高数据的准确度。“VBA语言専攻”提供的教程一共九套,分为初级、中级、高级三大部分,教程是对VBA的系统讲解&#…

Hive两代命令行客户端(Hive、Beeline)

Hive命令行客户端 Hive有两个主要的客户端工具,分别是旧版的Hive CLI(Command Line Interface)和新版的Beeline。 Hive CLI: Hive CLI 是 Hive 最早期的命令行客户端工具,它使用 JDBC 连接到 Hive 服务器,…

Colab/PyTorch - 002 Pre Trained Models for Image Classification

Colab/PyTorch - 002 Pre Trained Models for Image Classification 1. 源由2. 图像分类的预训练模型3. 示例 - AlexNet/ResNet1013.1 模型推断过程3.2 使用TorchVision加载预训练网络3.3 使用AlexNet进行图像分类3.3.1 Step1:加载预训练模型3.3.2 Step2&#xff1a…

free5gc+ueransim操作

启动free5gc容器 cd ~/free5gc-compose docker-compose up -d 记录虚拟网卡地址,eth0 ifconfig 查看并记录amf网元的ip地址 sudo docker inspect amf "IPAddress"那一行,后面记录的即是amf的ip地址 记录上述两个ip地址,完成UER…