请列出python的至少三种不可变数据类型,不可变数据类型Python
Yyds干货库存
现在我已经准备好写代码了,我认为值得探究一下Python中有哪些变量。在讨论过程中,我们将会看到函数、字符串和所有其他无聊的东西.不会像看起来那么无聊。这里有很多信息,放在一起理解很有意思。
欢迎来到Python的奇妙世界。
前言我在整个系列中使用术语“变量”,主要是因为它是一个跨语言的标准术语。在Python中使用这个术语是有效的,甚至在官方文档中也得到了认可。
但是,Python变量的技术术语其实是name这与我稍后将提到的“名称绑定”的整个概念有关。
使用任何你喜欢的术语。只知道Python“变量”的官方叫法是“名字”,你很可能会同时听到这两种情况。
2018年夏天,我坐在家里的沙发上,登录了GitHub。刚决定把语言从PHP换成Python,有一些疑问。
我加入了#python项目。
如何在Python中声明变量的数据类型?
过了一会儿,我收到了回复。我想这是我第一次真正进入陌生的python编程世界。
_habnabit您是一种数据类型
他和其他节目朋友很快回答了问题。Python是一种动态类型语言,这意味着我不必告诉语言变量它们包含什么样的信息。我甚至不必使用特殊的“变量声明”关键字。我只需要直接赋值,和PHP很像。
NetWorth=52348493767.50那一刻,Python成了我最喜欢的语言。
然而,在我们得意忘形之前,我必须指出Python仍然是一种强类型语言。
嗯,动力型的?强势型?这一切意味着什么?
动态类型:变量(对象)的数据类型在运行时确定。与“静态类型”相比,我们首先声明对象的数据类型。(C是静态类型。)强类型:这种语言对不同数据类型的操作有严格的规则,比如将整数和字符串相加。相对于“弱型”,这种语言几乎可以让你做任何事情,它会为你解决问题。(Javascript/PHP是弱类型的。)所以,换句话说:Python变量有一个数据类型,但是语言会自动确定那个数据类型是什么。
因此,我们可以重新分配一个变量来包含我们想要的任何数据。
净值=52348493767.50
NetWorth=52.3B ,但是我们能做的有限。
净值=52348493767.50
净值=净值“10亿”
回溯(最近一次呼叫):
模块中文件 stdin 的第1行
类型错误:不支持的操作数类型:“float”和“str”如果我们需要知道变量的类型,可以使用Type()函数。这将打印出变量是哪种类型的类实例。(在Python中,一切都是对象,所以戴上面向对象的帽子。)
净值=52348493767.50
类型(净值)
我们实际上可能想在使用它之前检查数据类型是什么。为此,我们可以将type()函数与is运算符配对,如下所示:
如果类型(净值)是float:
SwimInMoneyBin()但是,在很多情况下,使用isinstance()可能比type()更好,函数本身返回True或False。
如果是实例(净值,浮点):
SwimInMoneyBin()现在事实是我们很少用isinstance()检查,也就是说我们不需要检查类型是什么,只是简单的在对象上查找我们需要的特性。如果它长得像鸭子,走路像鸭子,叫起来像鸭子,那它一定是鸭子。不管它实际上是一只机器鸭还是一只穿着鸭子服装的驼鹿;如果它有我们需要的特征,那么剩下的通常是有争议的。
不变性原理虽然我刚介绍了运算符is,但是最好澄清一下:不要用is和==!
许多Python新手发现这很有效.
里奇斯达克=史高治麦克老鸭
如果richestDuck是“史高治麦克老鸭”:
打印(我是世界上最富有的鸭子!)
如果richestDuck不是“Glomgold”:
print(‘拜托,格洛金只是世界上第二富有的鸭子。’)
我是世界上最富有的鸭子!
拜托,glom gold只是世界上第二有钱的鸭子。“哦,太酷了!”一位年轻的开发商说。"所以,在Python中,我只使用is和not进行比较."
不对,不对,不对。这些条件语句是有效的,但它们不是我所想的那样。一旦你尝试了,这个错误的逻辑就会崩溃。
侄子=[休伊,杜威,路易]
如果nephews是[Huey , Dewey , Louie]:
打印(“斯克罗吉的侄子确定。”)
否则:
打印(“无法识别。”)
不认可。你可能会对此做一点研究,甚至确认侄子就是侄子的计算结果是真的。那么令人沮丧的结果是什么呢?
麻烦的是,操作is operator检查两个操作数是否是同一个实例,而Python中这些有趣的东西被称为不可变类型。
简单来说,当你有一个整数或者字符串之类的东西时,程序的内存中实际上只有一个数据。以前,当我创建字符串“史高治麦克老鸭”时,只有一个存在(它不是一直存在吗?)如果我说.
里奇斯达克=史高治麦克老鸭
冒险资本家=史高治麦克老鸭.我们会说,无论是富人还是冒险资本家都与记忆中的这个“史高治麦克老鸭”有着千丝万缕的联系。它们就像几个路标,都指向只有一个相同事物的存在。
换句话说,如果你熟悉指针,那就有点像。这相当于有两个指针指向内存中的同一个位置。
如果我们改变其中一个变量,比如richestDuck=Glomgold ,我们将重新绑定richestDuck,使其指向内存中的不同位置。
另一方面,可变类型可以在内存中多次存储相同的数据。列表,比如[Huey , Dewey , Louie],就是这些可变类型之一。也就是说,当用is比较两个相同的数据时,将返回False。虽然这两个列表包含相同的信息,但它们不是同一个实例。
技术说明:你应该知道不变性与只共享某个事物的一个实例无关。这是一种有用的想象方式,但不要期望它总是这样。可以有多个实例。在不同的交互终端中,运行结果会有所不同。
a=5
b=5
a是b
真实的
a=500
b=500
a是b
错误的
a=500b=500a是b
真实的
a= AVeryVeryVeryVeryLongString
b= AVeryVeryVeryVeryLongString
a是b
真实的
a=a b
b=a b
a是b
false不变性背后的原理实际上要复杂得多。有兴趣的可以去了解一下。以下是几点:
在交互模式下,每个字符串文字会申请一个新的字符串,但只有大小写字母、数字和下划线会被intern,即维护一个dict使这些字符串全局唯一;而这段代码在py文件中执行时,第二个也成立,因为它会不断地用内置的小对象池合并单字符串和空字符串,所以测试会是只实现cpy,全局只使用cpy的情况,这意味着:第一,其他实现不一定保证;第二,如果你用C扩展了一个py模块,构造了一个已经在C中实习过的string或者小对象,这个string对象在返回到py环境的时候是合法对象,但是地址明显和你之前用的不一样,也就是说你不要以为在cpy下可以依赖这个特性。
那么,我们应该用什么来代替is呢?其实可以用原来的==。
侄子=[休伊,杜威,路易]
如果侄子==[休伊,杜威,路易]:
打印(“斯克罗吉的侄子确定。”)
否则:
打印(“无法识别。”)
斯克里奇的侄子们认出了。通常,您应该始终使用==来比较值和is比较实例。含义,虽然它们看起来作用相同,但实际上,is是检查两个对象是否指向同一个内存空间,而==是检查它们的值是否相等。可以看出is是比==更严格的检查,is返回True说明这两个对象指向同一块内存,值必须相同。
里奇斯达克=史高治麦克老鸭
如果richestDuck==史高治麦克老鸭:
打印(我是世界上最富有的鸭子!)
如果richestDuck!=Glomgold :
print(‘拜托,格洛金只是世界上第二富有的鸭子。’)
我是世界上最富有的鸭子!
拜托,glom gold只是世界上第二有钱的鸭子。有一个例外。
许可证=1245262
如果许可证为无:
print(为什么Launchpad又被允许驱动了?)检查一个非值有点常见,foo是None因为只有一个None存在。当然,我们也可以用简写的形式。
如果没有许可:
print(为什么Launchpad又被允许驱动了?两种方式都好,虽然后者被认为是更简单更合理的方式。
匈牙利符号当我刚接触这种语言时,我有了一个“绝妙”的想法,即使用系统匈牙利符号来提醒我想要的数据类型。
intFoo=6
fltBar=6.5
StrBaz=你好,世界事实证明,这个想法既不新颖,也不优秀。
首先,系统匈牙利符号是对应用程序匈牙利符号的误解,它是微软开发人员查尔斯西蒙尼的聪明想法。
在匈牙利语的Apps中,我们在变量名的开头使用一个简短的缩写来提醒我们变量的用途。例如,他在Microsoft Excel的开发中使用了这种方法,他在与行相关的任何变量的开头使用row,在与列相关的任何变量的开头使用col。这使得代码可读性更好,并有助于防止名称冲突(例如,rowIndex vs colIndex)。今天,我在GUI开发中使用Apps Hungarian来区分小部件的类型和用途。
但是Systems Hungarian忽略了这一点,在变量前面加上了数据类型的缩写,比如intFoo或者strBaz。在静态类型语言中,这是非常多余的,但在Python中,这可能是一个好主意。
然而,它不是一个好主意的原因是它剥夺了动态类型语言的优势!我们可以在某个时候在一个变量中存储一个数字,然后转过来在里面存储一个字符串。只要我们在代码中以某种有意义的方式做到这一点,我们就可以释放静态类型语言所缺乏的许多潜力。然而,如果我们在精神上把自己锁定在每个变量的预定类型中,我们实际上是把Python当作一种静态类型语言,使我们在这个过程中变得犹豫不决。
不过,匈牙利系统在您的Python编码中没有位置。坦率地说,它在任何编码中都没有位置。立刻从你的军火库里避开它,让我们再也不要谈论它。
类型转换让我们从一成不变的脑筋急转弯中休息一下,谈谈更容易理解的东西:类型转换。
我说的是将数据从一种数据类型转换成另一种数据类型,在Python中,这几乎是最简单的,至少对于我们的标准类型来说是这样。
例如,要将整数或浮点数转换成字符串,我们只需使用str()函数。
净值=52348493767.50
里奇斯达克=史高治麦克老鸭
print(richestDuck 的净资产为1,000万美元
Scrooge MC Duck在本刊中的净资产为52348493767.5美元(.)语句,我能够将所有三个部分连接(组合)成一个要打印的字符串,因为这三个部分都是字符串。Print(最富有的鸭子的净值为$ 净值)会有一个TypeError错误,因为Python是强类型的(还记得吗?),而且不能完全拼接浮点数和字符串。
你可能会有点困惑,因为这很管用。
打印(净值)
5348493767.5那是因为这个打印(.)函数会在后台自动处理类型转换。但是它不能对那个操作符做任何事情。这发生在数据被给予打印之前(.)进行处理。所以我们必须自己在那里进行转换。
当然,如果您正在编写一个类,您需要自己定义这些函数,但这超出了本文的范围。(提示__str__()和__int__()进程分别将对象转换为字符串或整数。)
弦当我们讨论弦的时候,有一些关于弦的知识。也许最令人困惑的是,定义字符串的方法有很多种。
管家=比克利夫人
管家=比克利夫人
管家= Beakley夫人 我们可以用单引号将文本括起来 .,双引号 .或者三引号,Python会(大部分)以同样的方式处理。第三种选择有些特别,但我们将回头再来讨论。
Python风格指南PEP 8解决了使用单引号和双引号的问题:
在Python中,单引号字符串和双引号字符串是相同的。本佩普不建议这样。选择一个规则并坚持下去。但是,当字符串包含单引号或双引号时,请使用另一个字符来避免字符串中的反斜杠。它提高了可读性。
这在我们处理这类事情时会派上用场。
“我不是你的秘书,”比克利夫人喊道。
“我不是你的秘书,”比克利夫人喊道。显然,第二种选择可读性更强。引号前的反斜杠意味着我们想要文字字符,而不是让Python把它当作字符串的边界。但是,因为我们包装的字符串的引号必须匹配,如果我们用单引号包装,Python只会假设双引号是字符串中的字符。
我们真正需要这些反斜杠的唯一时间是当我们在字符串中包含两种类型的引号时。
印刷品(“斯克罗吉的‘钱柜’真是一座巨大的建筑。”)
斯克罗吉的“钱柜”真是一座巨大的建筑。就个人而言,在这种情况下,我更喜欢使用(并转义)双引号,因为它们不会像撇号一样逃过我的注意。
但是请记住,我们也有三重引号( ),我们也可以在这里使用。
印刷品(“斯克罗吉的‘钱柜’真的是一座巨大的建筑。”)
斯克罗吉的“钱柜”真是一座巨大的建筑。然而,为了方便起见,在开始用三个引号将所有字符串括起来之前,请记住我说过它们有一些特殊之处。其实有两件事。
首先,三个引号支持多行字符串。换句话说,我可以用它们来做这件事。
打印(“”\
你认为在哪里
斯克罗吉保持他的
头号硬币?)
你认为在哪里
斯克罗吉保持他的
头号硬币?包括换行符和前导空格在内的所有内容都用三个引号表示。唯一的例外是我们使用反斜杠(\)来转义某些东西,就像我在开头使用换行符一样。我们通常这样做只是为了让代码更干净。
内置的textwrap模块有一些处理多行字符串的工具,包括那些允许你“适当地”缩进而不包含它的工具(textwrap.dedent)。
三个引号的另一个特殊用途是创建文档字符串,它为模块、类和函数提供基本文档。
def swimInMoney():
如果你不是史高治麦克老鸭,请不要尝试这个。
当你从四十英尺高的地方掉下来时,金子会痛。
这些过程经常被误认为是注释,但它们实际上是Python评估的有效代码。文档字符串必须出现在它所涉及的任何内容(如函数)的第一行,并且必须用三个引号括起来。稍后,我们可以通过两种方式之一来访问这个文档字符串:
#这总是有效的
打印(swimInMoney。__doc__)
#这只在交互式shell中有效
Help(swimInMoney)特殊字符串类型我想简单介绍一下Python提供的另外两种类型的字符串。实际上,它们并不是真正不同类型的字符串3354。它们都是STR3354类的不可变实例,但是该语言对待字符串和文字略有不同。
例如,原始字符串以R开头.
print(r I love backlass:\他们是不是很酷?)在原始字符串中,反斜杠被视为文字字符。原字符串中没有任何东西可以“转义”。这对你使用的引号类型有影响,所以要小心。
打印( A\nB )
A
B
打印(rA\nB )
A\nB
打印(r )
这对于正则表达式模式尤其有用,在这种模式中,您可能需要大量的反斜杠作为模式的一部分,而不是在它到达之前被Python解释。始终使用正则表达式模式的原始字符串。
注意:如果反斜杠是原始字符串中的最后一个字符,它仍然会转义右引号,从而导致语法错误。这和Python自己的语言词法规则有关,和字符串无关。
字符串的另一种“类型”是格式化字符串或f字符串,这是Python 3.6中的新功能。它允许你以一种非常漂亮的方式将变量值插入到字符串中,而不用像我们以前那样担心连接或转换。
我们在字符串前面加一个F。在内部,我们可以将变量包装在{.}.我们像这样把它们放在一起.
净值=52348493767.50
里奇斯达克=史高治麦克老鸭
print(f“{ richest duck }”的净资产为${netWorth}。)
Scrooge MC鸭净资产52348493767.5美元。您并不局限于花括号({.})要么!实际上,你可以把几乎任何有效的Python代码放在里面,包括数学、函数调用、表达式……任何你需要的东西。
与更老的str.format()方法和% format(这里我就不赘述了)相比,F string要快很多。这是因为代码在运行前会被评估。
格式化字符串由PEP 498定义。你可以去那里获得更多的信息。
在介绍函数基本内容的同时,我们来说说Python函数。我不会用重新定义“功能”来炫耀你的智慧。提供一个基本的例子就足够了。
def抓钩(方向、角度、战斗口号):
print(fDirection={direction},Angle={angle},Battle Cry={battleCry} )
gratching hook(43.7,90, )def表示我们正在定义一个函数,然后我们在括号中提供名字和参数名。
让它更有趣一点。(以下适用于Python 3.6及更高版本。)
def抓钩(方向:浮动,角度:浮动,战斗口号:str= ):
print(fDirection={direction},Angle={angle},Battle Cry={battleCry} )
绘图钩(角度=90,方向=43.7)。信不信由你,这是有效的Python!里面有很多好看的小东西,我们来分解一下。
Call Function当我们调用一个函数的时候,我们显然可以按照参数在函数定义中出现的顺序来提供参数,就像第一个例子中的graffinghook(43.7,90,):
然而,如果我们愿意,我们实际上可以指定将哪些值传递给哪个参数。这使得我们的代码在很多情况下更具可读性:抓钩(角度=90,方向=43.7)。我们实际上不必按顺序传递参数,只要它们都有一个值。
默认参数到此为止。有没有注意到我battleCry在第二次通话中漏了值,它没有生我的气?这是因为我在函数定义中为参数提供了一个默认值。
抓钩(方向,角度,battleCry= ):在这种情况下,如果没有提供battleCry值,则使用空字符串 。实际上我可以在里面放任何我想要的值: Yaargh ,None,或者任何其他值。
通常将它用作缺省值None,这样就可以检查参数是否指定了值,如下所示。
def抓钩(方向、角度、战斗口号=无):
如果战斗口号:
Print(battleCry)但是,如果你只是想做这样的事情.
def抓钩(方向、角度、战斗口号=无):
如果不是战斗口号:
战斗口号=
Print(battleCry)你还不如一开始就给battleCry默认值 。
注意:默认参数只计算一次,并在所有函数调用中共享。这对可变类型有奇怪的影响,比如空列表[]。不可变的东西适用于默认参数,但是你应该避免使用可变的默认参数。
您必须在可选参数(具有默认值的参数)之前列出所有必需参数(没有默认值的参数)。(direction=0,angle,battlecry=none)是不可接受的,因为可选参数direction位于必需参数angle之前。
提示和函数注释如果你熟悉Java和C等静态类型语言,这可能会让你更好地理解.
抓钩(方向:飘,角度:飘,呐喊:str= )-无:但不是你想的那样!
我们可以在Python 3.6及更高版本中提供类型提示,它提供的是:关于应该传入什么数据类型的提示。类似地,冒号(:)-None之前的部分提示返回类型。
然而.
如果你传递了错误的类型,Python不会抛出错误。Python不会尝试转换成这种类型。Python实际上会忽略这些提示,继续前进,就好像它们不存在一样。那么这有什么意义呢?提示确实有一些优点,但最直接的是文档。函数定义现在显示它需要的信息类型,这在您输入参数时IDE自动显示提示时特别有用。如果你在做一些奇怪的事情,比如传递,一些ide和工具甚至可能会警告你字符串类型提示是整数;其实PyCharm很擅长这个!像Mypy这样的静态类型检查器也可以做到这一点。这里不讨论这些工具,只想说它们是存在的。
我应该更清楚地说明,上面那些类型提示是一种带有各种简洁用例的函数注释。这些在PEP 3107中有更详细的定义。
通过Python 3.5中添加的类型模块,您可以以多种方式使用类型提示,甚至超越函数定义。
正如你可能猜到的,因为Python是一个动态类型,所以我们不需要重载函数。因此,Python甚至不提供它们!通常你只能有一个版本。如果多次使用相同的名称定义一个函数,我们定义的函数的最后一个版本将覆盖所有其他同名的函数。
因此,如果您希望您的函数能够处理许多不同的输入,您需要利用Python的动态类型特性。
def抓钩(方向,角度,战斗口号:str= ):
if isinstance(方向,字符串):
#将方向作为表示基本方向的字符串处理.
如果方向==北:
及格
elif方向==南:
及格
elif direction==east :
及格
elif direction==west :
及格
否则:
#抛出某种关于无效方向的错误
否则:
#以角度形式处理方向。请注意,我在上面留下了一个类型提示,因为我正在处理多种可能性。说实话,这是个不好的例子,但只要你懂了。
注意:现在,尽管这是完全正确的,但是您应该尽量避免isinstance(),除非这绝对是解决您的问题的最佳方法.而且你可能整个职业生涯都不会遇到这种情况!
返回类型如果您是Python的新手,您可能还会注意到缺少了一些东西:返回类型。我们实际上并没有直接指定一个:我们只是在需要的时候返回一些东西。如果我们想在函数中途离开而不返回任何东西,我们可以使用return。
def landPlane():
if getPlaneStatus()==on fire :
返回
否则:
#尝试着陆,然后.
回宝Return和return None效果一样,而回宝会回任何值宝。(顺便说一句,这个代码不行,因为我从来没有定义过宝藏。这只是一个例子。)
这种约定使我们很容易处理可选退货:
treasure=landPlane()
如果宝藏:
储钱(宝)nonetype是个好东西。
注意:您会注意到本指南中的所有其他函数都缺少return声明。如果一个函数到了末尾,没有找到返回语句,会自动返回none没必要在最后加一个。
类型提示和默认值在使用类型提示时,您可能需要这样做。
def addPilot(name: str=None):
如果名称不是无:
打印(姓名)
否则:
打印(‘谁在飞这个东西?)这曾经是可以接受的,但现在已经不再被认为是官方正确的了。相反,您应该使用可选的[.]来处理这种情况。
添加Pilot (name: optional [str]=none):总结希望大家不要被Python的类型系统迷惑,再次强调重点:
Python是动态类型的,这意味着它将在运行时确定对象的数据类型。Python是强类型的,这意味着可以对任何给定的数据类型实施严格的规则。Python中的许多数据类型是不可变的,这意味着内存中只存在数据的副本,包含数据的每个变量只指向一个主副本。另一方面,可变类型不会这样做。检查is操作数是否是对象的同一个实例,并且==比较值。不要混淆它们。匈牙利符号(例如intFoo)是个坏主意。请不要这样做。可以用单个“.”将字符串括起来引号()或双引号( . )).三引号字符串( . ))用于多行字符串。它们也可以用于文档字符串来记录函数、类或模块。原始字符串(r\n )将任何反斜杠视为文字。这使得它们非常适合正则表达式模式。格式化字符串(f1 1={1 1} )让我们神奇地用字符串替换一些代码的结果。您可以为函数参数指定默认值,使其成为可选参数。所有可选参数都应该跟在必需参数后面。Type提示您“提示”应该将什么类型的数据传递给函数参数,但这将被视为建议,而不是规则。
原创作品来自程,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。