Python 内嵌函数:它们有什么用处?

news2024/11/23 11:42:52

Python 内部函数

目录

  • 创建 Python 内部函数
  • 使用内部函数:基础知识
    • 提供封装
    • 构建助手内部函数
    • 使用内部辅助函数与私有辅助函数
  • 使用内部函数保留状态:闭包
    • 在闭包中保留状态
    • 修改关闭状态
  • 使用内部函数添加行为:装饰器
  • 结论

一、说明

        内部函数,也称为嵌套函数,是在其他函数内部定义的函数。在 Python 中,这种函数可以直接访问封闭函数中定义的变量和名称。内部函数有很多用途,最显着的是作为闭包工厂和装饰器函数。

在本教程中,您将学习如何:

  • 提供封装并隐藏您的函数以防止外部访问
  • 编写辅助函数以促进代码重用
  • 创建在调用之间保留状态的闭包工厂函数
  • 代码装饰器函数以向现有函数添加行为

免费奖励: 单击此处获取 Python 备忘单并学习 Python 3 的基础知识,例如使用数据类型、字典、列表和 Python 函数。

二、创建 Python 内部函数

        在另一个函数内部定义的函数称为内部函数嵌套函数。在Python中,这种函数可以访问封闭函数中的名称。以下是如何在 Python 中创建内部函数的示例:

>>> def outer_func():
...     def inner_func():
...         print("Hello, World!")
...     inner_func()
...

>>> outer_func()
Hello, World!

        在此代码中,您inner_func()在内部定义outer_func()将消息打印Hello, World!到屏幕上。为此,您需要调用 的inner_func()最后一行outer_func()。这是在 Python 中编写内部函数的最快方法。然而,内部函数提供了许多有趣的可能性,超出了您在本示例中看到的范围。

        内部函数的核心特征是它们能够从其封闭函数访问变量和对象,即使该函数返回后也是如此。封闭函数提供了内部函数可访问的命名空间:

>>> def outer_func(who):
...     def inner_func():
...         print(f"Hello, {who}")
...     inner_func()
...

>>> outer_func("World!")
Hello, World!

        现在您可以将字符串作为参数传递给outer_func(),并inner_func()通过名称访问该参数who。然而,这个名称是在 的本地范围内定义的outer_func()。在外部函数的局部作用域中定义的名称称为非局部名称inner_func()从角度来看,它们是非本地的。

以下是如何创建和使用更复杂的内部函数的示例:

>>> def factorial(number):
...     # Validate input
...     if not isinstance(number, int):
...         raise TypeError("Sorry. 'number' must be an integer.")
...     if number < 0:
...         raise ValueError("Sorry. 'number' must be zero or positive.")
...     # Calculate the factorial of number
...     def inner_factorial(number):
...         if number <= 1:
...             return 1
...         return number * inner_factorial(number - 1)
...     return inner_factorial(number)
...

>>> factorial(4)
24

        在 中factorial(),您首先验证输入数据以确保您的用户提供的整数等于或大于零。然后定义一个名为 的递归内部函数,inner_factorial()该函数执行阶乘计算并返回结果。最后一步是调用inner_factorial().

        注意:有关递归和递归函数的更详细讨论,请查看Python 中的递归思考和Python 中的递归:简介。

        使用此模式的主要优点是,通过在外部函数中执行所有参数检查,您可以安全地跳过内部函数中的错误检查并专注于手头的计算。

三、使用内部函数:基础知识

        Python 内部函数的用例多种多样。您可以使用它们来提供封装并隐藏您的函数以防止外部访问,您可以编写辅助内部函数,还可以创建闭包和装饰器。在本节中,您将了解内部函数的前两个用例,在后面的部分中,您将学习如何创建闭包工厂函数和装饰器。

3.1 提供封装

        当您需要保护或隐藏给定函数免受其外部发生的所有事情影响时,就会出现内部函数的常见用例,以便该函数完全隐藏在全局范围之外。这种行为通常称为封装

下面的例子强调了这个概念:

>>> def increment(number):
...     def inner_increment():
...         return number + 1
...     return inner_increment()
...

>>> increment(10)
11

>>> # Call inner_increment()
>>> inner_increment()
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    inner_increment()
NameError: name 'inner_increment' is not defined

        在本例中,您无法inner_increment()直接访问。如果你尝试这样做,那么你会得到一个NameError。那是因为increment()完全隐藏inner_increment(),阻止您从全局范围访问它。

3.2 构建助手内部函数

        有时,您的函数会在其体内的多个位置执行相同的代码块。例如,假设您要编写一个函数来处理包含纽约市 Wi-Fi 热点信息的CSV 文件。要查找纽约的热点总数以及提供大部分热点的公司,您可以创建以下脚本:

# hotspots.py

import csv
from collections import Counter

def process_hotspots(file):
    def most_common_provider(file_obj):
        hotspots = []
        with file_obj as csv_file:
            content = csv.DictReader(csv_file)

            for row in content:
                hotspots.append(row["Provider"])

        counter = Counter(hotspots)
        print(
            f"There are {len(hotspots)} Wi-Fi hotspots in NYC.\n"
            f"{counter.most_common(1)[0][0]} has the most with "
            f"{counter.most_common(1)[0][1]}."
        )

    if isinstance(file, str):
        # Got a string-based filepath
        file_obj = open(file, "r")
        most_common_provider(file_obj)
    else:
        # Got a file object
        most_common_provider(file)

        这里,process_hotspots()takefile作为一个参数。该函数检查是否是物理文件或文件对象file的基于字符串的路径。然后它调用辅助内部函数,该函数接受一个文件对象并执行以下操作:most_common_provider()

  1. 将文件内容读入生成器,该生成器使用csv.DictReader.
  2. 创建 Wi-Fi 提供商列表。
  3. 使用对象计算每个提供商的 Wi-Fi 热点数量collections.Counter。
  4. 打印一条包含检索到的信息的消息。

        如果运行该函数,您将得到以下输出:

>>> from hotspots import process_hotspots

>>> file_obj = open("./NYC_Wi-Fi_Hotspot_Locations.csv", "r")
>>> process_hotspots(file_obj)
There are 3319 Wi-Fi hotspots in NYC.
LinkNYC - Citybridge has the most with 1868.

>>> process_hotspots("./NYC_Wi-Fi_Hotspot_Locations.csv")
There are 3319 Wi-Fi hotspots in NYC.
LinkNYC - Citybridge has the most with 1868.

        无论您process_hotspots()使用基于字符串的文件路径还是文件对象进行调用,您都会得到相同的结果。

3.3 使用内部辅助函数与私有辅助函数

        通常,您会创建辅助内部函数,例如most_common_provider()当您想要提供封装时。如果您认为除了包含函数之外不会在其他任何地方调用内部函数,您也可以创建内部函数。

        尽管将辅助函数编写为内部函数可以达到预期的结果,但将它们提取为顶级函数可能会更好。_在这种情况下,您可以在函数名称中使用前导下划线 ( ) 来指示它是当前模块或类的私有函数。这将允许您从当前模块或类中的任何其他位置访问辅助函数,并根据需要重用它们。

        将内部函数提取到顶级私有函数中可以使您的代码更清晰、更具可读性。这种实践可以产生应用单一职责原则的函数。

四、使用内部函数保留状态:闭包

        在Python中,函数是一等公民。这意味着它们与任何其他对象相同,例如数字、字符串、列表、元组、模块等。您可以动态创建或销毁它们,将它们存储在数据结构中,将它们作为参数传递给其他函数,将它们用作返回值,等等。

        您还可以在 Python 中创建高阶函数。高阶函数是通过将其他函数作为参数、返回它们或两者兼而有之来对其他函数进行操作的函数。

        到目前为止,您所看到的所有内部函数示例都是普通函数,只是碰巧嵌套在其他函数中。除非您需要向外界隐藏您的函数,否则没有特定理由嵌套它们。您可以将这些函数定义为私有顶级函数,这样就可以了。

        在本节中,您将了解闭包工厂函数。闭包是动态创建的函数,由其他函数返回。它们的主要特点是,即使封闭函数已返回并完成执行,它们也可以完全访问在创建闭包的本地命名空间中定义的变量和名称。

        在 Python 中,当您返回内部函数对象时,解释器会将该函数及其包含的环境或闭包打包在一起。函数对象保留在其包含范围内定义的所有变量和名称的快照。要定义闭包,您需要执行三个步骤:

  1. 创建一个内部函数。
  2. 来自封闭函数的引用变量。
  3. 返回内部函数。

        有了这些基本知识,您就可以立即开始创建闭包并利用其主要功能:在函数调用之间保留状态

4.1 在闭包中保留状态

        闭包导致内部函数在调用时保留其环境的状态。闭包不是内部函数本身,而是内部函数及其封闭环境。闭包捕获包含函数中的局部变量和名称并保留它们。

考虑以下示例:

 1# powers.py
 2
 3def generate_power(exponent):
 4    def power(base):
 5        return base ** exponent
 6    return power

以下是该函数中发生的情况:

  • 第 3 行创建generate_power(),这是一个闭包工厂函数。这意味着它每次被调用时都会创建一个新的闭包,然后将其返回给调用者。
  • 第 4 行定义power(),它是一个内部函数,它接受单个参数 ,base并返回表达式 的结果base ** exponent
  • 第 6 行power作为函数对象返回,但不调用它。

power()from的值从哪里获取exponent?这就是闭包发挥作用的地方。在此示例中,从外部函数power()获取 generate_power()的值。以下是当你调用generate_power()时 Python 所做的事情:exponent

  1. 定义 的一个新实例power(),它采用单个参数base
  2. 拍摄 的周围状态的快照power(),其中包括exponent其当前值。
  3. power()连同其整个周围状态一起返回。

        这样,当您调用power()by 返回的实例时generate_power(),您将看到该函数记住了 的值exponent

>>> from powers import generate_power

>>> raise_two = generate_power(2)
>>> raise_three = generate_power(3)

>>> raise_two(4)
16
>>> raise_two(5)
25

>>> raise_three(4)
64
>>> raise_three(5)
125

        在这些例子中,raise_two()记住了exponent=2,并且raise_three()记住了exponent=3。请注意,两个闭包都会在调用之间记住它们各自的值exponent

        现在考虑另一个例子:

>>> def has_permission(page):
...     def permission(username):
...         if username.lower() == "admin":
...             return f"'{username}' has access to {page}."
...         else:
...             return f"'{username}' doesn't have access to {page}."
...     return permission
...

>>> check_admin_page_permision = has_permission("Admin Page")

>>> check_admin_page_permision("admin")
"'admin' has access to Admin Page."

>>> check_admin_page_permision("john")
"'john' doesn't have access to Admin Page."

        内部函数检查给定用户是否具有访问给定页面的正确权限。您可以快速修改此设置以获取会话中的用户,以检查他们是否具有访问特定路由的正确凭据。

  "admin"您可以查询SQL 数据库来检查权限,然后根据凭据是否正确返回正确的视图,而不是检查用户是否等于 。

        您通常会创建不修改其封闭状态的闭包,或具有静态封闭状态的闭包,如上面的示例所示。但是,您还可以创建闭包,通过使用可变对象(例如字典、集合或列表)来修改其封闭状态。

        假设您需要计算数据集的平均值。数据来自所分析参数的连续测量值流,并且您需要函数在调用之间保留先前的测量值。在这种情况下,您可以编写一个闭包工厂函数,如下所示:

>>> def mean():
...     sample = []
...     def inner_mean(number):
...         sample.append(number)
...         return sum(sample) / len(sample)
...     return inner_mean
...

>>> sample_mean = mean()
>>> sample_mean(100)
100.0
>>> sample_mean(105)
102.5
>>> sample_mean(101)
102.0
>>> sample_mean(98)
101.0

        分配给的闭包sample_mean保留连续调用之间的状态sample。即使您sample在 in 中定义mean(),它仍然在闭包中可用,因此您可以修改它。在这种情况下,sample它起到一种动态封闭状态的作用。

4.2 修改关闭状态

        通常,闭包变量对外界完全隐藏。但是,您可以为它们提供gettersetter内部函数:

>>> def make_point(x, y):
...     def point():
...         print(f"Point({x}, {y})")
...     def get_x():
...         return x
...     def get_y():
...         return y
...     def set_x(value):
...         nonlocal x
...         x = value
...     def set_y(value):
...         nonlocal y
...         y = value
...     # Attach getters and setters
...     point.get_x = get_x
...     point.set_x = set_x
...     point.get_y = get_y
...     point.set_y = set_y
...     return point
...

>>> point = make_point(1, 2)
>>> point.get_x()
1
>>> point.get_y()
2
>>> point()
Point(1, 2)

>>> point.set_x(42)
>>> point.set_y(7)
>>> point()
Point(42, 7)

        这里,make_point()返回一个代表point对象的闭包。该对象附加了 getter 和 setter 函数。您可以使用这些函数来读取和写入变量xy,它们在封闭范围中定义并随闭包一起提供。

        尽管此函数创建的闭包可能比等效类运行得更快,但您需要注意此技术不提供主要功能,包括继承、属性、描述符以及类和静态方法。如果您想更深入地研究这项技术,请查看使用闭包和嵌套作用域模拟类的简单工具(Python Recipe)。

 

五、使用内部函数添加行为:装饰器

        Python装饰器是内部函数(尤其是闭包)的另一个流行且方便的用例。装饰器是高阶函数,它接受一个可调用的(函数、方法、类)作为参数并返回另一个可调用的。

        您可以使用装饰器函数动态地将职责添加到现有的可调用对象中,并透明地扩展其行为,而不会影响或修改原始可调用对象。

        注意:有关 Python 可调用对象的更多详细信息,请查看Python 文档中的标准类型层次结构并向下滚动到“可调用类型”。

        要创建装饰器,您只需要定义一个可调用对象(函数、方法或类),它接受函数对象作为参数,对其进行处理,然后返回具有添加行为的另一个函数对象。

        一旦装饰器函数就位,您就可以将其应用到任何可调用对象。为此,您需要@在装饰器名称前面使用 at 符号 ( ),然后将其单独放在装饰可调用之前的行上:

Python
@decorator def decorated_func():
    # Function body...
    pass

        此语法decorator()自动将decorated_func()其作为参数并在其主体中对其进行处理。此操作是以下赋值的简写:

Python
decorated_func = decorator(decorated_func)

以下是如何构建装饰器函数以向现有函数添加新功能的示例:

>>> def add_messages(func):
...     def _add_messages():
...         print("This is my first decorator")
...         func()
...         print("Bye!")
...     return _add_messages
...

>>> @add_messages
... def greet():
...     print("Hello, World!")
...

>>> greet()
This is my first decorator
Hello, World!
Bye!

        在这种情况下,您可以使用@add_messages来装饰greet(). 这为装饰函数添加了新功能。现在,当您调用 时,您的函数将打印两条新消息,而greet()不仅仅是打印。Hello, World!

        Python 装饰器的用例多种多样。这里是其中的一些:

  • 调试
  • 缓存
  • 记录
  • 定时

        调试 Python 代码的常见做法是插入调用来print()检查变量的值、确认代码块已执行等。添加和删​​除呼叫可能print()会很烦人,并且您可能会忘记其中一些呼叫。为了防止这种情况,你可以编写一个这样的装饰器:

>>> def debug(func):
...     def _debug(*args, **kwargs):
...         result = func(*args, **kwargs)
...         print(
...             f"{func.__name__}(args: {args}, kwargs: {kwargs}) -> {result}"
...         )
...         return result
...     return _debug
...

>>> @debug
... def add(a, b):
...     return a + b
...

>>> add(5, 6)
add(args: (5, 6), kwargs: {}) -> 11
11

        此示例提供了debug(),它是一个装饰器,它将函数作为参数,并使用每个参数的当前值及其相应的返回值打印其签名。您可以使用此装饰器来调试您的函数。一旦获得所需的结果,您可以删除装饰器调用@debug,您的函数将为下一步做好准备。

        注意:如果您有兴趣深入了解 Python 的工作方式*args**kwargs工作方式,请查看Python args 和 kwargs:揭秘。

        这是如何创建装饰器的最后一个示例。这次,您将重新实现generate_power()为装饰器函数:

>>> def generate_power(exponent):
...     def power(func):
...         def inner_power(*args):
...             base = func(*args)
...             return base ** exponent
...         return inner_power
...     return power
...

>>> @generate_power(2)
... def raise_two(n):
...     return n
...
>>> raise_two(7)
49

>>> @generate_power(3)
... def raise_three(n):
...     return n
...
>>> raise_three(5)
125

        此版本generate_power()产生的结果与原始实现中获得的结果相同。在这种情况下,您可以使用要记住的闭包exponent和返回输入函数 的修改版本的装饰器func()

        这里,装饰器需要接受一个参数(exponent),所以你需要有两层嵌套的内部函数。第一层由 表示power(),它将修饰函数作为参数。第二层用 表示,将中的inner_power()参数打包,最后计算幂并返回结果。exponentargs

六、结论

        如果您在另一个函数内定义一个函数,那么您将创建一个内部函数,也称为嵌套函数。在 Python 中,内部函数可以直接访问您在封闭函数中定义的变量和名称。这为您提供了一种创建辅助函数、闭包和装饰器的机制。

        在本教程中,您学习了如何:

  • 通过在其他函数中嵌套函数来提供封装
  • 编写辅助函数以重用代码片段
  • 实现在调用之间保留状态的闭包工厂函数
  • 构建装饰器函数以提供新功能

        您现在已准备好在自己的代码中利用内部函数的多种用途。如果您有任何问题或意见,请务必在下面的评论部分中分享。

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

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

相关文章

分析订单每日营收、流量数据:

曝光率----》流量----->订单数 点击率&#xff1a;1000次广告展示&#xff0c;点击率10%意味着你可以获得100个流量&#xff08;就是访问产品页的人数&#xff09; &#xff08;下单&#xff09;转化率&#xff1a;转化率5%意味着你可以获得&#xff1a;流量的%5&#xff…

有方N58 HTTP POST 请求连接 TDengine

串口调试软件&#xff1a;格西调试精灵 第一步先注册网络获取IP地址 建立PPP连接 ATXIIC1\r PPP链路建立成功&#xff0c;查询IP地址 ATXIIC?\r 设置网络APN ATCREG?\r 运行结果&#xff0c;红线处是获…

跨境商城源码怎么部署

随着全球电子商务的快速发展&#xff0c;跨境商城已成为一种重要的商业模式。然而&#xff0c;要成功运营一个跨境商城&#xff0c;除了要有优秀的源码开发技术外&#xff0c;还需要进行合理的源码部署。本文将为您提供一份全面的跨境商城源码部署指南。 二、跨境商城源码选择 …

API管理平台搭建过程问题总结

API管理的定义和好处 API管理是指对应用程序编程接口&#xff08;API&#xff09;进行集中管理、监控和维护的过程。API是用于不同软件之间进行通信和交互的编程接口&#xff0c;通过API管理可以有效地管理和控制API的使用、访问和安全性。 API管理的好处包括&#xff1a; 1…

配送中心信息系统建设

配送中心信息系统的网络构成 配送中心最主要的信息系统为“物流管理信息系统”(WarehouseManagementsystem简称WMS)&#xff0c;物流管理信息系统的网络构成主要由主机系统设备、资料库主机、终端系统设备、无线终端网络设备和网络系统设备组成。将这些设备通过现代网络技术有…

[概述] 获取点云数据的仪器

这里所说的获取点云的仪器指的是可以获取场景中物体距离信息的相关设备&#xff0c;下面分别从测距原理以及适用场景来进行介绍。 一、三角测距法 三角测距原理 就是利用三角形的几何关系来测量物体的距离。想象一下&#xff0c;你站在一个地方&#xff0c;你的朋友站在另一…

乐分享五五公排,整合资源打造全新消费生态

​小编介绍&#xff1a;10年专注商业模式设计及软件开发&#xff0c;擅长企业生态商业模式&#xff0c;商业零售会员增长裂变模式策划、商业闭环模式设计及方案落地&#xff1b;扶持10余个电商平台做到营收过千万&#xff0c;数百个平台达到百万会员&#xff0c;欢迎咨询。 分…

【云原生基础】了解云原生,什么是云原生?

&#x1f4d1;前言 本文主要讲了云原生的基本概念和原则的文章&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风讲故事 &#x1f304;每日一句&#x…

Unity 粒子特效-第六集-圆圈循环UI特效

一、特效预览 二、制作原理 1.素材介绍 我们停下来看一下这个球&#xff0c;是有无数个小圆圈形成的。 小圆圈素材资源 链接&#xff1a;https://pan.baidu.com/s/1cNMOgYQJnzWJ_uOuqhTpnQ?pwd48y5 提取码&#xff1a;48y5 2.步骤介绍 1.小球动画的时间大概在1秒 2.小球…

21款奔驰GLC300L升级23P驾驶辅助 出行更加的安全

驾驶辅助和自动驾驶的区别就是需要人为去接管&#xff0c;虽然车辆会根据道路自己行驶&#xff0c;弯道上也能居中自动修正行驶&#xff0c;长时间不接管方向盘&#xff0c;系统会提示人为接管&#xff0c;这就是奔驰的23P驾驶辅助系统&#xff0c; 很多车友升级23P驾驶辅助系…

任意文件下载之漏洞复现

0x01 应用介绍 泛微e-office系统是标准、易用、快速部署上线的专业协同OA软件,国内协同OA办公领域领导品牌,致力于为企业用户提供专业OA办公系统、移动OA应用等协同OA整体解决方案 0x02 影响版本及语法特征 泛微e-offcie9 fofa&#xff1a;app”泛微-EOffice” && b…

【了解一下,MySQL中的三大日志binlog redolog undolog】

文章目录 MySQL中的三大日志binlog redolog undolog引言binlog简介使用场景binlog刷盘时机binlog日志格式 redo log简介redo log基本概念redo log记录形式redo log与binlog区别 一条更新语句执行过程&#xff08;含日志写入&#xff09;undo log MySQL中的三大日志binlog redol…

阿里云推出AI编程工具“通义灵码“;生成式 AI 入门教程 2

&#x1f989; AI新闻 &#x1f680; 阿里云推出AI编程工具"通义灵码"&#xff0c;支持多种语言及实时续写功能 摘要&#xff1a;阿里云推出了一款名为"通义灵码"的AI编程工具&#xff0c;支持多种主流编程语言&#xff0c;包括Java、Python、Go等。该工…

电机控制::单位统一问题

电机控制中有很多单位处理的问题&#xff0c;需要同一单位。此处先做个记录&#xff0c;等有时间具体梳理一下&#xff0c;如果有熟悉的大佬可以指教一下。 无量纲的量 IQ标幺&#xff1b;UU单位&#xff1b;内部单位 物理量 1、时间问题&#xff1a;周期频率问题 &#xff…

关于卓越服务的调研问卷

这是NetSuite知识会关于精益实施研究课题的调研问卷&#xff0c;如果感兴趣的话&#xff0c;请参与进来。待调研期结束后&#xff0c;我们会把调研报告分享给大家。

Webpack的Tree Shaking。它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

经典文献阅读之--RLAD(城市环境中自动驾驶从像素进行强化学习)

0. 简介 强化学习在自动驾驶中的应用已经日渐普及&#xff0c;虽然由于一些伦理问题&#xff0c;目前真正的使用这种强化学习的还不是很多&#xff0c;但是目前已经有很多应用在自动驾驶中的强化学习的工作&#xff0c;但是我们发现这类方法基本都是将卷积编码器与策略网络一起…

平面波向球面波的展开

平面波向球面波的展开是一个极其重要的话题 手稿放在文章的结尾处 勒让德展开 citation 1: 我们整理一下&#xff0c;对exp(x)做泰勒展开&#xff0c;得 citation 2: 我们先把精力集中到解决这个积分上去 反复利用分部积分 考虑到奇偶性问题 当且仅当时积分不为零现在做变换 …

Faraday库

require faraday# 创建Faraday对象&#xff0c;使用作为代理服务器 proxy_host huake proxy_port 1111 faraday Faraday.new(:proxy > { :host > proxy_host, :port > proxy_port })# 使用Faraday对象发送GET请求到https://www.dianping.com/ response faraday.get…

Observability:使用 OpenTelemetry 手动检测 .NET 应用程序

作者&#xff1a;David Hope 在快节奏的软件开发领域&#xff0c;尤其是在云原生领域&#xff0c;DevOps 和 SRE 团队日益成为应用程序稳定性和增长的重要合作伙伴。 DevOps 工程师不断优化软件交付&#xff0c;而 SRE 团队则充当应用程序可靠性、可扩展性和顶级性能的管理者。…