V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
codists
V2EX  ›  Python

翻译:《实用的 Python 编程》02_01_Datatypes

  •  
  •   codists ·
    codists · 2021-02-20 22:07:18 +08:00 · 1424 次点击
    这是一个创建于 1159 天前的主题,其中的信息可能已经有所发展或是发生改变。

    2.1 数据类型和数据结构

    本节以元组和字典为代表介绍数据结构。

    原始数据类型

    Python 有一些原始数据类型:

    • 整数
    • 浮点数
    • 字符串(文本)

    空类型

    email_address = None
    

    None 常用作可选值或缺失值的占位符。它在条件语句中计算为 False

    if email_address:
        send_email(email_address, msg)
    

    数据结构

    实际的程序具有更复杂的数据。例如,关于股票的持有信息:

    100 shares of GOOG at $490.10
    

    这是一个包含三个部分的“对象”:

    • 股票的名称或符号("GOOG",字符串)
    • 股份数目( 100,整数)
    • 价格( 490.10 ,浮点数)

    元组

    元组是分组在一起的值的集合。

    示例:

    s = ('GOOG', 100, 490.1)
    

    有时候会在语法上省略 ()

    s = 'GOOG', 100, 490.1
    

    特殊情况( 0 元组,1 元组)。

    t = ()            # An empty tuple
    w = ('GOOG', )    # A 1-item tuple
    

    元组一般用来表示简单的记录或结构。

    通常,它是由多个部分组成的单个对象。这有一个很好的类比:元组就像数据库表中的一行。

    元组的内容是有序的(类似于数组)。

    s = ('GOOG', 100, 490.1)
    name = s[0]                 # 'GOOG'
    shares = s[1]               # 100
    price = s[2]                # 490.1
    

    但是,元组的内容无法修改。

    >>> s[1] = 75
    TypeError: object does not support item assignment
    

    你可以基于当前元组创建一个新元组。

    s = (s[0], 75, s[2])
    

    元组打包

    元组更多的是把相关的项打包到一个实体( entity )中。

    s = ('GOOG', 100, 490.1)
    

    然后,该元组很容易作为单个对象传递给程序的其它部分。

    元组拆包

    要在其它地方使用元组,可以把元组的各部分拆包为变量。

    name, shares, price = s
    print('Cost', shares * price)
    

    左侧变量的数目必须与元组的结构匹配。

    name, shares = s     # ERROR
    Traceback (most recent call last):
    ...
    ValueError: too many values to unpack
    

    元组与列表

    元组看起来像只读列表。但是,元组最常用于由多个部分组成的单项。列表通常是类型相同的项的集合,

    record = ('GOOG', 100, 490.1)       # A tuple representing a record in a portfolio
    
    symbols = [ 'GOOG', 'AAPL', 'IBM' ]  # A List representing three stock symbols
    

    字典

    字典是键到值的映射。有时,字典也称为哈希表( hash table )或关联数组( associative array )。键用作访问值的索引。

    s = {
        'name': 'GOOG',
        'shares': 100,
        'price': 490.1
    }
    

    常见操作

    要从字典中获取值,请使用键名。

    >>> print(s['name'], s['shares'])
    GOOG 100
    >>> s['price']
    490.10
    >>>
    

    要添加或修改值,请使用键名进行分配。

    >>> s['shares'] = 75
    >>> s['date'] = '6/6/2007'
    >>>
    

    要删除值,请使用 del 语句。

    >>> del s['date']
    >>>
    

    为什么使用字典?

    当存在很多不同的值并且可能会修改或操作这些值时,字典很有用。字典使代码更具可读性。

    s['price']
    # vs
    s[2]
    

    练习

    在上次的几个练习中,编写了一个取数据文件 Data/portfolio.csv 的程序 。使用 csv 模块,可以轻松地逐行读取文件。

    >>> import csv
    >>> f = open('Data/portfolio.csv')
    >>> rows = csv.reader(f)
    >>> next(rows)
    ['name', 'shares', 'price']
    >>> row = next(rows)
    >>> row
    ['AA', '100', '32.20']
    >>>
    

    尽管读取文件很容易,但是与读取数据相比,通常使用数据做更多的事情。例如,也许想存储它并对其执行一些计算。不幸的是,原始的数据“行”并不能这样做。例如,即使是简单的数学计算也不行。

    >>> row = ['AA', '100', '32.20']
    >>> cost = row[1] * row[2]
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    TypeError: can't multiply sequence by non-int of type 'str'
    >>>
    

    要执行更多的操作,通常需要以某种方式解释原始数据,并将其转换为更有用的对象类型,以便以后处理。有两种简单的方式可以选择:元组或者字典。

    练习 2.1:元组

    在交互式提示符下,创建以下代表上一行的元组,但数字列要转换为恰当的数字。

    >>> t = (row[0], int(row[1]), float(row[2]))
    >>> t
    ('AA', 100, 32.2)
    >>>
    

    使用这种方式,现在可以使用股份数目乘以价格来计算总价,

    >>> cost = t[1] * t[2]
    >>> cost
    3220.0000000000005
    >>>
    

    在 Python 中,数学没用了吗?结果为什么是 3220.0000000000005 ?

    这是计算机上浮点硬件的产物,只能在二进制(而不是十进制)中准确表示小数。即使是涉及十进制小数的简单计算,也会引入小的误差。这很正常,如果你之前没有见过,可能会有点惊讶。

    虽然在所有使用浮点小数的编程语言中都会发生这种情况,但是打印的时候可以把它隐藏,例如:

    >>> print(f'{cost:0.2f}')
    3220.00
    >>>
    

    元组是只读的。可以通过尝试把股份数目改为 75 来验证这点。

    >>> t[1] = 75
    Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
    TypeError: 'tuple' object does not support item assignment
    >>>
    

    尽管无法更改元组的内容,但是始终可以创建一个全新的元组来替换旧的元组。

    >>> t = (t[0], 75, t[2])
    >>> t
    ('AA', 75, 32.2)
    >>>
    

    每当像这样重新分配现有变量名时,旧值就会被丢弃。虽然上面的赋值可能看起来像在修改元组,但实际上是在创建一个新的元组,并且将旧的元组丢弃。

    元组通常用于将值打包或拆包到变量中。请尝试以下操作:

    >>> name, shares, price = t
    >>> name
    'AA'
    >>> shares
    75
    >>> price
    32.2
    >>>
    

    取上面的变量并将其打包回元组中:

    >>> t = (name, 2*shares, price)
    >>> t
    ('AA', 150, 32.2)
    >>>
    

    练习 2.2:把字典当作数据结构

    可以创建字典来替代元组。

    >>> d = {
            'name' : row[0],
            'shares' : int(row[1]),
            'price'  : float(row[2])
        }
    >>> d
    {'name': 'AA', 'shares': 100, 'price': 32.2 }
    >>>
    

    计算持有的总价:

    >>> cost = d['shares'] * d['price']
    >>> cost
    3220.0000000000005
    >>>
    

    将此示例与上面涉及元组的相同的计算进行比较,将股份数目修改为 75 。

    >>> d['shares'] = 75
    >>> d
    {'name': 'AA', 'shares': 75, 'price': 32.2 }
    >>>
    

    与元组不同,字典可以自由修改。添加一些属性:

    >>> d['date'] = (6, 11, 2007)
    >>> d['account'] = 12345
    >>> d
    {'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007), 'account': 12345}
    >>>
    

    练习 2.3: 字典的其它操作

    如果将一个字典转换为列表,则将获得其所有的键:

    >>> list(d)
    ['name', 'shares', 'price', 'date', 'account']
    >>>
    

    类似地,如果使用 for 语句对字典进行迭代,则将获得其所有的键。

    >>> for k in d:
            print('k =', k)
    
    k = name
    k = shares
    k = price
    k = date
    k = account
    >>>
    

    尝试使用这个同时执行查找的变体:

    >>> for k in d:
            print(k, '=', d[k])
    
    name = AA
    shares = 75
    price = 32.2
    date = (6, 11, 2007)
    account = 12345
    >>>
    

    也可以使用 keys() 方法获得所有的键:

    >>> keys = d.keys()
    >>> keys
    dict_keys(['name', 'shares', 'price', 'date', 'account'])
    >>>
    

    在这里,keys() 稍微有点不同,它返回的是一个 dict_keys 对象。

    这是对原始字典的覆盖,它始终提供当前字典的键——即使字典改变了。例如,试试一下操作:

    >>> del d['account']
    >>> keys
    dict_keys(['name', 'shares', 'price', 'date'])
    >>>
    

    请注意,尽管没有再次调用 d.keys() ,但键'account' 消失了。

    一个更优雅地一起使用键和值的方式是使用 items() 方法。这可以获得键值组成的元组 (key, value)

    >>> items = d.items()
    >>> items
    dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
    >>> for k, v in d.items():
            print(k, '=', v)
    
    name = AA
    shares = 75
    price = 32.2
    date = (6, 11, 2007)
    >>>
    

    如果有类似于 items 的元组,那么可以使用 dict() 函数创建一个字典。请尝试以下操作:

    >>> items
    dict_items([('name', 'AA'), ('shares', 75), ('price', 32.2), ('date', (6, 11, 2007))])
    >>> d = dict(items)
    >>> d
    {'name': 'AA', 'shares': 75, 'price':32.2, 'date': (6, 11, 2007)}
    >>>
    

    注:完整翻译见 https://github.com/codists/practical-python-zh

    4 条回复    2021-02-21 22:00:36 +08:00
    MicroBotter
        1
    MicroBotter  
       2021-02-20 22:21:34 +08:00
    官网的中文文档不好吗?这个网站有几个人不会编程?你这也太水了,这么基础的东西在这里根本没人看。有这时间还不如扔到百度贴吧。你就直接百度搜“python 教程”有一大堆结果,这种东西已经烂大街了,不缺你这个翻译,你翻译了也不会发生什么变化。
    codists
        2
    codists  
    OP
       2021-02-20 22:41:33 +08:00
    @MicroBotter
    感谢大佬的建议。是这样的:
    1 、我不知道你是否看完了这个教程,个人认为这个教程还是很不错的,如果能完整地学习下来,会有很大收获。同时,这份教程的作者 David Beazley 是《 Python Cookbook 》的作者之一,这本书评价还是挺高的(见豆瓣 https://book.douban.com/subject/20491078/)。
    2 、翻译的初衷是为了传播有关 python 的优秀内容。对于你而言,可能这并不算什么,如果对你造成打扰,在这里说声抱歉。官方的中文文档很不错,但不一定适合每一个人。对于其它人而言,可能需要这样的一份翻译。
    3 、如果你有更优秀的 python 教程,可以在评论中贴出来,大家一起交流。
    ttyhtg
        3
    ttyhtg  
       2021-02-21 21:21:24 +08:00
    大佬加油
    codists
        4
    codists  
    OP
       2021-02-21 22:00:36 +08:00
    @ttyhtg
    我努力~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   4599 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 04:04 · PVG 12:04 · LAX 21:04 · JFK 00:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.