展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > 如何在Python中使用函数,递归和闭包?

如何在Python中使用函数,递归和闭包?

重新认识函数我们已经接触过数据类型和不变性中的函数。如果你还没有读过那篇文章,我建议你现在回去看看。让我们看一个函数的简单示例,以确保我们在同一维度。defcheer(volume=None):ifvolumeisNone:print("yay.")elifvolume=="Louder!":print("yay!")elifvolume=="LOUDER!":print("*deepbreath*")print("yay!")cheer()#prints"yay."cheer("Louder!")#pr

重新认识函数

我们已经接触过数据类型和不变性中的函数。如果你还没有读过那篇文章,我建议你现在回去看看。

让我们看一个函数的简单示例,以确保我们在同一维度。

def cheer(volume=None):
    if volume is None:
        print("yay.")
    elif volume == "Louder!":
        print("yay!")
    elif volume == "LOUDER!":
        print("*deep breath*")
        print("yay!")


cheer()  # prints "yay."
cheer("Louder!")  # prints "yay!"
cheer("LOUDER!")  # prints "*deep breath* ...yay!"

这里没有什么令人惊讶的。函数cheer()接受单个参数volume。如果我们不为volume传递参数,它将默认为None。

什么是函数式编程?

我们这些来自面向对象编程语言的人已经学会了从类和对象的角度来思考一切。数据被组织成对象,以及负责访问和修改该数据的函数。有时这可行,但有时,类开始感觉像太多模板。

函数式编程几乎与此相反。我们围绕函数进行组织,我们通过这些函数传递数据。我们必须遵守一些规则:

  • 函数应该只接受输入,只产生输出。

  • 函数不应该有副作用;他们不应该修改任何外部的东西。

  • 函数应该(理想情况下)总是为相同的输入产生相同的输出。函数内部不应该有会破坏这种模式的状态。

现在,在你将所有 Python 代码重写为纯函数式之前,停止!不要忘记 Python 的一大优点是它是一种多范式语言。你不必选择一种范式并坚持下去;你可以在你的代码中混合搭配,这样是最好的。

事实上,我们已经这样做了!迭代器和生成器都是从函数式编程中参考而来的,它们与对象一起工作得很好。也可以随意合并 lambda、装饰器和闭包。这一切都是为了选择最适合这项工作的工具。

在实践中,我们很少能同时避免副作用。在将函数式编程的概念应用到 Python 代码中时,你应该更多地关注和慎重考虑副作用,而不是完全避免它们。将它们限制在没有更好方法解决问题的情况下。这里没有硬性规定可以依靠。你需要培养自己的洞察力。

递归

当一个函数调用自身时,这称为递归。当我们需要重复函数的整个逻辑,但循环不合适(或者感觉太混乱)时,这会很有帮助。

注意:我下面的示例被简化以突出递归本身。这实际上并不是递归是最佳方法的情况。当你需要对不同的数据块重复调用复杂的语言时,例如当你遍历树结构时,递归 会更好。

import random
random.seed()


class Villain:

    def __init__(self):
        self.defeated = False

    def confront(self):
        # Roll of the dice.
        if random.randint(0,10) == 10:
            self.defeated = True


def defeat(villain):
    villain.confront()
    if villain.defeated:
        print("Yay!")
        return True
    else:
        print("Keep trying...")
        return defeat(villain)


starlight = Villain()
victory = defeat(starlight)

if victory:
    print("YAY!")

与random相关的东西可能看起来很新。它与这个主题并没有真正相关,但简而言之,我们可以通过在程序开始时用随机数生成器生成随机数 (random.seed()),然后调用random.randint(min, max), 函数里面的min和max定义可能值的包含范围。

这里逻辑的重要部分是defeat()函数。只要villain 没有被打败,函数就会调用自己,传递villain变量,直到其中一个函数调用返回一个值。在这种情况下,该值在递归调用堆栈中返回,最终存储在victory.

不管花多长时间*,我们最终都会打败那个villain 。

注意无限递归

递归可以是一个强大的工具,但它也会带来一个问题:如果我们没有办法停下来怎么办?

def mirror_pool(lookers):
    reflections = []
    for looker in lookers:
        reflections.append(looker)
    lookers.append(reflections)

    print(f"We have {len(lookers) - 1} duplicates.")

    return mirror_pool(lookers)


duplicates = mirror_pool(["Pinkie Pie"])

显然,这将永远运行!一些语言没有提供一种干净的方式来处理这个问题——函数只会无限递归,直到崩溃。

Python 更优雅地阻止了这种疯狂。一旦达到设定的递归深度(通常为 997-1000 次),它就会停止整个程序并引发错误:

RecursionError:调用 Python 对象时超出最大递归深度

像所有错误一样,我们可以在事情失控之前发现它:

try:
    duplicates = mirror_pool(["Pinkie Pie"])
except RecursionError:
    print("Time to watch paint dry.")

值得庆幸的是,由于我编写这段代码的方式,我实际上不需要做任何特别的事情来清理 997 个重复项。递归函数从未返回,因此duplicates在这种情况下保持未定义。

但是,我们可能希望以另一种方式控制递归,因此我们不必使用 try-except来防止灾难。在我们的递归函数中,我们可以通过添加一个参数来跟踪它被调用的次数calls,并在它变得太大时立即中止。

def mirror_pool(lookers, calls=0):
    calls += 1

    reflections = []
    for looker in lookers:
        reflections.append(looker)
    lookers.append(reflections)

    print(f"We have {len(lookers) - 1} duplicates.")

    if calls < 20:
        lookers = mirror_pool(lookers, calls)

    return lookers


duplicates = mirror_pool(["Pinkie Pie"])
print(f"Grand total: {len(duplicates)} Pinkie Pies!")

我们仍然需要弄清楚如何在不丢失原始数据的情况下删除 20 个重复项,但至少程序没有崩溃。

注意:你可以使用sys.setrecursionlimit(n)覆盖最大递归级别,其中n是你想要的最大值。

嵌套函数

有时,我们可能想要在一个函数中重用一段逻辑,但我们不想通过创建另一个函数来弄乱我们的代码。

def use_elements(target):
    elements = ["Honesty", "Kindness", "Laughter",
                "Generosity", "Loyalty", "Magic"]

    def use(element, target):
        print(f"Using Element of {element} on {target}.")

    for element in elements:
        use(element, target)


use_elements("Nightmare Moon")

当然,这个简单的例子的问题在于它的用处不是很明显。当我们想要将大量逻辑抽象为函数以实现可重用性但又不想在主函数之外定义时,嵌套函数会变得很有帮助。如果use()函数要复杂得多,并且可能不仅仅是循环调用,那么这种设计将是合理的。

尽管如此,该示例的简单性仍然体现了基本概念。这也带来了另一个困难。你会注意到,每次我们调用它时use(),我们都在传递target给内部函数,这感觉毫无意义。我们不能只使用已经在本地范围内的target变量吗?

事实上,我们可以:

def use_elements(target):
    elements = ["Honesty", "Kindness", "Laughter",
                "Generosity", "Loyalty", "Magic"]

    def use(element):
        print(f"Using Element of {element} on {target}.")

    for element in elements:
        use(element)


use_elements("Nightmare Moon")

然而,一旦我们尝试修改该变量,我们就会遇到麻烦:

def use_elements(target):
    elements = ["Honesty", "Kindness", "Laughter",
                "Generosity", "Loyalty", "Magic"]

    def use(element):
        print(f"Using Element of {element} on {target}.")
        target = "Luna"

    for element in elements:
        use(element)

    print(target)


use_elements("Nightmare Moon")

运行该代码会引发错误:

UnboundLocalError: local variable 'target' referenced before assignment

显然,它不再认识我们的局部变量target。这是因为默认情况下,分配给变量时会覆盖封闭范围中的任何已有相同的变量。因此,该行target == "Luna"试图创建一个限制在use()范围内的新变量,并在use_elements()的封闭范围内隐藏已有的target变量。与Python 看到了这一点并假设,因为我们在 use()函数中定义了target,所以对该变量的所有引用都与该本地名称相关。这不是我们想要的!

关键字nonlocal允许我们告诉内部函数我们正在使用来自封闭局部范围的target变量。

def use_elements(target):
    elements = ["Honesty", "Kindness", "Laughter",
                "Generosity", "Loyalty", "Magic"]

    def use(element):
        nonlocal target
        print(f"Using Element of {element} on {target}.")
        target = "Luna"

    for element in elements:
        use(element)

    print(target)


use_elements("Nightmare Moon")

现在,运行结果,我们看到了打印出来的值Luna。我们在这里的工作完成了!

注意:如果你希望函数能够修改定义为全局范围(在所有函数之外)的变量,请使用global关键字而不是nonlocal。

闭包

基于嵌套函数的思想,我们可以创建一个函数,该函数实际上构建并返回另一个函数(称为闭包)。

def harvester(pony):
    total_trees = 0

    def applebucking(trees):
        nonlocal pony, total_trees
        total_trees += trees
        print(f"{pony} harvested from {total_trees} trees so far.")

    return applebucking


apple_jack = harvester("Apple Jack")
big_mac = harvester("Big Macintosh")
apple_bloom = harvester("Apple Bloom")

north_orchard = 120
west_orchard = 80  # watch out for fruit bats
east_orchard = 135
south_orchard = 95
near_house = 20

apple_jack(west_orchard)
big_mac(east_orchard)
apple_bloom(near_house)
big_mac(north_orchard)
apple_jack(south_orchard)

在此示例中,applebucking()就是闭包,因为它关闭了非局部变量pony和total_trees。即使在外部函数终止后,闭包仍保留对这些变量的引用。

闭包从harvester()函数返回,并且可以像任何其他对象一样存储在变量中。正是因为它“关闭”了一个非局部变量,这使得它本身就是一个闭包。否则,它只是一个函数。

在这个例子中,我使用闭包来有效地创建带有状态的对象。换句话说,每个收割机都记得他或她从多少棵树上收割过。这种特殊用法并不严格符合函数式编程,但如果你不想创建一个完整的类来存储一个函数的状态,它会非常有用!

apple_jack, big_macintosh, 和apple_bloom现在是三个不同的函数,每个函数都有自己独立的状态;他们每个人都有不同的名字,并记住他们收获了多少棵树。在一个闭包状态中发生的事情对其他闭包状态没有影响,他们都是独立的个体。

当我们运行代码时,我们看到了这个状态:

Apple Jack harvested from 80 trees so far.
Big Macintosh harvested from 135 trees so far.
Apple Bloom harvested from 20 trees so far.
Big Macintosh harvested from 255 trees so far.
Apple Jack harvested from 175 trees so far.

闭包的问题

闭包本质上是“隐式类”,因为它们将功能及其持久信息(状态)放在同一个对象中。然而,闭包有几个独特的缺点:

  • 你不能按原样访问“成员变量”。在我们的示例中,我永远无法访问闭包apple_jack上的变量total_trees!我只能在闭包自己的代码的上下文中使用该变量。

  • 关闭状态是完全不透明的。除非你知道闭包是如何编写的,否则你不知道它记录了哪些信息。

  • 由于前面两点,根本不可能直接知道闭包何时具有任何状态。

使用闭包时,你需要准备好处理这些问题,以及它们带来的所有调试困难。我建议仅在你需要单个函数来存储调用之间的少量私有状态时才使用它们,并且仅在代码中如此有限的时间段内使用它们,以至于编写整个类并不合理。(另外,不要忘记生成器和协程,它们可能更适合许多此类场景。)

闭包仍然可以成为 Python中有用的部分,只要你非常小心地使用它们。

Lambdas

lambda是由单个表达式组成的匿名函数(无名称)。

仅此定义就是许多程序员无法想象他们为什么需要一个定义的原因。编写一个没有名称的函数有什么意义,基本上使重用完全不切实际?当然,你可以将lambda 分配给一个变量,但此时,你不应该刚刚编写了一个函数吗?

为了理解这一点,让我们先看一个没有lambdas 的例子:

class Element:

    def __init__(self, element, color, pony):
        self.element = element
        self.color = color
        self.pony = pony

    def __repr__(self):
        return f"Element of {self.element} ({self.color}) is attuned to {self.pony}"


elements = [
    Element("Honesty", "Orange", "Apple Jack"),
    Element("Kindness", "Pink", "Fluttershy"),
    Element("Laughter", "Blue", "Pinkie Pie"),
    Element("Generosity", "Violet", "Rarity"),
    Element("Loyalty", "Red", "Rainbow Dash"),
    Element("Magic", "Purple", "Twilight Sparkle")
]


def sort_by_color(element):
    return element.color


elements = sorted(elements, key=sort_by_color)
print(elements)

我希望你注意的主要事情是sort_by_color()函数,我必须编写该函数以明确按颜色对列表中的 Element 对象进行排序。实际上,这有点烦人,因为我再也不需要那个功能了。

这就是 lambdas 的用武之地。我可以删除整个函数,并将elements = sorted(...)行更改为:

elements = sorted(elements, key=lambda e: e.color)

使用 lambda 可以让我准确地描述我的逻辑我在哪里使用它,而不是在其他任何地方。(这key=部分只是表明我将 lambda 传递给sorted()函数的key的参数。)

一个 lambda 具有结构lamba : 。它可以收集任意数量的参数,用逗号分隔,但它只能有一个表达式,其值是隐式返回的。

注意:与常规函数不同,Lambda 不支持类型注释(类型提示)。

如果我想重写那个 lambda 以按元素的名称而不是颜色排序,我只需要更改表达式部分:

elements = sorted(elements, key=lambda e: e.name)

就这么简单。

同样,lambda在需要将带有单个表达式的函数传递给另一个函数时非常有用。这是另一个示例,这次在 lambda 上使用了更多参数。

为了设置这个示例,让我们从 Flyer 的类开始,它存储名称和最大速度,并返回 Flyer 的随机速度。

import random
random.seed()


class Flyer:

    def __init__(self, name, top_speed):
        self.name = name
        self.top_speed = top_speed

    def get_speed(self):
        return random.randint(self.top_speed//2, self.top_speed)

我们希望能够让任何给定的 Flyer 对象执行任何飞行技巧,但是将所有这些逻辑放入类本身是不切实际的……可能有成千上万的飞行技巧和变体!

Lambdas是定义这些技巧的一种方式。我们将首先向该类添加一个函数,该函数可以接受函数作为参数。我们假设这个函数总是有一个参数:执行技巧的速度。

def perform(self, trick):
        performed = trick(self.get_speed())
        print(f"{self.name} perfomed a {performed}")

要使用它,我们创建一个 Flyer 对象,然后将函数传递给它的perform()方法。

rd = Flyer("Rainbow Dash", 780)
rd.perform(lambda s: f"barrel-roll at {s} mph.")
rd.perform(lambda s: f"flip at {s} mph.")

因为 lambda 的逻辑在函数调用中,所以更容易看到发生了什么。

回想一下,你可以将 lambdas 存储在变量中。当你希望代码如此简短但需要一些可重用性时,这实际上会很有帮助。例如,假设我们有另一个 Flyer,我们希望他们两个都进行barrelroll。

spitfire = Flyer("Spitfire", 650)
barrelroll = lambda s: f"barrel-roll at {s} mph."

spitfire.perform(barrelroll)
rd.perform(barrelroll)

当然,我们可以将barrelroll写成一个适当的单行函数,但是通过这种方式,我们为自己节省了一些样板文件。而且,由于在这段代码之后我们不会再次使用该逻辑,因此没有必要再使用一个成熟的函数。

再一次,可读性很重要。Lambda 非常适合用于简短、清晰的逻辑片段,但如果你有更复杂的事情,你还是应该编写一个合适的函数。

装饰器

假设我们想要修改任何函数的行为,而不实际更改函数本身。

让我们从一个相当基本的函数开始:

def partial_transfiguration(target, combine_with):
    result = f"{target}-{combine_with}"
    print(f"Transfiguring {target} into {result}.")
    return result


target = "frog"
target = partial_transfiguration(target, "orange")
print(f"Target is now a {target}.")

运行给我们:

Transfiguring frog into frog-orange.
Target is now a frog-orange.

很简单,对吧。但是,如果我们想为此添加一些额外的宣传呢?如你所知,我们真的不应该将这种逻辑放在我们的partial_transfiguration函数中。

这就是装饰器的用武之地。装饰器“包装”了函数周围的附加逻辑,这样我们实际上不会修改原始函数本身。这使得代码更易于维护。

让我们从为大张旗鼓创建一个装饰器开始。这里的语法一开始可能看起来有点过于复杂,但请放心,我会详细介绍。

import functools


def party_cannon(func):
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        print("Waaaaaaaait for it...")
        r = func(*args, **kwargs)
        print("YAAY! *Party cannon explosion*")
        return r

    return wrapper

你可能已经认识到wrapper()它实际上是一个闭包,它是由我们的party_cannon()函数创建并返回的。我们传递我们正在“装饰”的函数,func。

然而,我们真的对我们装饰的函数一无所知!它可能有也可能没有参数。闭包的参数列表(*args, **kwargs)实际上可以接受任何数量的参数,从零到无穷大。调用func()时,我们以相同的方式将这些参数传递给func()。

当然,如果func()上的参数列表与通过装饰器传递给它的参数之间存在某种不匹配,则会引发通常和预期的错误(这显然是一件好事)。

在wrapper()内部,我们可以随时随地调用我们的函数func()。我选择在打印我的两条消息之间这样做。

我不想丢弃func()返回的值,所以我将返回的值分配给r,并确保在装饰器的末尾用return r.

请注意,对于在装饰器中调用函数的方式,或者即使调用它或调用多少次,实际上并没有硬性规定。你还可以以任何你认为合适的方式处理参数和返回值。关键是要确保装饰器实际上不会以某种意想不到的方式破坏它装饰的函数。

装饰器前的奇数行,@functools.wraps(func),实际上是一个装饰器本身。没有它,被装饰的函数本质上会混淆它自己的身份,弄乱我们对__doc__(文档字符串)和__name__.。这个特殊的装饰器确保不会发生这种情况;被包装的函数保留自己的身份,可以从函数外部以所有常用方式访问。(要使用那个特殊的装饰器,我们必须首先import functools。)

现在我们已经编写了party_cannon装饰器,我们可以使用它来添加我们想要的partial_transfiguration()函数。这样做很简单:

@party_cannon
def partial_transfiguration(target, combine_with):
    result = f"{target}-{combine_with}"
    print(f"Transfiguring {target} into {result}.")
    return result

第一行,@party_cannon是我们做出的唯一改变!partial_transfiguration函数现在已装饰。

注意:你甚至可以将多个装饰器堆叠在一起,一个在下一个之上。只需确保每个装饰器紧接在它所包装的函数或装饰器之前。

我们以前的用法根本没有改变:

target = "frog"
target = partial_transfiguration(target, "orange")
print(f"Target is now a {target}.")

然而输出确实发生了变化:

Waaaaaaaait for it...
Transfiguring frog into frog-orange.
YAAY! *Party cannon explosion*
Target is now a frog-orange.
本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
作者最新文章
编程开发 Python
相关文章 更多
精品专题 更多
装机必备

正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

Windows

正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

PDF教程

正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

macOS软件

正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

IOS软件

正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

AI

正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

Mac软件 更多
WPS Office macOS版
WPS Office macOS版

WPS Office是一款面向macOS用户的综合办公套件,将文字处理、电子表格、演示文稿、PDF工具、模板与云协作整合在同一应用中。它兼容常见Microsoft Office格式,支持Intel及Apple芯片Mac,基础功能可免费使用,

Shapr3D macOS版
Shapr3D macOS版

Shapr3D是一款面向工业设计、机械工程、建筑概念和三维打印工作流的CAD软件。Mac版采用Parasolid建模内核,支持草图约束、实体建模、工程图、可视化渲染及常见CAD格式交换,并可通过账户在多台设备之间同步项目。

REAPER macOS版
REAPER macOS版

REAPER是Cockos开发的数字音频工作站,提供多轨音频与MIDI录制、剪辑、处理、混音和母带制作工具。Mac版兼容Intel与Apple芯片,支持AU、VST、VST3、CLAP等插件格式,并提供高度可定制的工作流程。

Ableton Live macOS版
Ableton Live macOS版

Ableton Live 是面向音乐制作人与现场表演者的数字音频工作站,提供编曲视图、独具特色的现场视图、音频录制、MIDI创作、实时变速、乐器及效果器。Mac版原生支持Apple芯片,并可连接音频接口、MIDI控制器和第三方插件。

Adobe After Effects macOS版
Adobe After Effects macOS版

Adobe After Effects 是面向动态图形、影视特效与视频合成的专业创作软件。它提供关键帧动画、遮罩抠像、运动跟踪、三维空间、文字动画和表达式等工具,并可与 Premiere Pro、Photoshop、Illustrator

Adobe Audition macOS版
Adobe Audition macOS版

Adobe Audition 是面向播客、影视后期、音乐制作及内容创作者的专业音频工作站,提供波形精修、多轨录制与混音、频谱编辑、降噪修复、响度匹配和效果处理工具,并可与 Adobe Premiere 协同完成视频声音制作。

Adobe Bridge macOS版
Adobe Bridge macOS版

Adobe Bridge 是面向摄影师、设计师及内容团队的免费数字资产管理工具,可集中预览照片、视频和 Adobe 项目文件,并利用评级、标签、关键词、元数据、筛选与收藏集完成分类检索。它还支持批量重命名、格式导出、相机导入及 Camera

Adobe Illustrator macOS版
Adobe Illustrator macOS版

Adobe Illustrator 是 Adobe 推出的专业矢量图形设计软件,适合在 Mac 上制作标志、图标、插画、包装、信息图及印刷版面。它以路径和锚点构建可无损缩放的图形,并提供钢笔、形状、文字、图像描摹、渐变、画板及生成式功能。

Adobe InDesign macOS版
Adobe InDesign macOS版

Adobe InDesign 是面向印刷品与数字出版物的专业版面设计软件,可在 Mac 上制作书籍、杂志、宣传册、海报、报告及交互式文档。它提供精细的文字样式、网格、母版、长文档管理和印前输出能力。

Adobe Lightroom Classic macOS版
Adobe Lightroom Classic macOS版

Adobe Lightroom Classic 是面向桌面摄影工作流的照片管理与后期处理软件,可将原始照片保存在本地硬盘,通过目录、关键词、评分和收藏夹高效整理图库,并提供 RAW 冲印、蒙版、镜头校正、批量同步及多格式导出等功能。

Adobe Media Encoder macOS版
Adobe Media Encoder macOS版

Adobe Media Encoder 是 Adobe 推出的专业音视频编码与转码工具,可通过队列、预设和监视文件夹批量完成格式转换、代理文件创建及多平台成片输出,并与 Premiere Pro、After Effects 等软件紧密协作。

Adobe Photoshop macOS版
Adobe Photoshop macOS版

Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理软件,提供图层、蒙版、选区、修复、调色、文字排版、智能对象及生成式编辑等能力。Mac 版支持 Intel 与 Apple Silicon 处理器。

WINDOWS 更多
Adobe Photoshop Windows版
Adobe Photoshop Windows版

Adobe Photoshop 是面向摄影师、设计师和内容创作者的专业图像处理工具,可在 Windows 上完成照片修饰、选区抠图、图层合成、文字排版、绘画及生成式编辑。软件采用订阅授权,由 Creative Cloud 管理安装、更新与许

Adobe InDesign Windows版
Adobe InDesign Windows版

Adobe InDesign 是面向印刷与数字出版的专业页面排版工具,可制作书籍、杂志、宣传册、海报、交互式 PDF 和电子书。它提供精细的文字样式、多页面管理、印前检查及多格式输出能力,并能与 Photoshop、Illustrator

Adobe Illustrator Windows版
Adobe Illustrator Windows版

Adobe Illustrator 是用于绘制矢量图形、插画、图标、徽标和版式的专业设计工具。它以路径和锚点为核心,作品放大后仍能保持清晰,并提供画板、文字、渐变、图像描摹及精确变换等功能,适合品牌视觉、印刷物料、数字界面和商业插画创作。

Adobe Bridge Windows版
Adobe Bridge Windows版

Adobe Bridge 是 Adobe 推出的创意资产管理工具,可集中预览、分类和查找照片、视频、PDF及多种设计文件,并支持元数据、关键词、评级、批量重命名和格式导出。它可与 Photoshop、Illustrator 等应用衔接,

Affinity Photo Windows版
Affinity Photo Windows版

Affinity Photo 是一款面向摄影师、修图师和视觉设计人员的桌面图像编辑工具,提供 RAW 显影、多图层合成、蒙版、实时滤镜、批处理和色彩管理等功能。原独立产品已停止销售,其照片编辑能力已延续至免费的新 Affinity 应用;

Adobe Lightroom Classic Windows版
Adobe Lightroom Classic Windows版

Adobe Lightroom Classic 是面向 Windows 桌面摄影工作流的照片管理与无损编辑工具,可通过目录集中整理大型图库,并完成 RAW 显影、局部蒙版、批量调整、打印和多格式导出。它强调本地文件管理与精细控制,

Figma Windows版
Figma Windows版

Figma 是面向产品设计与开发团队的云端协作平台,可在 Windows 桌面客户端中完成界面绘制、组件管理、交互原型、评论评审和开发交付。文件保存在云端,多名成员能够同步编辑并共享设计系统;官方同时提供免费 Starter 方案及按席位计

Affinity Designer Windows版
Affinity Designer Windows版

Affinity Designer 是面向矢量图形、数字插画和界面设计的专业创作工具,可在矢量、像素与导出工作区之间快速切换。它提供曲线编辑、形状构建、画板、排版、图层和专业色彩管理,并支持常见设计文件的导入及多种印刷、网页格式输出。

Capture One Pro Windows版
Capture One Pro Windows版

Capture One Pro 是面向摄影师和影像团队的专业桌面照片处理工具,提供相机定制色彩配置、RAW转换、图层与蒙版、联机拍摄、目录及会话管理等功能。它适合棚拍、人像、商业产品、婚礼和风光摄影,

Adobe Acrobat Pro Windows版
Adobe Acrobat Pro Windows版

Adobe Acrobat Pro 是面向专业 PDF 工作的综合解决方案,可在 Windows 中创建、编辑、转换、比较、整理和保护文档,并支持表单、电子签名、扫描件文字识别及敏感信息永久遮盖。订阅还包含网页、移动服务和云端协作能力,

Adobe After Effects Windows版
Adobe After Effects Windows版

Adobe After Effects 是面向动态图形、动画与影视视觉特效制作的专业工具,可完成关键帧动画、图层合成、遮罩跟踪、抠像、文字动画和二维三维元素整合。Windows 版通过 Adobe Creative Cloud 安装及更新,

DaVinci Resolve Windows版
DaVinci Resolve Windows版

DaVinci Resolve是Blackmagic Design推出的一体化影视后期工具,将素材管理、非线性剪辑、专业调色、Fusion视觉特效、Fairlight音频处理和成片交付整合在统一工程中。免费版已覆盖多数个人创作需求,