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

简介:

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

2.2 数据对象、计算和类型

前面介绍了Python中可以表示和处理的几种数——整数、浮点数和复数,它们都是数学里的某类数的对应物,可以对它们做各种数学运算(用运算符描述),得到运算的结果。这些数都是程序操作的对象。
2.2.1 对象和类型
虽然整数、浮点数都是数,可以使用同样的运算符,但对数值相同的整数和浮点数做同样计算时,由于采用的规则不同,得到的结果也不同。例如:

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

整数计算将得到任意大的准确结果,浮点数计算得到有限精度的近似结果 。
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厘米,现在希望求出这个三角形的面积。
显然,为完成这个任务,首先需要找到从三边长求面积的方法。数学知识已经给出了相应的面积公式:


a8403ed707b8360a78b150072e266d84ee2b22f3

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

相关文章
|
4天前
|
数据采集 存储 API
网络爬虫与数据采集:使用Python自动化获取网页数据
【4月更文挑战第12天】本文介绍了Python网络爬虫的基础知识,包括网络爬虫概念(请求网页、解析、存储数据和处理异常)和Python常用的爬虫库requests(发送HTTP请求)与BeautifulSoup(解析HTML)。通过基本流程示例展示了如何导入库、发送请求、解析网页、提取数据、存储数据及处理异常。还提到了Python爬虫的实际应用,如获取新闻数据和商品信息。
|
25天前
|
数据格式 Python
如何使用Python的Pandas库进行数据透视图(melt/cast)操作?
Pandas的`melt()`和`pivot()`函数用于数据透视。基本步骤:导入pandas,创建DataFrame,然后使用这两个函数转换数据格式。示例代码展示了如何通过`melt()`转为长格式,再用`pivot()`恢复为宽格式。输入数据是包含&#39;Name&#39;和&#39;Age&#39;列的DataFrame,最终结果经过转换后呈现出不同的布局。
38 6
|
25天前
|
数据挖掘 数据处理 索引
如何使用Python的Pandas库进行数据筛选和过滤?
Pandas是Python数据分析的核心库,其DataFrame数据结构便于数据操作。筛选与过滤数据主要包括:导入pandas,创建DataFrame,通过布尔索引、`query()`或`loc[]`、`iloc[]`方法筛选。
|
26天前
|
数据处理 Python
如何使用Python的Pandas库进行数据排序和排名?
Pandas在Python中提供数据排序和排名功能。使用`sort_values()`进行排序,如`df.sort_values(by=&#39;A&#39;, ascending=False)`进行降序排序;用`rank()`进行排名,如`df[&#39;A&#39;].rank(ascending=False)`进行降序排名。多列操作可传入列名列表,如`df.sort_values(by=[&#39;A&#39;, &#39;B&#39;], ascending=[True, False])`。
22 6
|
27天前
|
Python
如何使用Python的Pandas库进行数据缺失值处理?
Pandas在Python中提供多种处理缺失值的方法:1) 使用`isnull()`检查;2) `dropna()`删除含缺失值的行/列;3) `fillna()`用常数、前/后一个值填充;4) `interpolate()`插值填充。根据需求选择合适的方法处理数据缺失值。
15 0
|
27天前
|
索引 Python
如何使用Python的Pandas库进行数据合并和拼接?
【2月更文挑战第28天】【2月更文挑战第103篇】如何使用Python的Pandas库进行数据合并和拼接?
|
28天前
|
索引 Python
如何使用Python的Pandas库进行数据透视表(pivot table)操作?
如何使用Python的Pandas库进行数据透视表(pivot table)操作?
16 0
|
27天前
|
索引 Python
如何在Python中,Pandas库实现对数据的时间序列分析?
Pandas在Python中提供强大的时间序列分析功能,包括:1) 使用`pd.date_range()`创建时间序列;2) 通过`pd.DataFrame()`将时间序列转为DataFrame;3) `set_index()`设定时间列作为索引;4) `resample()`实现数据重采样(如按月、季度);5) `rolling()`进行移动窗口计算,如计算移动平均;6) 使用`seasonal_decompose()`进行季节性调整。这些工具适用于各种时间序列分析场景。
26 0
|
29天前
|
机器学习/深度学习 数据挖掘 API
python生成数据(三)
python生成数据(三)
22 0
|
1天前
|
机器学习/深度学习 数据采集 数据挖掘
Python 的科学计算和数据分析: 解释什么是数据规整(Data Wrangling)?
数据规整是将原始数据转化为适合分析和建模的格式的关键步骤,涉及缺失值处理(删除、填充、插值)、异常值检测与处理、数据类型转换、重采样、数据合并、特征选择和特征变换等任务。这些预处理步骤确保数据质量和准确性,为后续的数据分析和机器学习模型构建奠定基础。
12 4