引言
Python 基础系列 2 基础数据类型 Taxonomy of Built-in Abstract Data Types 老早写的文章,比较粗枝大叶,所以重温一下,完善一些细节知识点。有关更多 Python 基础系列文章,请参考 Python基础知识大纲
内容提要:
- 程序员的窘境
- Python 语言的特点
- Python 对象
- 哈希值和可变性 Mutability
- 如何创建对象
- Python 内置抽象数据类型
- 同类 Homogeneous vs. 异类 Heterogeneous 容器类型
- 强制类型转换 Coercion
- 可变性和对象标识 MUTABILITY & OBJECT IDENTITY
- Python 命名规范
程序员的窘境
下图给出各种语言的优劣势。解释性语言生产效率高,但是性能相对低一些。而编译性语言性能高,但是生产效率偏低。这也是码农们的烦恼,应该选择哪门语言呢?既然是 Python 系列知识介绍,当然首推 Python ,哈哈!
Python 语言的特点
-
面向对象 Object-oriented 语言
● Python 中一切皆是对象,每个对象都有相应类型,也就是有对应的类 class。用 type(obj) 来查看对象的类型。
● 基于不同的对象,相同的函数会有不同的行为。如 print() 函数应用于不同的对象。
● 类是用来定义如何用类的构造函数创建对象,以及定义方法 method 来改变对象的。不像一般的函数,方法是定义在类的内部的,作用于类的对象。 -
函数式 Functional 语言
● 函数是作为 Python 的第一类对象。它可以存储于一个变量,也可以作为一个参数传给另外一个函数。 -
向量化 Vectorized
● NumPy 和 Pandas 模块支持向量化操作
● 向量化操作优于显式 for 循环 -
动态 Dynamic/run-time
● 只有对象的值有类型,对象赋值的变量是没有类型的
● 只在执行时通过赋值语句将变量名和对象绑定在一起。 -
泛型 Generic 语言
● 不用显示申明对象的类型签名
● 不过函数会用来确定对象的类
Python 对象
class 用来定义对象:
- 属性 Attributes:
● 描述对象的数据或状态 - 方法 Methods:
● 更改对象的数据或状态 - 类 class
● 定义如果创建或初始化对象
● class类的构造器用来创建一个类的对象
str_obj = str (‘hi’)
list_obj = list () - 方法 Methods ( .method_name () ) vs. 函数 Functions ( fun_name () )
● 方法是类实例特有的函数 : list_obj.append(str_obj)
● 方法定义在类内部
● 函数是通用的,应用于多个对象: print(), type(), len(), dir(), help()
构造函数 vs. 方法 vs. 函数
内置的函数
Characteristic | Built-In Functions | Comments |
---|---|---|
Identity | id (x) | Memory address |
Type | type (x) | ≡ Class name |
Length | len (seq) | # of items in a sequence |
Attributes | dir (x) | hasattr (x, attr) |
getattr (x, attr) | ||
String of x | str (x) | |
Representation of x | repr (x) | |
Hash value | hash (x) | mutable objects only |
Instance of a class | isinstance (x, class) | issubclass (x, class), super() |
Sorted sequence sorted (seq) | sort sequence items |
str() vs. repr()
str():
● 输出格式要便于理解,适合用于输出内容到用户终端
● 输出追求可读性
repr()
● 用于调试和开发
● 输出追求明确性,无歧义,除了对象内容,还需要展示出对象的数据类型信息
哈希值和可变性 Mutability
-
一个哈希值:
● 一个固定长度的整型用来标识对象
● 用于在一个大的集合中(如 集合 set 和 字典 dict )快速查找某值。
● 与访问和比较列表每个元素的列表不同 -
哈希值的机制
● Python 跟踪每个哈希值
● 如果 x in values 这个语句触发:
首先计算 x 的哈希值
在内部结构查找定位到这个哈希值,
当 values 集合中有存在跟 x 哈希值一样的对象时,将这个对象和 x 进行比较 -
可变性
● 可变对象其值是可以改变的
● 可变对象不可哈希
● 列表是可变的,不可哈希,但是列表可以包含不可哈希的对象
● 可哈希对象是不可改变的,为了确保对象在其整个生命周期中保持一致。
Python 数据类型的可变性,可哈希性:
如何创建对象
Python 各数据类型的构造函数:
Object | Type=Class | Constructor | Symbol: Literal Syntax |
---|---|---|---|
Integer | int | int() | |
Floating point | float | float() | |
Boolean | bool | bool() | |
String | str | str() | " " or ’ ’ |
Tuple | tuple | tuple() | ( ) |
Lis | t list | list() | [ ] |
Dictionary | dict | dict() | { } |
Set | set | set() | { } |
创建对象或实例化类:
- 创建一个空的对象: 用类的构造函数
● str_obj = str() - 创建一个空的对象: 用类的符号或字面语法
● t = ()
● d = {} - 创建一个有预定义值的对象
● 对标量类型, 简单地赋值就可以了,如 i = 10
● 对容器类型, 将预先定义的值放在类型符号里面
d = { ‘key1’: 5.0 }
ll = [ 1, 2, 3 ] - 创建一个对象,通过将另外一个对象强制类型转换:
● 将原始类型的对象放在目标对象类型的构造函数里
t_orig = (1,2)
s_target = set (t_orig)
举例:
Python 内置抽象数据类型
容器类型 Container Types
- 容器: 对象的一个集合
● 将对象视为 sequence, set, 或 map - 序列 Sequence
● 对象的有序集合
● 索引 Indexing 和 分片 slicing 用来访问集合中的个体 - 集 Set
● 对象的无序集合
● 通过哈希值高效去重 - Map
● 对象的无序集合
● 键值对: key-value
● 通过键的哈希值对快速找到对应的键值 - 可迭代容器:
● 支持迭代遍历容器中的每个对象:
next ( iter (obj) )
d.keys(); d.items(); d.values()
基于索引的遍历: object [index], index的范围 (0, len(object))
基于键的遍历: d [key]: e.g., d[‘name’]
同类 Homogeneous vs. 异类 Heterogeneous 容器类型
容器类对象,只有 NumPy 中各对象必须是相同类型的,要么全是字符型,要么全是数字类型。而其它容器类对象可以是不同类型的。
强制类型转换 Coercion
不同类型之间的互相转换,一个对象按一原本类型存储,但是因为上下文需要,这个对象需要转换成另外一种类型。例如:我们从标准的输入中读取数据,数据是以字符串的形式输入的,但是或许我们是需要数字型的。
显式隐式类型转换:
- 显式 Explicit (Casting)
当将对象显式地传递给另外一个类型的构造函数时 - 隐式 Implicit
当函数,方法,或表达式自动将对象转换成另外一种因上下文需要的其它类型。但是如果类型不支持隐式转换,将会出现TypeError 异常
,这时必须显式转换。
强制转换的影响
- 丢失精度:
- 不可逆的类型改变:
- 改变了期望对象的长度
- 自动转换顺序比较敏感
- 不兼容性,特别针对异类容器对象,不是每个对象都支持对应的类型转换
- 缺失的数据或 None:
● 如 Pandas 模块将缺失的数据处理成
可变性和对象标识 MUTABILITY & OBJECT IDENTITY
对象标识: id() — 内存地址
name = ‘Peter’ 字符串 ‘Peter’ 赋值给变量 name,变量 name 是指向字符串的引用也就是字符串的内存地址。
first = name 将 name 指向的对象赋值给变量 first,也就是说 first 变量现在也指向了字符串 ‘Peter’ 对象了。
可变对象和不可变对象 Mutable vs. Immutable
可变对象:
对象的值是可以改变的,对象改变前和改变后的内存地址是一样的。
不可变对象:
不能改变不可变对象的值,不然改变不可变对象的值,其实对象是指向另外一个新对象。
Python 命名规范
标识符:
包含字符,数字,下划线,但是不可以以数字开头
大小定敏感:下面三个是不同的变量
PEP-8
● 四个空格缩进
● 不要用混合的空格,tabs缩进,推荐用空格
● 类与函数 Function 之间间隔两个空白行
● 类中方法 Method 之间间隔一个空白行
● 函数或方法内部逻辑块可以用空行分隔
● 模块导入放在文件顶部
● 多个模块的导入用不同的行分开
● 类名用驼峰命名规则 CamelCase
● 下划线用来分隔命名用于变量名,方法名,函数名