探索 Python,第 1 部分: Python 的内置数值类型

2019-03-18 22:08|来源: 网络

Python 是一种敏捷的、动态类型化的、极富表现力的开源编程语言,可以被自由地安装到多种平台上(参阅 参考资料)。Python 代码是被解释的。如果您对编辑、构建和执行循环较为熟悉,则 Python 代码对您来说更简单。但是,请不要搞错:Python 器可以是简单的脚本,也可以是大型的复杂程序。事实上,Python 解释器的最大特点是鼓励探索和简化学习过程。如果您想证明这一点,请使用 Python 编写著名的 Hello World! 程序:

  1. 启动 Python 解释器。在 UNIX 系统(包括 Mac OS X)中,启动解释器通常包括在命令提示行键入 python;在 Microsoft® Windows® 系统中,启动 Python 命令 shell。

  2. 在 Python 提示行中,在三个大于号 (>>>) 标志后输入 print 'Hello World!',然后按 Enter

  3. 完成:没有第三步了。清单 1 显示了此命令的输出。


清单 1. 用 Python 编写的 "Hello World" 的输出
rb% python
Python 2.4 (#1, Mar 29 2005, 12:05:39) 
[GCC 3.3 20030304 (Apple Computer, Inc. build 1495)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'Hello World!'
Hello World!

您可以看到,我使用的是运行于 Apple OS X 系统上的 Python V2.4。但是,不管操作系统是什么,基本原理都是一样的,而且在本例中,所用的是 Python 的哪一个实际版本也无所谓。我虽然不了解您,但是此 Hello World! 练习比我学过的 C、C++ 甚至 Java™ 语言的对应练习容易多了。这种简单性就是使用 Python 解释器的主要优点之一。开发人员可以快速试验一个想法、研究一种对象属性或不同算法,而无需编译、执行和测试任何代码。

Python 类型层次结构

从其他语言过渡到 Python 编程语言时需要学习的最重要的课程之一是,Python 中的每样东西都是对象。这一点可能并没有什么特别之处,尤其是对于熟悉面向对象的语言(如 C++、Java 或 C#)的人来说。然而,Python 的面向对象原理与其他语言不同,主要表现在两个方面:第一,Python 中的所有数据值都被封装在相关对象类中。第二,Python 程序中的所有东西都是可以从程序访问的对象,即使是您编写的代码也不例外。

大多数流行的编程语言都有多个内置的数据类型,在这一方面 Python 也一样。例如,C 编程语言具有整型和浮点类型。由于谱系相同,Java 语言和 C# 具有内置类型也不足为奇。这意味着在 C 程序中,可以编写 int i = 100 来创建和初始化整型变量。在 Java 和 C# 中,此方法也是可能的,而且使用它们的自动装箱功能,在需要时这两种语言还可以把这种简单的内置类型转换为 Integer 对象。

另一方面,Python 不包含像 int 这样的简单类型 —— 只有对象类型。如果 Python 中需要整数值,将整数赋值给相应变量(如 i = 100 )即可。在后台,Python 将创建一个整数对象,并将对新对象的引用赋值给变量。问题的关键是:Python 是一种动态类型化语言,所以无需声明变量类型。事实上在单个程序中,变量的类型是可以改变(多次)的。

一种直观演示动态类型化工作方式的简单方法是,设想单个名为 PyObject 的基类,让 Python 中的所有其他对象类型都继承它。在这一模型中,您创建的所有变量都将引用在总的类层次结构中创建的对象。如果您还让 PyObject 类记录曾创建并分配给变量的子类的实际类型或名称,则 Python 程序可正确确定程序执行过程中需要采取的步骤。

上一段描述 Python 的面向对象的模型图像是对 Python 的实际工作方式很好的模拟。除此之外,Python 还可以使用类型函数来简化对变量类型的确定。(本例还介绍如何使用带有 # 字符的内联注释。)


清单 2. 演示 Python 简单类型
>>> i = 100 # Create an int object whose value is 100
>>> type(i)
<type 'int'>
>>> f = 100.0
>>> type(f)
<type 'float'>

可以将 PyObject 类之下的所有 Python 类划分为 Python 运行时解释器可以使用的四个主要类别:

  • 简单类型 —— 基本构建块,如 intfloat

  • 容器类型 —— 保存其他对象。

  • 代码类型 —— 封装 Python 程序的元素。

  • 内部类型 —— 程序执行期间使用的类型。

到本系列结束时,我会把所有不同类别都介绍给大家。但是在这第一篇文章中,我重点介绍简单类型。

简单类型

Python 有五个内置的简单类型:boolintlongfloatcomplex。这些类型是不可变的,就是说整数对象一旦创建,其值便不可更改。相反,系统将创建新的简单类型对象并将其赋值给变量。通过 Python id 函数,可以查看基本 PyObject 标识的变更方式:


清单 3. 使用 Python id 函数
>>> i = 100 
>>> id(i)
8403284
>>> i = 101
>>> id(i)
8403296

此方法看似容易丢失对象,会导致内存泄漏。但是,Python 像 C# 和 Java 一样,使用了垃圾回收功能,以释放用于保存不再引用的对象的内存,如上例中用于保存 100 的整数对象。

布尔类型

Python 中最简单的内置类型是 bool 类型,该类型包括的对象仅可能为 TrueFalse


清单 4. bool 类型
>>> b = True
>>> type(b)
<type 'bool'>
>>> id(b)
1041552

因为只有两个可能值,所以布尔类型是惟一的。Python 解释器提供这仅有的(也是必需的)两个 bool 对象:TrueFalse。在任何时候,在 Python 程序需要这些对象时,变量只能相应地引用其中一个值。清单 5 显示 bb 变量如何具有同一个 id,不管您直接赋予它 b 变量的值还是直接赋予它 True 对象。


清单 5. bb 变量的值
>>> b = True
>>> id(b)
1041552
>>> bb = b
>>> id(bb)
1041552
>>> bb = True
>>> id(bb)
1041552

布尔对象名称的大小写是至关重要的,因为 true(和 false)是未定义的:


清单 6. 未定义的 true 和 false
>>> b = true
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
NameError: name 'true' is not defined

在这一点上,bool 类型可能看起来不是很有用。不过顾名思义,布尔表达式是依赖于名称的,如下所示:


清单 7. 布尔表达式
>>> b = 100 < 101
>>> print b
True

很多程序利用布尔表达式,Python 提供一整套布尔比较和逻辑运算,详细信息请分别参见表 1 和表 2。

表 1. Python 中的布尔比较运算符

运算符描述示例
<小于i < 100
<=小于等于i <= 100
>大于i > 100
>=大于等于i >= 100
==相等i == 100
!=不相等(另外使用 <>)i != 100

补充一点,表 1 中列出的运算符优先级都一样,除非将表达式置于括号中,否则按从左到右的顺序应用。

表 2. Python 中的逻辑运算符

运算符描述示例
not逻辑非not b
and逻辑与(i <= 100) and (b == True)
or逻辑或(i < 100) or (f > 100.1)

逻辑运算符的优先级低于单独的比较运算符,这一点意义重大,因为必须先计算比较运算符,然后才能计算逻辑运算符。逻辑运算符的实际优先级就是表 2 中罗列这些运算符的顺序。

在 Python 中,关于 orand 逻辑运算符有意思的是,它们都是快捷运算符。简言之,如果给定表达式 x or y,则仅当 xFalse 时才会计算 y。同样地,如果给定表达式 x and y,则仅当 xTrue 时,才会计算 y。此功能可以增强表达式求值的性能(尤其是针对长的或复杂的表达式),然而对于习惯于从其他语言学来的不同规则的程序员而言,则容易犯错。

数值类型

Python 中其他四个简单的内置类型都是数值类型:intlongfloatcomplex。在程序中,数值类型很常见,不管使用的是什么语言。Python 对算术运算提供完整支持,包括加法、减法、乘法和除法(参见表 3)。

表 3. Python 中的算术运算

运算符描述示例
*i * 100
/i / 100
//整除i // 100
%取余f % 100
+i + 100
-i - 100

乘法和除法运算符(表 3 中列出的前四个)具有高于加法和减法的优先级。如前所述,您可以通过使用括号分组子表达式,将其分离出来以提高优先级。

Python 与 Java 语言不同,Java 语言通常定义允许的数值类型的范围,而 Python 在这一点上更像 C,因为它的类型范围是依赖于平台的。您可以使用 intlong 两种类型来保存整数值,它们的不同点在于 int 是一种 32 位的整数值。因而,它被限制为只能保存从 -232 到 232 - 1 之间的值(在多数平台上)。与此相反,长整数类型的精度不受限,仅计算机内存对它有影响。要通知 Python 应该按照长类型处理整数,只需将 L 附加到数字的末尾,如 100L。在 Python 中,浮点值始终是按双精度处理的;因此 Python 的 float类型对应于 C 类语言中的双精度。

与数值类型相关的其他两个重点是常量(如上例中的 100,只是明确表达的数字)和位运算。程序员一般在十进制系统(以 10 为基数)中工作。但是,有时其他系统也相当有用,尤其是我们知道计算机是基于二进制的。Python 可以提供对八进制(以 8 为基数)和十六进制(以 16 为基数)数字的支持。要通知 Python 应该按八进制数字常量处理数字,只需将零附加在前面。将一个零加上一个 x 附加在数字的前面是告诉 Python 按十六进制数值常量处理数字,如以下代码所示:


清单 8. 通知 Python 按十六进制数值常量处理数字
>>> print 127    # Using decimal literal
127
>>> print 0177   # Using octal literal
127
>>> print 0x7F   # Using hexadecimal literal
127

当您具有容易的方式来表达数值常量时,尤其是十六进制,就可以容易地构建对应于特定测试用例的标志,这是一种常见的编程技术。例如,一个 32 位的整数可以存储 32 个标志值。使用位测试,可以容易地测试标志变量上的特定标志。Python 中位运算的完整列表如表 4 所示。

表 4. Python 中的位运算

运算符描述示例
~按位求补~b
<<向左位移b << 1
>>向右位移b >> 1
&按位和b & 0x01
^按位异或b ^ 0x01
|按位或b | 0x01

至此,您可能想知道不同数值类型在单个表达式中混合出现的时候怎么办。简单的答复是,Python 会根据需要将表达式中的所有操作数转换为最复杂的操作数的类型。复杂度的顺序是:intlongfloatcomplex(非双关),下面是一个简单的示例:


清单 9. Python 将所有操作数转换为最复杂的操作数
>>> 1 / 3
0
>>> 1.0 / 3
0.33333333333333331
>>> 1.0 // 3
0.0
>>> 1 % 3
1
>>> 1.0 % 3
1.0

尽管 Python 会与您预期的一样转换操作数,但是语言并不基于运算符转换操作数,如 1/3 示例中所示,其计算结果为整数。如果要强制取得浮点结果,则必须确保操作数中至少有一个为浮点类型。

complex 类型

最后一种类型 complex 可能是大多数程序员难以识别的,因为它不是其他编程语言中常见的内置数据类型。而对于工程师和科学家来说,复数却是个司空见惯的概念。从形式上讲,复数 具有实部和虚部两个部分,都由 Python 中的 float 类型来表示。虚数 是 -1 的平方根的倍数,用 ij 表示 —— 取决于您被培养为科学家还是工程师。在 Python 中,复数的虚部被表示为 j


清单 10. 复数的虚部
>>> c = 3.0 + 1.2j
>>> print c
(3+1.2j)
>>> print c.real, c.imag
3.0 1.2

本例是一个实部为 3.0 和虚部为 1.2 的复数。注意,通过使用复杂对象的 realimag 属性,即可访问复数的不同部分。

它们真是对象吗?

到此为止,我已经介绍了 Python 只处理对象类型,然而示例中好像并没有什么对象。最后还有一个问题,构造函数在哪里?对于简单的内置数据类型,Python 替您做了大量的工作。不过,构造函数还在那里(其名称与相关数据类型的名称相同),如果您愿意,可以直接使用它们,如下所示:


清单 11. Python 构造函数
>>> b = bool(True)
>>> i = int(100)
>>> l = long(100)
>>> f = float(100.1)
>>> c = complex(3.0, 1.2)
>>> print b, i, l, f, c
True 100 100 100.1 (3+1.2j)

结束语

Python 是一种无比简单又功能强大的语言。入门极其容易,尤其是对于已经具有 C 类语言的经验的程序员来说。本文简单介绍了 Python 编程语言和内置数据类型:boolintlongfloatcomplex。如果您尚未理解,则请启动一个 Python 解释器,并尝试按照我上面讨论的方法操作。您将会很高兴,我做到的您也可以做到。


本文链接:探索 Python,第 1 部分: Python 的内置数值类型,转载请注明出版:http://www.656463.com/article/605

相关问答

更多
  • n=None while not isinstance(n,int): n1=raw_input("Please input a number: ") try: n=eval(n1) except: n1=raw_input("Please input a number: ") #try-except对排除了输入为字符串的情况。因为由字母构成的字符串是不能eval的,可是'123'可以被eval #isinstance(*,int)是检测*是否为整数的方法。 呵呵,感觉这种要求导致的代码相当awkward呀 ...
  • 常用基本数据类型. int 整型 boolean 布尔 string 字符串 list 列表 tuple 元祖 dict 字典
  • Python数值类型[2024-01-05]

    第三个选项不是,它是个字符串。 这里有详细的数字类型介绍Python 数字类型 详解
  • 使用内置函数id,返回对象的标识来理解下: >>> a=1 >>> id(a) 31118360L >>> a=2 >>> id(a) 31118336L >>> b=[] >>> id(b) 44908360L >>> b.append(1) >>> id(b) 44908360L >>> a="hello" >>> id(a) 44919944L >>> a += " world" >>> id(a) 44958608L 可以看出对于整数和字符串,值的改变实际代表对象本身id变了,也就是变量名绑定到了新 ...
  • import types type(x) is types.IntType # 判断是否int 类型 type(x) is types.StringType #是否string类型
  • 关于python[2022-08-08]

    An event can be thought of as a moment in time when something important happens. The problem is, if we want to know when the event happens, we have to watch for it, and that can be expensive. Imagine a phone that, instead off ringing, flashed a light that ...
  • 大多数内置类型不是直接弱引用的(例如str,int,float,list,dict,None),并且还有一些甚至不能通过子类进行创建(例如CPython中的元组)。 Raymond Hettinger在2005年3月至2005年的python-list文章中可以找到关于几种内置类型的weakrefs底层实现的一些细节。 Most of the built-in types are not directly weak referenceable (e.g. str, int, float, list, dic ...
  • 你试过pydoc吗? pydoc包 与调用帮助函数相同,但您可以从命令行执行此操作,当然,您可以使用点表示法浏览到模块,类或函数级别。 Have you try pydoc pydoc package Is the same as calling the help function but you can do it from the command line, and of course you can browse to a module, class or function level with th ...
  • 你是对的: 对这个类的需求已经在很大程度上被直接从dict子类化(从Python 2.2版开始可用的功能)所取代。 在引入dict之前,UserDict类用于创建类似字典的子类,通过覆盖现有方法或添加新方法来获得新的行为。 注意第一句。 这来自UserDict的文档 。 哦,在Python 3中它已经不存在了。 You're right: The need for this class has been largely supplanted by the ability to subclass direct ...
  • 来自文档 : 重新加载内置或动态加载的模块通常不是很有用。 不建议重新加载sys , __main__ , builtins和其他关键模块。 在许多情况下,扩展模块不是设计为多次初始化,并且在重新加载时可能以任意方式失败。 From the docs: It is generally not very useful to reload built-in or dynamically loaded modules. Reloading sys, __main__, builtins and other key ...