极简 Python:数据类型与不变性 一个迂腐的观点 数据类型在哪儿?!? 不变的真相 警告:匈牙利命名法 演员招募 被……挂起 字符串函数回顾

2025-06-08

非常简单的 Python:数据类型和不变性

迂腐的观点

数据类型在哪里?!?

不变的真理

警告:匈牙利命名法

试镜

悬而未决

功能

审查

喜欢这些文章吗?那就买本书吧! Jason C. McDonald 的《Dead Simple Python》现已由 No Starch Press 出版。


我收到了Damian Rivas对这个系列的精彩评论......

我刚刚读完了目前发布的前两部分。不得不说,Python 差不多是我接触的第五门语言了,我真的很欣赏这种教学风格!很难找到不以“什么是变量”开头的教材,哈哈。

不想让人失望,达米安,但我无法永远避免变数!

好了好了,我就不跟你们解释变量了,第 2,582,596 个解释。你们很聪明,我相信你们现在应该都懂了。

既然我们已经准备好编写代码了,我觉得有必要聊聊Python 中的变量是什么。顺便说一下,我们先来了解一下函数、字符串,以及其他那些枯燥乏味的东西……其实它们在底层可能并没有那么枯燥。这里面有很多信息,但我相信,把它们放在一起理解会更有道理。

欢迎来到 Python。进入兔子洞时请注意家具。

迂腐的观点

我在整个系列中都使用“变量”这个术语,主要是因为它是跨语言的标准术语。在 Python 中使用该术语是有效的,甚至在官方文档中也得到了认可。

然而,Python 变量的技术术语实际上是name;它与我稍后将提到的“名称绑定”的整个概念有关。

使用任何你觉得舒服的术语就好。只要理解 Python 的“变量”官方说法是“名称”,你很可能听到这两种说法。

数据类型在哪里?!?

2011 年夏天,我坐在华盛顿州西雅图的门廊秋千上,登录了 Freenode IRC 聊天室。我刚刚决定将语言从 Visual Basic .NET 切换到 Python,我有一些问题想问。

我加入#python并立即投入其中。

如何在 Python 中声明变量的数据类型?

不一会儿,我就收到了回复,我认为这是我第一次真正进入奇妙的编程世界。

<_habnabit> 你是一个数据类型

他和其他常客很快就给我讲解了。Python是一种动态类型语言,这意味着我不需要告诉语言变量中应该包含什么样的信息。我甚至不需要使用特殊的“变量声明”关键字。我只需赋值即可。

netWorth = 52348493767.50
Enter fullscreen mode Exit fullscreen mode

正是在那一刻,Python 成为了我最喜欢的语言。

然而,在我们忘乎所以之前,我必须指出Python 仍然是一种强类型语言

嗯,动态类型?强类型?这些是什么意思?

  • 动态类型:变量(对象)的数据类型在运行时确定。与“静态类型”相对,“静态类型”是指初始时声明对象的数据类型。(C++ 是静态类型的。)

  • 强类型:该语言对不同类型的操作有严格的规定,例如将整数和字符串相加。与之相对的是“弱类型”,在弱类型中,该语言几乎允许你执行任何操作,并且会自动帮你完成。(JavaScript 是弱类型的。)

(如果您想要更高级的解释,请参阅为什么 Python 是一种动态语言,也是一种强类型语言)。

换句话说:Python 变量数据类型,但语言会自动找出该数据类型。

因此,我们可以重新分配一个变量来包含我们想要的任何数据......

netWorth = 52348493767.50
netWorth = "52.3B"
Enter fullscreen mode Exit fullscreen mode

...但我们能做的有限...

netWorth = 52348493767.50
netWorth = netWorth + "1 billion"
>>> Traceback (most recent call last):
>>>  File "<stdin>", line 1, in <module>
>>> TypeError: unsupported operand type(s) for +: 'float' and 'str'
Enter fullscreen mode Exit fullscreen mode

如果我们需要知道某个变量的类型,可以使用该type()函数。它会打印出该变量所属的。(在 Python 中,一切都是对象,所以要学会面向对象。)

netWorth = 52348493767.50
type(netWorth)
>>> <class 'float'>
Enter fullscreen mode Exit fullscreen mode

在对某个数据类型进行操作之前,我们可能确实需要检查一下它的类型。为此,我们可以将type()函数与is运算符配对,如下所示:

if type(netWorth) is float:
    swimInMoneyBin()
Enter fullscreen mode Exit fullscreen mode

然而,在很多情况下,使用 可能更好,因为这将考虑子类和继承(面向对象编程,有人吗?)额外isinstance()type()好处是,函数本身返回 True 或 False...

if isinstance(netWorth, float):
    swimInMoneyBin()
Enter fullscreen mode Exit fullscreen mode

事实上,我们很少用 来检查。Python 爱好者更喜欢鸭子类型isinstance()的哲学;也就是说,我们不是检查类型是什么,而是直接寻找对象所需的特性。如果它看起来像鸭子,走起来像鸭子,叫起来也像鸭子,那它肯定就是鸭子。至于它实际上是一只机器鸭子,还是一只穿着鸭子服装的驼鹿,那就无所谓了;如果它具备我们需要的特性,那么其余的通常就没什么意义了。

不变的真理

由于我刚刚介绍了该is操作符,我们最好澄清一些事情:is不要==做同样的事情!

许多 Python 新手发现这很有效......

richestDuck = "Scrooge McDuck"

if richestDuck is "Scrooge McDuck":
    print("I am the richest duck in the world!")

if richestDuck is not "Glomgold":
    print("Please, Glomgold is only the SECOND richest duck in the world.")

>>> I am the richest duck in the world!
>>> Please, Glomgold is only the SECOND richest duck in the world.
Enter fullscreen mode Exit fullscreen mode

“哦,太酷了!”西雅图一位年轻的开发者说道。“所以,在 Python 中,我只用is‘和’is not来比较。”

错,错,错!那些条件语句虽然有效,但原因却与我想象的不一样。is一旦你尝试这样做,这个错误的逻辑环境就崩溃了……

nephews = ["Huey", "Dewey", "Louie"]

if nephews is ["Huey", "Dewey", "Louie"]:
    print("Scrooge's nephews identified.")
else:
    print("Not recognized.")

>>> Not recognized.
Enter fullscreen mode Exit fullscreen mode

“等等,什么?”你可能会仔细琢磨一下,甚至确认一下 的nephews is nephews计算结果是否为True。那么 dismal downs 到底是怎么回事呢?

问题是,运算is符检查两个操作数是否是同一个实例,而 Python 中存在称为不可变类型的奇怪东西

简单来说,当你有一个整数或字符串之类的东西时,程序内存中实际上一次只有一个这样的数据。之前我创建字符串的时候"Scrooge McDuck",只有一个存在(难道不是一直都存在吗?)。如果我说……

richestDuck = "Scrooge McDuck"
adventureCapitalist = "Scrooge McDuck"
Enter fullscreen mode Exit fullscreen mode

……我们会说 和 都richestDuck绑定adventureCapitalist内存中的这个 实例"Scrooge McDuck"。它们就像一对路标,指向同一个东西,而我们只有一个。

换句话说,如果你熟悉指针,这有点像那样(没有可怕的尖锐边缘)。你可以有两个指针指向内存中的同一个位置。

如果我们修改了其中一个变量,比如说richestDuck = "Glomgold",我们就会重新绑定 richestDuck,使其指向内存中不同的值。(我们也会因为声称 Glomgold 如此富有而感到自豪。)

另一方面,可变类型["Huey", "Dewey", "Louie"]可以在内存中多次存储相同的数据。像 这样的列表就是这种可变类型之一,这就是为什么该is运算符会报告它之前所做的事情。这两个列表虽然包含完全相同的信息,但它们并不是同一个 实例

技术说明:您应该知道,不变性实际上与仅共享一个实例无关,尽管这是一个常见的副作用。这是一种有用的想象方式,但不要指望它总是如此。可以存在多个实例。在交互式终端中运行此代码,以了解我的意思……

a = 5
b = 5
a is b
>>> True
a = 500
b = 500
a is b
>>> False
a = 500; b = 500; a is b
>>> True
Enter fullscreen mode Exit fullscreen mode

不变性背后的真相远比这复杂得多。我的 Freenode#python朋友 Ned Batchelder ( nedbat) 就此发表了一篇精彩的演讲,你绝对应该去看看。

那么,我们应该用什么来代替is?你会很高兴知道,它只是老式的==

nephews = ["Huey", "Dewey", "Louie"]

if nephews == ["Huey", "Dewey", "Louie"]:
    print("Scrooge's nephews identified.")
else:
    print("Not recognized.")

>>> Scrooge's nephews identified.
Enter fullscreen mode Exit fullscreen mode

通常,你应该始终使用==(etc.) 来比较,并is使用 (etc.) 来比较实例这意味着,尽管它们看起来作用相同,但前面的示例实际上应该这样写……

richestDuck = "Scrooge McDuck"

if richestDuck == "Scrooge McDuck":
    print("I am the richest duck in the world!")

if richestDuck != "Glomgold":
    print("Please, Glomgold is only the SECOND richest duck in the world.")

>>> I am the richest duck in the world!
>>> Please, Glomgold is only the SECOND richest duck in the world.
Enter fullscreen mode Exit fullscreen mode

有一个半例外……

license = "1245262"
if license is None:
    print("Why is Launchpad allowed to drive, again?")
Enter fullscreen mode Exit fullscreen mode

检查非值是很常见的,foo is None因为只有一个None非值。当然,我们也可以用更简洁的方式做到这一点……

if not license:
    print("Why is Launchpad allowed to drive, again?")
Enter fullscreen mode Exit fullscreen mode

两种方法都可以,但后者被认为是更干净、更“Pythonic”的方法。

警告:匈牙利命名法

当我还不熟悉该语言时,我突然想到使用系统匈牙利表示法来提醒我想要的数据类型。

intFoo = 6
fltBar = 6.5
strBaz = "Hello, world."
Enter fullscreen mode Exit fullscreen mode

事实证明,这个想法既不新颖,也不高明。

首先,系统匈牙利表示法是对应用程序匈牙利表示法的严重误解,而应用程序匈牙利表示法本身是微软开发人员 Charles Simonyi 的聪明想法。

在 Apps Hungarian 中,我们在变量名开头使用简短的缩写来提醒我们该变量的用途。例如,他在开发 Microsoft Excel 时就使用了这种方法,他会row在任何与行相关的变量开头以及col与列相关的变量开头使用它。这使得代码更具可读性,并且非常有助于防止名称冲突(例如rowIndexvs colIndex)。直到今天,我仍然在 GUI 开发中使用 Apps Hungarian,以区分小部件的类型和用途。

然而,系统匈牙利算法完全忽略了这一点,而是在变量前面加上了数据类型intFoo的缩写,例如或strBaz。在静态类型语言中,这显然是多余的,但在 Python 中,这可能是一个好主意。

然而,这并不是一个好主意,因为它剥夺了动态类型语言的优势!我们可以一会儿把数字存入变量,一会儿又把字符串存入变量。只要我们以某种在代码中合理的方式进行操作,就能释放出静态类型语言所缺乏的大量潜力。但如果我们刻意将每个变量锁定在一个预先确定的类型上,我们实际上就是把 Python 当作静态类型语言,从而在这个过程中束缚了我们自己。

总而言之,系统匈牙利算法不适用于你的 Python 代码。坦白说,它不适用于任何代码。立即从你的代码库中移除它,以后再也不要提它了。

试镜

让我们暂时放下关于不变性的脑力劳动,来谈谈一些更容易理解的事情:类型转换。

不,这不是大卫·田纳特为史高治·麦克老鸭配音的那种类型的演员……尽管他在这个角色中表现得非常出色。

我正在谈论将数据从一种数据类型转换为另一种数据类型,而在 Python 中,这非常容易,至少对于我们的标准类型而言。

例如,要将整数或浮点数转换为字符串,我们只需使用该str()函数。

netWorth = 52348493767.50
richestDuck = "Scrooge McDuck"
print(richestDuck + " has a net worth of $" + str(netWorth))
>>> Scrooge McDuck has a net worth of $52348493767.5
Enter fullscreen mode Exit fullscreen mode

在该print(...)语句中,我能够将所有三个部分连接(组合)成一个要打印的字符串,因为所有三个部分都是字符串print(richestDuck + " has a net worth of $" + netWorth)会失败,TypeError因为 Python 是强类型的(还记得吗?),并且您不能直接组合浮点数和字符串。

您可能会有点困惑,因为是有效的......

print(netWorth)
>>> 52348493767.5
Enter fullscreen mode Exit fullscreen mode

这是因为print(...)函数会在后台自动处理类型转换。但它无法处理那个+运算符——它在数据传递之前就发生了print(...)——所以我们必须自己在那里进行转换。

当然,如果你正在编写一个类,你需要自己定义这些函数,但这超出了本文的讨论范围。(提示:__str__()__int__()分别处理将对象转换为字符串或整数。)

悬而未决

既然我们讨论的是字符串,那么有几点需要了解。最让人困惑的,或许是定义字符串字面量的方法有很多种……

housekeeper = "Mrs. Beakley"
housekeeper = 'Mrs. Beakley'
housekeeper = """Mrs. Beakley"""
Enter fullscreen mode Exit fullscreen mode

'...'我们可以用单引号、双引号"..."或三引号来包裹字面值"""...""",Python 会(大部分情况下)以相同的方式处理它。第三种方式有些特殊,我们稍后再讨论。

Python 风格指南PEP 8解决了单引号和双引号的使用问题:

在 Python 中,单引号字符串和双引号字符串是相同的。本 PEP 对此不做任何建议。请选择一条规则并严格遵守。但是,当字符串包含单引号或双引号字符时,请使用另一个引号,以避免字符串中出现反斜杠。这可以提高可读性。

当我们处理这样的事情时这会很有用......

quote = "\"I am NOT your secretary,\" shouted Mrs. Beakley."
quote = '"I am NOT your secretary," shouted Mrs. Beakley.'
Enter fullscreen mode Exit fullscreen mode

显然,第二种选择可读性更强。引号前的反斜杠表示我们想要的是字面字符,而不是让 Python 将其视为字符串的边界。但是,由于我们包裹字符串的引号必须匹配,如果我们用单引号包裹,Python 会将双引号视为字符串中的字符。

只有在字符串中同时包含两种类型的引号时,我们才真正需要这些反斜杠。

print("Scrooge's \"money bin\" is really a huge building.")
>>> Scrooge's "money bin" is really a huge building.
Enter fullscreen mode Exit fullscreen mode

就我个人而言,在这种情况下,我更喜欢使用(并转义)双引号,因为它们不会像撇号那样引起我的注意。

但请记住,我们还有三重引号 ( """),我们也可以在这里使用。

print("""Scrooge's "money bin" is really a huge building.""")
>>> Scrooge's "money bin" is really a huge building.
Enter fullscreen mode Exit fullscreen mode

不过,在你为了方便起见把所有字符串都用三重引号括起来之前,请记住我说过它们有一些特殊之处。事实上,有两点。

首先,三重引号是多行的。换句话说,我可以用它们来做这件事……

print("""\
Where do you suppose
    Scrooge keeps his
        Number One Dime?""")
>>> Where do you suppose
>>>    Scrooge keeps his
>>>        Number One Dime?
Enter fullscreen mode Exit fullscreen mode

所有内容,包括换行符和前导空格,在三重引号中都是字面意义上的。唯一的例外是,如果我们使用反斜杠 ( \) 来转义某些内容,就像我在开头对换行符所做的那样。我们通常这样做,只是为了让代码更简洁。

内置textwrap模块有一些用于处理多行字符串的工具,包括允许您在不包含它的情况下进行“正确”缩进的工具(textwrap.dedent)。

三重引号的另一个特殊用途是创建文档字符串,它为模块、类和函数提供基本文档。

def swimInMoney():
    """
    If you're not Scrooge McDuck, please don't try this.
    Gold hurts when you fall into it from forty feet.
    """
    pass
Enter fullscreen mode Exit fullscreen mode

这些经常被误认为是注释,但它们实际上是 Python 会执行的有效代码。文档字符串必须出现在其所讨论内容(例如函数)的第一行,并且必须用三重引号括起来。之后,我们可以通过以下两种方式之一访问该文档字符串,如下所示:

# This always works
print(swimInMoney.__doc__)

# This works in the interactive shell only
help(swimInMoney)
Enter fullscreen mode Exit fullscreen mode

特殊字符串类型

我想简单介绍一下 Python 提供的另外两种字符串类型。实际上,它们并不是真正不同的字符串类型——它们都是该类的不可变实例str——只是 Python 对字符串字面量的处理略有不同。

原始字符串前面带有r,例如...

print(r"I love backslashes: \ Aren't they cool?")
Enter fullscreen mode Exit fullscreen mode

在原始字符串中,反斜杠被视为文字字符。原始字符串中的内容不能被“转义”。这会对您使用的引号类型产生影响,因此请务必谨慎。

print("A\nB")
>>> A
>>> B
print(r"A\nB")
>>> A\nB
print(r"\"")
>>> \"
Enter fullscreen mode Exit fullscreen mode

这对于正则表达式模式尤其有用,因为你可能会在模式中包含大量的反斜杠,而这些反斜杠在到达模式之前不会被 Python 解释掉。因此,对于正则表达式模式,请始终使用原始字符串。

警告:如果反斜杠是原始字符串的最后一个字符,它仍然会将结尾的引号转义,从而导致语法错误。这与 Python 自身的词法分析规则有关,而非字符串本身。

另一种字符串“类型”是格式化字符串,或称f-string,它是 Python 3.6 中新增的。它允许你以非常优雅的方式将变量的值插入到字符串中,而无需像之前那样进行连接或转换。

我们在字符串前面加上一个f。在 里面,我们可以用 包裹变量来替换它们{...}。我们把它们放在一起,像这样……


netWorth = 52348493767.50
richestDuck = "Scrooge McDuck"
print(f"{richestDuck} has a net worth of ${netWorth}.")
>>> Scrooge McDuck has a net worth of $52348493767.5.
Enter fullscreen mode Exit fullscreen mode

你不仅可以在花括号 ( {...}) 中输入变量!实际上,你可以将任何有效的 Python 代码放入其中,包括数学运算、函数调用、表达式……任何你需要的内容。

与旧的str.format()方法和%格式(我这里不会介绍)相比,f 字符串要快得多。这是因为它们在代码运行之前就被求值了。

格式化的字符串由PEP 498定义,因此请前往那里获取更多信息。

功能

趁着讲完基础知识,我们来聊聊 Python 函数。我不会再重新定义“函数”来炫耀你的智商了。举个简单的例子就够了。

def grapplingHook(direction, angle, battleCry):
    print(f"Direction = {direction}, Angle = {angle}, Battle Cry = {battleCry}")

grapplingHook(43.7, 90, "")
Enter fullscreen mode Exit fullscreen mode

def说我们正在定义一个函数,然后我们给出函数名,并在括号中给出参数名。哈欠

让我们让它更有趣一点。(以下内容适用于 Python 3.6 及更高版本。)

def grapplingHook(direction: float, angle: float, battleCry: str = ""):
    print(f"Direction = {direction}, Angle = {angle}, Battle Cry = {battleCry}")

grapplingHook(angle=90, direction=43.7)
Enter fullscreen mode Exit fullscreen mode

信不信由你,这才是正宗的 Python!里面有很多精妙的小玩意儿,我们来分解一下。

调用函数

当我们调用一个函数时,我们显然可以按照参数在函数定义中出现的顺序提供参数,就像在第一个例子中一样:grapplingHook(43.7, 90, "")

但是,如果我们愿意,我们实际上可以指定要将哪些值传递给哪个参数。这在很多情况下使我们的代码更具可读性:grapplingHook(angle=90, direction=43.7)。此外,我们实际上不必按顺序传递参数,只要它们都有值即可。

默认参数

说到这里,你有没有注意到,在第二次调用中我省略了 for 的值battleCry,而它却没有生气?那是因为我在函数定义中为参数提供了一个默认值……

def grapplingHook(direction, angle, battleCry = ""):
Enter fullscreen mode Exit fullscreen mode

在这种情况下,如果没有提供 的值,则使用battleCry空字符串。实际上,我可以在那里输入任何我想要的值: ,或者其他任何值。"""Yaargh"None

它很常见地用作None默认值,因此您可以检查参数是否具有指定的值,如下所示......

def grapplingHook(direction, angle, battleCry = None):
    if battleCry:
        print(battleCry)
Enter fullscreen mode Exit fullscreen mode

但是,如果你只是要做这样的事情......

def grapplingHook(direction, angle, battleCry = None):
    if not battleCry:
        battleCry = ""
    print(battleCry)
Enter fullscreen mode Exit fullscreen mode

...此时,您最好从一开始就给出battleCry该默认值。""

陷阱警告:默认参数只计算一次,并在所有函数调用之间共享。这对于可变类型(例如空列表)来说,会产生奇怪的影响[]。不可变类型可以作为默认参数,但应该避免使用可变的默认参数。

警告:您必须在可选参数(具有默认值的参数)之前列出所有必需参数(没有默认值的参数)。这是不行的,因为可选参数在必需参数之前(direction=0, angle, battleCry = None)directionangle

类型提示和函数注释

如果您熟悉 Java 和 C++ 等静态类型语言,这可能会让您有点兴奋……

def grapplingHook(direction: float, angle: float, battleCry: str = "") -> None:
Enter fullscreen mode Exit fullscreen mode

但这并没有达到你想象的效果!

我们可以在 Python 3.6 及更高版本中提供类型提示,它们提供的正是:关于应该传入什么数据类型的提示-> None。类似地,冒号 ( :) 之前的部分提示了返回类型。

然而...

  • 如果传递错误的类型,Python 不会抛出错误。
  • Python 不会尝试转换为该类型。
  • Python 实际上会忽略这些提示并继续执行,就好像它们不存在一样。

那么重点是什么呢?类型提示确实有一些优点,但最直接的优点是文档。函数定义现在会显示它需要什么类型的信息,这在 IDE 会在你输入参数时自动显示提示的情况下尤其有用。某些 IDE 和工具甚至会在你执行一些奇怪的操作时发出警告,比如,将一个字符串传递给类型提示为整数的对象;事实上,PyCharm 在这方面非常擅长!像 Mypy 这样的静态类型检查器也会这样做。我不会在这里讨论这些工具,但可以说,它们确实存在。

我应该特别说明一下,上面的类型提示是一种函数注解,它有各种各样的巧妙用例。这些在PEP 3107中有更详细的定义。

使用Python 3.5 中添加的typing模块,您可以通过多种方式使用类型提示,甚至超越函数定义。

重载函数?

你可能已经猜到了,由于 Python 是动态类型的,我们不太需要重载函数。因此,Python 甚至不提供重载函数!通常只能有一个版本。如果多次定义同名函数,我们定义的最后一个版本将会遮蔽(隐藏)所有其他版本。

因此,如果您希望函数能够处理许多不同的输入,则需要利用 Python 的动态类型特性。

def grapplingHook(direction, angle, battleCry: str = ""):
    if isinstance(direction, str):
        # Handle direction as a string stating a cardinal direction...
        if direction == "north":
            pass
        elif direction == "south":
            pass
        elif direction == "east":
            pass
        elif direction == "west":
            pass
        else:
            # throw some sort of error about an invalid direction
    else:
        # Handle direction as an angle.
Enter fullscreen mode Exit fullscreen mode

注意,我上面省略了类型提示,因为我要处理多种可能性。说实话,这是一个很糟糕的例子,但你明白我的意思了。

陷阱警报:虽然这完全合理,但它几乎总是一种“代码异味”——糟糕设计的标志。你应该isinstance()尽量避免,除非它绝对是解决问题的最佳方法……而且你可能一辈子都无法做到这一点!

返回类型

如果您是 Python 新手,您可能还注意到缺少了一些东西:返回类型。我们实际上并没有直接指定返回类型:我们只是在需要时返回一些值。如果我们想在函数执行过程中退出而不返回任何值,我们可以直接使用return

def landPlane():
    if getPlaneStatus() == "on fire":
        return
    else:
        # attempt landing, and then...
        return treasure
Enter fullscreen mode Exit fullscreen mode

这句话的意思return和说的一样return None,whilereturn treasure会返回 is 的值treasure。(顺便说一句,这段代码不会运行,因为我从来没有定义过 treasure。这只是一个比较简单的示例。)

这种约定让我们可以轻松处理可选的返回值:

treasure = landPlane()
if treasure:
    storeInMoneyBin(treasure)
Enter fullscreen mode Exit fullscreen mode

NoneType真是一件奇妙的事。

提示:您会注意到,本指南中的所有其他函数都缺少return语句。如果函数None执行到末尾仍未找到return语句,则会自动返回;无需在末尾添加语句。

类型提示和默认值

当使用类型提示时,您可能会想这样做......

def addPilot(name: str = None):
    if name is not None:
        print(name)
    else:
        print("Who is flying this thing?!?")
Enter fullscreen mode Exit fullscreen mode

这曾经是可以接受的,但现在已不再被认为是正确的。您应该使用Optional[...]来处理这种情况。

def addPilot(name: Optional[str] = None):
Enter fullscreen mode Exit fullscreen mode

审查

希望你对 Python 的类型系统不再感到困惑,也希望你在探索的过程中没有磕磕绊绊。以下是重点内容:

  • Python 是动态类型的,这意味着它在运行时确定对象的数据类型。

  • Python 是强类型的,这意味着对于对任何给定数据类型的操作都有严格的规则。

  • Python 中的许多数据类型都是不可变的,这意味着内存中只存在数据的副本,并且每个包含该数据的变量都只指向该主副本。可变类型则不会这样做。

  • is检查操作数是否是同一个对象的实例==,而比较值。不要混淆它们。

  • 系统匈牙利命名法(例如intFoo)是个坏主意。请不要这么做。

  • 您可以将字符串括在单引号 ( '...') 或双引号 ( "...") 中。

  • 三引号字符串 ("""...""") 用于多行字符串。它们也可以用于文档字符串,用于记录函数、类或模块。

  • 原始字符串 ( r"\n") 将任何反斜杠视为字面值。这使得它们非常适合正则表达式模式。

  • 格式化字符串(f"1 + 1 = {1+1}")让我们可以神奇地将一些代码的结果替换为字符串。

  • 可以为函数参数指定默认值,使其成为可选参数。所有可选参数都应位于必需参数之后。

  • 类型提示可让您“提示”应将哪种类型的数据传递到函数参数中,但这将被视为建议,而不是规则。

与往常一样,您可以在 Python 文档中找到有关这些主题的更多信息。


感谢deniska、、grymikanobori(Freenode IRC #python)提出的修改建议。

鏂囩珷鏉ユ簮锛�https://dev.to/codemouse92/dead-simple-python-data-typing-and-immutability-41dm
PREV
极简 Python:循环和迭代器 循环概述 一些容器 拆开容器 事物迭代器 你自己迭代器 展望未来 回顾
NEXT
所有酷孩子都在这么做