《从问题到程序:用Python学编程和计算》——2.2 数据对象、计算和类型

简介:

本节书摘来自华章计算机《从问题到程序:用Python学编程和计算》一书中的第2章,第2.2节,作者 裘宗燕,更多章节内容可以访问云栖社区“华章计算机”公众号查看。

2.2 数据对象、计算和类型

前面介绍了Python中可以表示和处理的几种数——整数、浮点数和复数,它们都是数学里的某类数的对应物,可以对它们做各种数学运算(用运算符描述),得到运算的结果。这些数都是程序操作的对象。

2.2.1 对象和类型

虽然整数、浮点数都是数,可以使用同样的运算符,但对数值相同的整数和浮点数做同样计算时,由于采用的规则不同,得到的结果也不同。例如:

>>> 12**30
237376313799769806328950291431424
>>> 12.0**30.0
2.373763137997698e+32

整数计算将得到任意大的准确结果,浮点数计算得到有限精度的近似结果。[ 在Python里,一定范围内的整数通过硬件直接实现,计算效率高。超范围的整数计算通过软件技术模拟,运算可能耗费较多时间。另一方面,浮点数采用硬件实现的计算,统一而高效。]

Python语言把在程序运行中能使用和处理的各种实体统称为对象(object),一个整数是一个对象,一个浮点数也是一个对象。在处理整数或浮点数字面量时,解释器创建相应的整数对象或浮点数对象,而计算也就是从一些对象算出另一些对象。在交互方式下,解释器把计算得到的结果对象显示出来给人看。

不同对象可能具有不同的性质。Python把性质相同、可以使用同一组操作、采用同样计算规则的一集对象称为一个类型。对属于同一类型的对象,解释器采用同样的处理方式。例如,整数就是一个类型,浮点数是另一个类型,复数又是另一个不同的类型。这几个类型有各自的字面量写法、可用运算的集合和运算规则。人们经常把整数类型简称为整型,把浮点数类型简称为浮点型。后面有时也这样说。

Python中的每个类型有一个名字(类型名),可以用特殊的方法得到:

>>> type(100)
<class 'int'>
>>> type(100.0)
<class 'float'>
>>> type(100+0j)
<class 'complex'>

第一个结果 表示字面量100描述的整数对象属于名字为int的类型,其他结果的意义类似。每个类型都有一个名字,称为类型名。整数类型的名字是int,浮点数的类型名是float,而复数的类型名是complex。对于任何描述对象的表达式,都可以用type取得其计算结果的类型:

>>> type(100 + 200)
<class 'int'>
>>> type(1.27 * 2.8)
<class 'float'>

int、float和complex统称为数值类型(numerical type)。这几个数值类型都是Python语言预先定义的类型,称为内置类型或者标准类型。

2.2.2 混合类型计算和类型转换

对数值类型的对象,Python允许做混合类型计算,也就是说,允许在一个表达式里出现不同数值类型的对象。例如:

>>> 2.7 * 3
8.100000000000001
>>> (2 + (1 + 3.4j)) * (5.78 - 3)
(8.34+9.452j)

自然,最后一个表达式得到的是复数类型的结果(对象)。

整数和浮点数各有自己的乘法运算规则,两者的运算规则不同。为了完成两个不同类型的对象之间的运算,Python严格规定了采用的规则。在这里的规定是:如果遇到表达式要求做一个整数和一个浮点数的运算,那么就先从那个整数转换得到一个“与之等值”的浮点数对象,而后再按浮点数的规则计算,得到浮点数结果。如果是整数(或浮点数)与复数运算,就先从该数转换得到一个复数,然后再计算。注意,这里说转换,术语是类型转换,实际上原来的数并不改变,而是根据该数按规则做出另一个满足需要的数。

上面的“与之等值”加了引号,是想说明这个说法并不准确。整数可以任意大,具有任意位精度。用浮点数表示,或许能表示其近似值(因此并不与之等值),甚至无法表示它(由于整数太大而溢出)。这是混合类型计算中可能出现的情况,必须注意。

总结一下:对混合类型的计算表达式,Python解释器将自动安排适当的转换,使表达式描述的计算得以进行。这种转换是解释器自动完成的操作,从已有的某类型对象出发,做出一个与之相关的具有所需类型的对象。在上面第二个例子里,先根据2做出一个复数,再用它与复数(1+3.4j)相加;再从整数3做出一个浮点数并从5.78里减去它;再从第二个计算的结果(一个浮点数)做出一个复数并完成两个复数的乘法。可见,要理解复杂表达式的意义,不仅要关注其中的计算如何进行,还要注意哪些地方出现了类型转换,各为从什么类型转到什么类型,具体计算是在哪个类型里进行的。

有时,自动完成的转换不符合实际计算的需要。出现这种情况时,我们就需要在表达式里说明期望的转换,相应描述称为强制类型转换。强制类型转换通过类型名描述,描述形式与前面写type的形式类似。例如:

>>> int(2.37**5.6) * 4
500

这里int(2.37**5.6)要求把浮点数计算的结果转换为整数,然后用它乘以4得到整数结果。用int将浮点数转换到整数的规则是丢掉小数,取得整数部分。

如果写表达式float(12**20),可以得到括号里整数计算结果的浮点数近似值。但Python不允许用float或int去转换复数对象,数学里也没有相应的规则。如果对不能转换的对象做转换,解释器也会报告错误。例如:

>>> float((2 + 1.2j)**3)
Traceback (most recent call last):
  File "<pyshell#69>", line 1, in <module>
    float((2 + 1.2j)**3)
TypeError: can't convert complex to float

取得复数的实部、虚部或者模的问题在后面说明。

类型名complex可用于构造复数:

>>> complex(12**20, 1.25**20)
(3.833759992447475e+21+86.73617379884035j)

括号里逗号分隔的两个表达式分别表示要构造的复数的实部和虚部。

最后考虑一个实际应用题:已知三角形的三边长度分别为5、7和11厘米,现在希望求出这个三角形的面积。

显然,为完成这个任务,首先需要找到从三边长求面积的方法。数学知识已经给出了相应的面积公式:

image

其中s是三角形的半周长,。根据这些公式,不难写出下面表达式:

>>> ((5 + 7 + 11)/2 * ((5 + 7 + 11)/2 - 5) *
 ((5 + 7 + 11)/2 - 7) * ((5 + 7 + 11)/2 - 11)) ** 0.5
12.968712349342937

为了写出这个长表达式,我们特别在前面多写了一个括号。在表达式换行时,因为有括号没配对,解释器自动把后一行当作续行。显然,这个表达式虽然解决了问题,但其形式不太令人满意,其中出现繁琐的重复。2.5节将解决这个问题。

2.2.3 数值类型和计算的简单总结

现在对本章中至此有关数值类型计算的讨论做一点总结。

Python语言提供了三个基本数值类型:int、float和comlex,规定了各种数字面量的描述形式,以便人们直接描述计算中使用的数值对象。Python的整数对象可以表示任意大的整数值,但浮点数(和复数)只能表示有限范围内精度有限的数值。

表示数值计算的表达式基于数值字面量、算术运算符和括号描述,形式上是一维的单词序列,序列中的单词和序列的构成形式都必须满足表达式的语法要求。满足规定(满足语法)的表达式才有意义(语义)。Python严格规定了单词和表达式的形式,所采用的形式解释器容易处理,人可以接受和习惯。遇到不合法的单词,或者构成形式不合法的表达式,解释器将报错,并能标明发现错误的位置。

合法的表达式描述了一个计算过程。如果解释器处理一个表达式的计算能顺利完成,就会求出该表达式的值。但是,满足语法的表达式在计算中也可能出错,如3/0、3.0/0.0在计算中就会报告除以0的动态运行错误。此外,浮点数运算的结果可能超出浮点数的表示范围,这种情况称为溢出。出现溢出时得到一个特殊结果。

表达式描述的求值过程由多方面的因素确定:运算符有优先级和结合方式,高优先级的运算符先执行,相同优先级的运算符按结合顺序执行。如果由优先级和结合方式默认确定的计算顺序不合适,可以加入括号明确指定所需计算顺序。

算术运算符分为一元运算符(正负号)和二元运算符,对二元运算符,在做它所要求的计算之前,总是先计算其左边的运算对象,再计算右边的运算对象。

参与计算的对象都有类型,计算的结果也有类型,对象的类型决定计算的方式和结果。两个同样类型的数值对象直接参与运算,运算结果一般也具有同样类型(整数除法运算符 / 的情况特殊,其结果是浮点数)。用type可以得到表达式的计算结果的类型(注意,字面量是最简单的表达式)。

如果参与一个二元运算的两个对象的类型不同,解释器先把它们转换为同样类型后再计算。整数与浮点数或复数运算,解释器自动由它做出一个浮点数或复数;浮点数与复数运算,解释器自动由这个浮点数做出一个复数。如果混合类型计算中的自动转换不合乎需要,可以人工描述转换。用类型名int可以构造与给定浮点数对应的整数值(取整)。

应特别注意,做数值转换时可能出错。在把一个整数转换为一个浮点数时,得到的结果可能超出浮点数的表示范围。还需注意,整数计算是精确计算,总得到精确的整数结果(除了使用运算符 / 的情况),浮点数计算和复数计算是近似计算,总得到近似结果,计算中可能出现误差,需要特别当心。这个问题后面还会讨论。

相关文章
|
1天前
|
存储 机器学习/深度学习 数据可视化
Python面板时间序列数据预测:格兰杰因果关系检验Granger causality test药品销售实例与可视化
Python面板时间序列数据预测:格兰杰因果关系检验Granger causality test药品销售实例与可视化
31 6
|
1天前
|
API Python
Python模块化编程:面试题深度解析
【4月更文挑战第14天】了解Python模块化编程对于构建大型项目至关重要,它涉及代码组织、复用和维护。本文深入探讨了模块、包、导入机制、命名空间和作用域等基础概念,并列举了面试中常见的模块导入混乱、不适当星号导入等问题,强调了避免循环依赖、合理使用`__init__.py`以及理解模块作用域的重要性。掌握这些知识将有助于在面试中自信应对模块化编程的相关挑战。
14 0
|
1天前
|
机器学习/深度学习 数据采集 供应链
从数据到决策:scikit-learn在业务分析中的应用
【4月更文挑战第17天】本文探讨了scikit-learn在业务分析中的应用,包括数据预处理、分类、回归和聚类模型的构建,以及模型评估与优化。通过使用scikit-learn,企业能有效处理数据、预测趋势、客户细分并制定决策,从而提升经营效率和市场策略。随着机器学习的发展,scikit-learn在业务分析领域的潜力将持续释放,创造更多价值。
|
1天前
|
算法 数据可视化 Python
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
Python中LARS和Lasso回归之最小角算法Lars分析波士顿住房数据实例
|
2天前
|
BI 开发者 数据格式
Python代码填充数据到word模板中
【4月更文挑战第16天】
|
2天前
|
数据可视化 算法 API
Python数据可视化-seaborn Iris鸢尾花数据
Python数据可视化-seaborn Iris鸢尾花数据
|
2天前
|
Python
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
python面型对象编程进阶(继承、多态、私有化、异常捕获、类属性和类方法)(上)
22 0
|
2天前
|
索引 Python
python 格式化、set类型和class类基础知识练习(上)
python 格式化、set类型和class类基础知识练习
21 0
|
2天前
|
程序员 索引 Python
06-python数据容器-set(集合)入门基础操作
06-python数据容器-set(集合)入门基础操作
|
2天前
|
索引 容器
06-python数据容器-list列表定义/list的10个常用操作/列表的遍历/使用列表取出偶数
06-python数据容器-list列表定义/list的10个常用操作/列表的遍历/使用列表取出偶数

热门文章

最新文章