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
ansheng
V2EX  ›  Python

Python 全栈之路系列之数字数据类型

  •  
  •   ansheng ·
    anshengme · 2017-01-09 09:57:05 +08:00 · 1094 次点击
    这是一个创建于 2685 天前的主题,其中的信息可能已经有所发展或是发生改变。

    上篇文章中我们简单的体验了 Python 语言基本概念与语法,那么在继续深入下去的过程中,不妨先学习几个常见的 Python 内置数据类型?这也是大部分 Python 教科书的学习目录,由浅至深,慢慢深入。

    Python 常用的几种数据类型就是以下几种,其实 Python 内部的数据类型还是很多的,多归多但是很少有我们用到了,太多了也记不了,把常用的几个玩熟练了就 OK 了。

    那么接下来我们会学到那些内置的数据类型呢?

    Python-basic-data-types

    虽然说我们是在学习数据类型,但其实只是在学习每一个类型所提供的 API 而已,你所需要的大部分功能, Python 都已经帮我们封装好了,不需要担心任何效率的问题,当你熟悉了这些 API 之后,灵活的组合应用,因为这在开发的过程中是必不可少的,那么接下来就让我们开始漫长的数据类型 API 学习之旅吧。

    所有的数据类型所具备的方法都存在相对应的类里面,当创建一个类型的对象时,该对象所具备的功能都保存在相应的类中。

    数字

    在 Python3 中,整型、长整型、浮点数、负数、布尔值等都可以称之为数字类型。

    创建数字类型类型的对象

    int类型通常都是数字,创建数字类型的方式有两种,且在创建的时候值两边不需要加双引号或单引号。

    第一种创建整型的方式

    >>> number = 9
    >>> type(number)
    <class 'int'>
    

    第二种创建整型的方式

    >>> number = int(9)
    >>> type(number)
    <class 'int'>
    

    以上两种创建整型对象的方式都可以创建的,但是他们也是有本质上的区别,第一种方式实际上会转换成第二种方式,然后第二种方式会把括号内的数据交给__init__这个构造方法,构造方法是int类的,然后构造方法会在内存中开辟一块空间用来存放数据,但实际上我们在用时候是没有任何区别的。

    构造方法每个数据类型中都会有,这是 Python 内部所定义的,如下图所示:

    Python-Day03-02

    __init__

    def __init__(self, x, base=10): # known special case of int.__init__
    

    可以从源码中看到,__init__的方法有两个参数,其中base=10是可选的参数,x是我们对象的值,base=10其实就是说把我们的值(默认二进制)以十进制的方式输出出来,通过下面的实例可以看到:

    >>> var=int('0b100',base=2)
    >>> var
    4
    

    通过 int()可以将一个数字的字符串变成一个整数,并且如果你指定了第二个参数,还可以将值进制数转换为整数:

    # 将数字字符串转换为整数,数字字符串通过进制转换为整数
    >>> int('99'),int('100',8),int('40',16),int('10000000',2)
    (99, 64, 64, 128)
    # 讲进制数转换为整数
    >>> int('0x40',16),int('0b1000000',2)
    (64, 64)
    

    把二进制的数字 4 通过十进制输出出来, 4 的二进制就是0b100,又有一个知识点就是在类的方法中,所有以__开头,并且以__结尾的方法都是 Python 内部自己去调用的,我们在写代码的过程中是不需要去调用的,最简单的例子就是__init__,通过上面的流程图我们就可以很清楚的看到。

    int 内部优化机制

    下图中我们可以很清楚的看到 int 类型在创建对象时内存所分配空间的情况

    Python-Day03-03

    首先我们知道当我们创建第一个对象 var1 的时候会在内存中开辟一块空间作为存放 var1 对象的值用的,当我们创建第二个对象 var2 的时候也会在内存中开辟一块空间来作为 var2 对象的值,那如果这样说,那是不是说对象 var1 和 var2 的值内存是否会同时开辟两块呢?我们通过下面的实例可以得到答案:

    C:\Users\anshe>c:\Python35\python.exe
    # 注意我是用的是 Python3.5.1
    Python 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2016, 01:54:25) [MSC v.1900 64 bit (AMD64)] on win32
    Type "help", "copyright", "credits" or "license" for more information.
    # 分别创建对象 var1 和 var2
    >>> var1=123
    >>> var2=123
    # 我们可以看到他们的内存地址都是指向的`1502084720`
    >>> id(var1)
    1502084720
    >>> id(var2)
    1502084720
    

    通过上面的结果我们可以看到 var1 和 var2 的内存地址是相同的,就代表他们的值是使用的同一块空间,那么如果我把 var2 的值改为 456 呢?

    >>> var2=456
    >>> id(var1)
    1502084720
    >>> id(var2)
    2452305956816
    

    可以看到 var2 的内存地址已经改变了(废话),因为对象的值不一样了,所以他才不会改变, OK ,我们可以得到一个结论就是:当两个或者多个对象的值都是同一个的时候,那么这些对象都会使用同一个内存地址,这里的值是是有范围的,默认范围是-5~257,得到这个结论之后我们继续往下看。

    Python-Day03-04

    这张图我们同样创建了两个对象,但是唯一不同的是我把第一个创建的对象的值作为第二个对象的值,这里他们肯定使用的是同一个内存地址,但是如果我把第一个对象的值改动了呢?

    >>> var1=123
    >>> var2=var1
    >>> id(var1)
    1502084720
    >>> id(var2)
    1502084720
    >>> var1=456
    >>> id(var1)
    2452305956816
    >>> id(var2)
    1502084720
    

    请自行思考,这里不多做解释,然后下面我们再来说说刚才的话题,说在-5~257这个范围内对象的值都会引用同一块内存地址,我们可以通过下面的实验来测试:

    >>> var1=12345
    >>> var2=12345
    >>> id(var1)
    2452305956816
    >>> id(var2)
    2452308384720
    

    事实证明我们的结论是完全没有问题的,注意我上面的实例都是在Python3.5上面执行的哦,var1var2两个对象的值同样是 12345 ,但是他们的内存地址就是不一样,这就是 Python 在内部做的优化,他把-5~257这个范围内我们常用道德数字多对象可引用的, OK ,到此结束这个话题。

    数字类型的长度限制

    数字类型在python2.7里面是分整型和长整型这个区别的,也就是说如果你的数字大到一定的范围,那么 python 会把它转换为长整形,一个数字类型包含 32 位,可以存储从-2147483648214483647的整数。

    一个长整(long)型会占用更多的空间, 64 位的可以存储-922372036854775808922372036854775808的整数。

    python3 里 long 型已经不存在了,而 int 型可以存储到任意大小的整型,甚至超过 64 为。

    Python 内部对整数的处理分为普通整数和长整数,普通整数长度为机器位长,通常都是 32 位,超过这个范围的整数就自动当长整数处理,而长整数的范围几乎完全没限制,如下:

    • Python2.7.x
    >>> var=123456
    >>> var
    123456
    >>> var=10**20
    >>> var
    100000000000000000000L
    >>> type(var)
    # long 就是长整型
    <type 'long'>
    
    • Python3.5.x
    >>> var=123456789
    >>> var
    123456789
    >>> var=10**20
    >>> var
    100000000000000000000
    >>> type(var)
    <class 'int'>
    

    请自行补脑 - - 、

    数字类型所具备的方法

    bit_length

    返回表示该数字时占用的最少位数

    >>> num=20
    >>> num.bit_length()
    5
    

    conjugate

    返回该复数的共轭复数,复数,比如 0+2j,其中 num.real,num.imag 分别返回其实部和虚部, num.conjugate(),返回其共扼复数对象

    >>> num =-20
    >>> num.conjugate()
    -20
    >>> num=0+2j
    >>> num.real
    0.0
    >>> num.imag
    2.0
    >>> num.conjugate()
    -2j
    

    imag

    返回复数的虚数

    >>> number = 10
    >>> number.imag
    0
    >>> number = 3.1415926
    >>> number.imag
    0.0
    

    内置的方法还有denominatorfrom_bytesnumeratorrealto_bytes,实在搞不懂这有什么用,也不太理解,就不做介绍了,你可以通过help(int.numerator)查看该方法的帮助信息等。

    混合类型

    所谓混合类型就是浮点数和整数进行运算,如下所示:

    >>> 3.14159 + 10
    13.14159
    

    结果和我们想象中的一样,但是一个浮点数一个正整数它是怎么进行相加的呢?其实很简单, Python 会把两个值转换为其中最复杂的那个对象的类型,然后再对相同类型运算。

    比如上面的例子中,会先把10转换为10.0然后再与3.14159相加。

    数字类型的复杂度

    整数比浮点数简单、浮点数比复数简单。

    布尔类型(bool)

    布尔类型其实就是数字 0 和 1 的变种而来,即真( True/0 )假( False/1 ),实际上就是内置的数字类型的子类而已。

    # 如果 0 不是真,那么就输出'0 is False.'
    >>> if not 0: print('0 is False.')
    ... 
    0 is False.
    # 如果 1 是真,那么就输出'1 is True.'
    >>> if 1: print('1 is True.')
    ... 
    1 is True.
    

    你还可以使用布尔值进行加减法,虽然从来没在任何代码中见过这种形式:

    >>> True + 1
    # 1 + 1 = 2
    2
    >>> False + 1
    # 0 + 1 = 1
    1
    

    集合(set)

    集合的元素是不允许重复、不可变且无序的集合,集合就像是字典舍弃了值一样,集合中的元素只能够出现一切且不能重复。

    创建 set 集合

    >>> s = set([11,22,33])
    >>> s
    {33, 11, 22}
    >>> type(s)
    <class 'set'>
    

    第二种不常用创建 set 集合的方式

    # 这种的创建方式,集合中的元素相当于字典中的 key
    >>> s = {11,22,33}
    >>> type(s)
    <class 'set'>
    >>> s
    {33, 11, 22}
    

    把其它可迭代的数据类型转换为 set 集合

    >>> li = ["a","b","c"]
    >>> seting = set(li)
    >>> seting
    {'b', 'a', 'c'}
    >>> type(seting)
    <class 'set'>
    

    集合同样支持表达式操作符

    # 首先创建两个集合
    >>> x = set('abcde')
    >>> y = set('bdxyz')
    >>> x
    {'a', 'd', 'b', 'c', 'e'}
    >>> y
    {'y', 'd', 'b', 'x', 'z'}
    # 使用 in 进行成员检测
    >>> 'a' in x
    True
    # 差集
    >>> x - y
    {'a', 'e', 'c'}
    # 并集
    >>> x | y
    {'b', 'y', 'z', 'a', 'd', 'e', 'c', 'x'}
    # 交集
    >>> x & y
    {'d', 'b'}
    # 对称差
    >>> x ^ y
    {'y', 'z', 'a', 'e', 'c', 'x'}
    # 比较
    >>> x > y, x < y
    (False, False)
    

    集合解析

    >>> {x for x in 'abc'}
    {'a', 'b', 'c'}
    >>> {x+'b' for x in 'abc'}
    {'bb', 'cb', 'ab'}
    

    集合所提供的方法

    add

    往集合内添加元素

    >>> se = { 11, 22, 33 }
    >>> se
    {33, 11, 22}
    # 元素写在小括号内
    >>> se.add(44)
    >>> se
    {33, 11, 44, 22}
    

    clear

    清除集合内容

    >>> se = { 11, 22, 33 }
    >>> se
    {33, 11, 22}
    >>> se.clear()
    >>> se
    set()
    

    copy 浅拷贝

    下文介绍   difference

    寻找集合的元素 var1 中存在, var2 中不存在的

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22 ,55 }
    >>> var1.difference(var2)
    {33, 11}
    >>> var2.difference(var1)
    {55}
    

    difference_update

    寻找集合的元素 var1 中存在, var2 中不存在的元素,并把查找出来的元素重新复制给 var1

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22 ,55 }
    >>> var1.difference_update(var2)
    >>> var1
    {33, 11}
    

    discard

    移除指定元素,不存在不保错

    >>> var1 = { 11, 22, 33 }
    >>> var1.discard(11)
    >>> var1
    {33, 22}
    >>> var1.discard(1123123)
    >>> var1
    {33, 22}
    

    remove

    移除指定元素,不存在保错

    >>> var1 = { 11, 22, 33 }
    >>> var1
    {33, 11, 22}
    >>> var1.remove(11)
    >>> var1
    {33, 22}
    >>> var1.remove(asda)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'asda' is not defined
    

    intersection

    交集,查找元素中都存在的值

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22, 55, "一二" }
    >>> var1.intersection(var2)
    {22}
    

    intersection_update

    取交集并更更新到 A 中

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22, 55, "一二" }
    >>> var1.intersection_update(var2)
    >>> var1
    {22}
    

    isdisjoint

    判断有没有交集,如果有返回 False ,否则返回 True

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22, 44, 55 }
    >>> var1.isdisjoint(var2)
    False
    >>> var2 = { 66, 44, 55 }
    >>> var1.isdisjoint(var2)
    True
    

    issubset

    是否是子序列,也就是说如果 var2 的所有元素都被 var1 所包含了,那么 var2 就是 var1 的子序列

    >>> var1 = {11,22,33,44}
    >>> var2 = {11,22}
    >>> var2.issubset(var1)
    True
    

    issuperset

    是否是父序列

    >>> var1 = { 11, 22, 33 }
    >>> var2 = { 22, 44, 55 }
    >>> var1.issuperset(var2)
    True
    

    pop

    移除一个元素,并显示移除的元素,移除时是无序的

    >>> var1 = {11,22,33,44}
    >>> var1.pop()
    33
    >>> var1
    {11, 44, 22}
    

    symmetric_difference

    对称交集,把 var1 存在且 b 不存在和 var2 存在且 var1 不存在的元素合在一起

    >>> var1 = { 11, 22, 33, 44 }
    >>> var2 = { 11, 22, 77, 55 }
    >>> var1.symmetric_difference(var2)
    {33, 44, 77, 55}
    

    symmetric_difference_update

    对称交集,并更新到 var1 中

    >>> var1 = { 11, 22, 33, 44 }
    >>> var2 = { 11, 22, 77, 55 }
    >>> var1
    {33, 11, 44, 22}
    >>> var1.symmetric_difference_update(var2)
    >>> var1
    {33, 44, 77, 55}
    

    union

    并集,把两个集合中的所有元素放在一起,如果有重复的则只存放一个

    >>> var1 = { 11, 22, 33, 44 }
    >>> var2 = { 11, 22, 77, 55 }
    >>> var1.union(var2)
    {33, 11, 44, 77, 22, 55}
    

    update

    更新,把一个集合中的元素更新到另一个集合中

    >>> var1 = { 11, 22, 33, 44 }
    >>> var2 = { 11, 22, 77, 55 }
    >>> var1.update(var2)
    >>> var1
    {33, 11, 44, 77, 22, 55}
    

    原文链接

    Python 全栈之路系列文章

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2924 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 14:13 · PVG 22:13 · LAX 07:13 · JFK 10:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.