Python for Data Analysis 学习笔记(2)

2.3 Python语言基础

在本节中,我将向您介绍基本的Python编程概念和语言机制。 在下一章中,我将详细介绍Python的数据结构,函数和其他内置工具。

语言语义

Python语言设计的重点在于可读性,简单性和显性。 有些人甚至把它比作“可执行的伪代码”。

缩进,而不是大括号
Python使用空格(制表符或空格)来构造代码,而不是像R,C ++,Java和Perl等许多其他语言中的使用大括号。 考虑排序算法的for循环:

for x in array:
    if x < pivot:
        less.append(x)
    else:
        greater.append(x)

冒号表示缩进代码块的开始,之后所有代码必须以相同的量缩进,直到块结束。

对Python程序员来说,重要的空白是生活的一部分,根据我的经验,它可以使Python代码比我用过的其他语言更具可读性。 虽然起初看起来很陌生,但你希望能够及时习惯。

    我强烈建议使用四个空格作为默认缩进,并用四个空格替换制表符。 许多文本编辑器都会自动替换制表位和空格(执行此操作!)。 有些人使用标签或不同数量的空格,两个空格不是非常罕见。 总的来说,四个空间是绝大多数Python程序员所采用的标准,所以我建议在没有令人信服的理由的情况下这样做。

正如您现在所看到的,Python语句也不需要以分号结尾。 但是,可以使用分号分隔单行上的多个语句:

a = 5; b = 6; c = 7

Python中通常不鼓励使用多行语句,因为它经常使代码不易读。


一切都是一个对象

Python语言的一个重要特征是其对象模型的一致性。 Python解释器中的每个数字,字符串,数据结构,函数,类,模块等都存在于它自己的“框”中,它被称为Python对象。 每个对象都有一个关联的类型(例如,字符串或函数)和内部数据。 实际上,这使得语言非常灵活,因为甚至可以像其他任何对象那样对待函数。


注释

Python解释器会忽略任何以哈希标记(井号)#开头的文本。 这通常用于向代码添加注释。 有时,您可能还希望排除某些代码块而不删除它们。 一个简单的解决方案是注释代码:
results = []
for line in file_handle:
    # keep the empty lines for now
    # if len(line) == 0:
    # continue
    results.append(line.replace('foo', 'bar'))
注释也可能发生在一行执行的代码之后。 虽然有些程序员更喜欢将注释放在特定代码行之前的行中,但有时这会很有用:

print("Reached this line") # Simple status report

函数和对象方法调用

您可以使用圆括号并传递零个或多个参数来调用函数,可以将返回值分配给一个变量:
result = f(x, y, z)
g()

几乎Python中的每个对象都有附加的函数,称为方法,可以访问对象的内部内容。 您可以使用以下语法调用它们:

obj.some_method(x, y, z)
函数可以同时使用位置和关键字参数:
result = f(a, b, c, d=5, e='foo')

稍后再说。


变量和参数传递

在Python中分配变量(或名称)时,您将在等号的右侧创建对该对象的引用。 实际上,考虑一个整数列表:

In [8]: a = [1, 2, 3]

假设我们将一个新的变量赋值给一个新的变量b:

In [9]: b = a
在某些语言中,此分配会导致复制数据[1,2,3]。 在Python中,a和b现在实际上是指同一个对象,即原始列表[1,2,3](参见图2-7中的一个模型)。 你可以通过给元素添加一个元素然后检查b来证明这一点。
In [10]: a.append(4)
In [11]: b
Out[11]: [1, 2, 3, 4]

图2-7    两个引用为同一个对象

在Python中处理更大的数据集时,了解Python中引用的语义以及何时,如何以及为何要复制数据尤为重要。

    赋值也被称为绑定,因为我们将一个名称绑定到一个对象。 已分配的变量名称有时可能被称为绑定变量。

当您将对象作为参数传递给函数时,将在不进行任何复制的情况下引用原始对象来创建新的局部变量。 如果将新对象绑定到函数内的变量,则该更改将不会反映在父作用域中。 因此可以改变可变参数的内部。 假设我们有以下功能:

def append_element(some_list, element):
    some_list.append(element)
然后我们有:
In [27]: data = [1, 2, 3]
In [28]: append_element(data, 4)
In [29]: data
Out[29]: [1, 2, 3, 4]


动态引用,强类型
与许多编译语言(如Java和C ++)相比,Python中的对象引用没有与它们关联的类型。 以下几点没有问题:

In [12]: a = 5
In [13]: type(a)
Out[13]: int
In [14]: a = 'foo'
In [15]: type(a)
Out[15]: str
变量是特定名称空间内对象的名称; 类型信息存储在对象本身中。 一些观察者可能会匆忙地得出结论:Python不是“类型语言”。这不是真的; 考虑这个例子:
In [16]: '5' + 5
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-16-f9dbf5f0b234> in <module>()
----> 1 '5' + 5
TypeError: must be str, not int
在某些语言中,如Visual Basic,字符串'5'可能会隐式转换(或转换)为整数,从而产生10.但在其他语言(如JavaScript)中,整数5可能会被转换为字符串, 串联的字符串'55'。 在这方面,Python被认为是强类型语言,这意味着每个对象都有一个特定的类型(或类),并且隐式转换只会在某些明显的情况下发生,如下所示:
In [17]: a = 4.5
In [18]: b = 2
# String formatting, to be visited later
In [19]: print('a is {0}, b is {1}'.format(type(a), type(b)))
a is <class 'float'>, b is <class 'int'>
In [20]: a / b
Out[20]: 2.25
了解对象的类型非常重要,能够编写可处理多种不同类型输入的函数非常有用。 您可以使用isinstance函数检查对象是特定类型的实例:
In [21]: a = 5
In [22]: isinstance(a, int)
Out[22]: True

isinstance可以接受一个元组的类型,如果你想检查一个对象的类型是否在元组中:

In [23]: a = 5; b = 4.5
In [24]: isinstance(a, (int, float))
Out[24]: True
In [25]: isinstance(b, (int, float))
Out[25]: True
属性和方法
Python中的对象通常具有两个属性(其他Python对象存储在对象内部)和方法(与可访问对象内部数据的对象相关的函数)。 它们都可以通过语法obj.attribute_name访问:
In [1]: a = 'foo'
In [2]: a.<Press Tab>
a.capitalize a.format a.isupper a.rindex a.strip
a.center a.index a.join a.rjust a.swapcase
a.count a.isalnum a.ljust a.rpartition a.title
a.decode a.isalpha a.lower a.rsplit a.translate
a.encode a.isdigit a.lstrip a.rstrip a.upper
a.endswith a.islower a.partition a.split a.zfill
a.expandtabs a.isspace a.replace a.splitlines
a.find a.istitle a.rfind a.startswith
属性和方法也可以通过getattr函数按名称访问:
In [27]: getattr(a, 'split')
Out[27]: <function str.split>

在其他语言中,按名称访问对象通常被称为“反射”。尽管本书不会广泛使用函数getattr和相关函数hasattr和setattr,但它们可以非常有效地用于编写通用的可重用代码。

鸭子打字
通常你可能不关心对象的类型,而仅仅关心它是否具有某些方法或行为。 这有时被称为“鸭子打字”,在说过“如果它像鸭子一样走路,像鸭子一样嘎嘎叫,那么它就是鸭子”之类的话。“例如,如果实现迭代器协议,则可以验证对象是可迭代的。 对于很多对象来说,这意味着它有一个__iter__“魔术方法”,尽管另一种更好的检查方法是尝试使用iter函数:

def isiterable(obj):
    try:
        iter(obj)
        return True
    except TypeError: # not iterable
        return False
对于字符串以及大多数Python集合类型,此函数将返回True:
In [29]: isiterable('a string')
Out[29]: True
In [30]: isiterable([1, 2, 3])
Out[30]: True
In [31]: isiterable(5)
Out[31]: False

我一直在使用这个功能的地方是编写可以接受多种输入的函数。 一个常见的情况是编写一个可以接受任何类型的序列(列表,元组,ndarray)甚至迭代器的函数。 您可以首先检查对象是否是列表(或NumPy数组),如果不是,则将其转换为一个:

if not isinstance(x, list) and isiterable(x):
     x = list(x)
导入
在Python中,模块只是一个带有Python代码的.py扩展名的文件。 假设我们有以下模块:
# some_module.py
PI = 3.14159
def f(x):
    return x + 2
def g(a, b):
    return a + b
如果我们想访问some_module.py中定义的变量和函数,可以从同一目录中的另一个文件访问:
import some_module
result = some_module.f(5)
pi = some_module.PI
或等同地:
from some_module import f, g, PI
result = g(5, PI)
通过使用as关键字,您可以输入不同的变量名称:
import some_module as sm
from some_module import PI as pi, g as gf
r1 = sm.f(pi)
r2 = gf(6, pi)


二进制运算符和比较
大部分的二进制数学运算和比较如你所期望的那样:

In [32]: 5 - 7
Out[32]: -2
In [33]: 12 + 21.5
Out[33]: 33.5
In [34]: 5 <= 2
Out[34]: False
所有可用的二元运算符见表2-3。
要检查两个引用是否引用同一个对象,请使用is关键字。 如果你想检查两个对象是不一样的,这也不是完全有效的:
In [35]: a = [1, 2, 3]
In [36]: b = a
In [37]: c = list(a)
In [38]: a is b
Out[38]: True
In [39]: a is not c
Out[39]: True
由于列表总是创建一个新的Python列表(即副本),因此我们可以确定c不同于a。 与is相比,与==运算符不同,因为在这种情况下,我们有:
In [40]: a == c
Out[40]: True
is和is not的一个非常常见的用法是检查变量是否为None,因为只有一个None的实例:
In [41]: a = None
In [42]: a is None
Out[42]: True
表2-3    二进制运算符
Operation Description
a + b               Add a and b
a - b                Subtract b from a
a * b                Multiply a by b
a / b                Divide a by b
a // b               将a除以b,删除任何小数余数
a ** b               a的b次幂
a & b               如果a和b都为真,则为真; 对于整数,采取按位与
a | b                 如果a或b为真,则为真; 对于整数,采取按位或

a ^ b                对于布尔值,如果a或b为真,但不是两者都为真; 对于整数,采取按位异或或

a == b             如果a等于b,则为真

a != b               如果a不等于b,则为真
a <= b, a < b   如果a小于(小于或等于)b,则为真
a > b, a >= b   如果a大于(大于或等于)b,则为真
a is b                如果a和b引用相同的Python对象,则为true

a is not b          如果a和b引用不同的Python对象,则为真


可变和不可变的对象
Python中的大多数对象(如列表,字典,NumPy数组和大多数用户定义的类型(类))都是可变的。 这意味着它们包含的对象或值可以修改:

In [43]: a_list = ['foo', 2, [4, 5]]
In [44]: a_list[2] = (3, 4)
In [45]: a_list
Out[45]: ['foo', 2, (3, 4)]
另外,如字符串和元组,是不可变的:
In [46]: a_tuple = (3, 5, (4, 5))
In [47]: a_tuple[1] = 'four'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-47-b7966a9ae0f1> in <module>()
----> 1 a_tuple[1] = 'four'
TypeError: 'tuple' object does not support item assignment
请记住,仅仅因为你可以改变一个对象并不意味着你总是应该这样做。 这种行为被称为副作用。 例如,在编写函数时,任何副作用都应该在函数的文档或注释中明确传达给用户。 如果可能,我建议尽量避免副作用并支持不变性,即使可能存在可变对象。


标量类型

Python和它的标准库有一小组内置类型用于处理数字数据,字符串,布尔值(True或False)值以及日期和时间。 这些“单值”类型有时被称为标量类型,我们在本书中称它们为标量。 请参阅表2-4以获取主要标量类型的列表。 日期和时间处理将分开讨论,因为它们是由标准库中的日期时间模块提供的。

表2-4    标准Python标量类型

类型         描述
None        Python的“null”值(只有一个None对象实例存在)
str             字符串类型; 保存Unicode(UTF-8编码)字符串
bytes        原始ASCII字节(或Unicode编码为字节)
float         双精度(64位)浮点数(注意没有单独的双精度型)
bool         真值或假值
int            任意精度有符号整数


数字类型
数字的主要Python类型是int和float。 int可以存储任意大的数字:

In [48]: ival = 17239871
In [49]: ival ** 6
Out[49]: 26254519291092456596965462913230729701102721
浮点数用Python浮点类型表示。 在引擎盖下,每一个都是双精度(64位)值。 它们也可以用科学记数法表示:
In [50]: fval = 7.243
In [51]: fval2 = 6.78e-5

不产生整数的整数除法总是会产生一个浮点数:

In [52]: 3 / 2
Out[52]: 1.5
要获得C型整数除法(如果结果不是整数,则舍去小数部分),请使用floor division运算符//:
In [53]: 3 // 2
Out[53]: 1


字符串
很多人使用Python来实现强大而灵活的内置字符串处理功能。 您可以使用单引号或双引号来编写字符串文字:

a = 'one way of writing a string'
b = "another way"

对于带换行符的多行字符串,可以使用三角引号:'''或""":

c = """
This is a longer string that
spans multiple lines
"""
令人惊讶的是,这个字符串c实际上包含四行文本;"""后的行会被中断,并且行被包含在字符串中之后,我们可以用c:中的count方法计算新的行字符,
In [55]: c.count('\n')
Out[55]: 3
Python字符串是不可变的; 你不能修改一个字符串:
In [56]: a = 'this is a string'
In [57]: a[10] = 'f'
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-57-5ca625d1e504> in <module>()
----> 1 a[10] = 'f'
TypeError: 'str' object does not support item assignment
In [58]: b = a.replace('string', 'longer string')
In [59]: b
Out[59]: 'this is a longer string'
在这个操作之后,变量a是未修改的:
In [60]: a
Out[60]: 'this is a string'

许多Python对象可以使用str函数转换为字符串:

In [61]: a = 5.6
In [62]: s = str(a)
In [63]: print(s)
5.6
字符串是一系列Unicode字符,因此可以像其他序列一样对待,如列表和元组(我们将在下一章中更详细地探讨):
In [64]: s = 'python'
In [65]: list(s)
Out[65]: ['p', 'y', 't', 'h', 'o', 'n']
In [66]: s[:3]
Out[66]: 'pyt'
语法s [:3]被称为切片,并被实现用于多种Python序列。 这将在后面更详细地解释,因为它在本书中被广泛使用。
反斜杠字符\是一个转义字符,这意味着它用于指定特殊字符,如换行符或Unicode字符。 要用反斜杠编写字符串文字,您需要转义它们:
In [67]: s = '12\\34'
In [68]: print(s)
12\34
如果你有一个反斜杠和没有特殊字符的字符串,你可能会觉得这有点烦人。 幸运的是,您可以在r前面加上字符串的前导引号,这意味着这些字符应该被解释为:
In [69]: s = r'this\has\no\special\characters'
In [70]: s
Out[70]: 'this\\has\\no\\special\\characters'

r代表未加工的。

添加两个字符串连接在一起并生成一个新的字符串:
In [71]: a = 'this is the first half '
In [72]: b = 'and this is the second half'
In [73]: a + b
Out[73]: 'this is the first half and this is the second half'
字符串模板或格式是另一个重要的主题。 随着Python 3的出现,这样做的方式已经扩展了很多,下面我将简要介绍其中一个主要接口的机制。 字符串对象有一个格式方法,可以用来将格式化的参数替换为字符串,产生一个新的字符串:
In [74]: template = '{0:.2f} {1:s} are worth US${2:d}'
在这个字符串中,
·{0:.2f}表示将第一个参数格式化为带有两位小数的浮点数。
·{1:s}表示将第二个参数格式化为一个字符串。
·{2:d}表示将第三个参数格式化为精确的整数。
为了替换这些格式参数的参数,我们将一系列参数传递给format方法:
In [75]: template.format(4.5560, 'Argentine Pesos', 1)
Out[75]: '4.56 Argentine Pesos are worth US$1'
字符串格式化是一个深刻的话题; 有多种方法和众多的选项和调整可用于控制如何在结果字符串中格式化值。 要了解更多信息,我建议查阅 官方的Python文档
我将在 第8章中更详细地讨论与数据分析有关的通用字符串处理。


字节和Unicode

在现代Python(即Python 3.0及更高版本)中,Unicode已成为第一类字符串类型,以便更加一致地处理ASCII和非ASCII文本。 在旧版本的Python中,字符串都是字节,没有任何明确的Unicode编码。 假设您知道字符编码,您可以转换为Unicode。 我们来看一个例子:


我们可以使用编码方法将此Unicode字符串转换为其UTF-8字节表示形式:

In [78]: val_utf8 = val.encode('utf-8')
In [79]: val_utf8
Out[79]: b'espa\xc3\xb1ol'
In [80]: type(val_utf8)
Out[80]: bytes
假设您知道字节对象的Unicode编码,您可以使用解码方法返回:

虽然使用UTF-8进行任何编码已成为首选,但出于历史原因,您可能会遇到任何数量的不同编码中的数据:

In [82]: val.encode('latin1')
Out[82]: b'espa\xf1ol'
In [83]: val.encode('utf-16')
Out[83]: b'\xff\xfee\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'
In [84]: val.encode('utf-16le')
Out[84]: b'e\x00s\x00p\x00a\x00\xf1\x00o\x00l\x00'
在使用文件的上下文中遇到字节对象是最常见的,其中将所有数据隐式解码为Unicode字符串可能不是理想的。
尽管您很少需要这样做,但您可以通过在字符串前添加b来定义自己的字节文字:
In [85]: bytes_val = b'this is bytes'
In [86]: bytes_val
Out[86]: b'this is bytes'
In [87]: decoded = bytes_val.decode('utf8')
In [88]: decoded # this is str (Unicode) now
Out[88]: 'this is bytes
布尔
Python中的两个布尔值被写为True和False。 比较和其他条件表达式评估为True或False。 布尔值与and和or关键字结合使用:
In [89]: True and True
Out[89]: True
In [90]: False or True
Out[90]: True
类型铸造
str,bool,int和float类型也是可用于将值转换为这些类型的函数:
In [91]: s = '3.14159'
In [92]: fval = float(s)
In [93]: type(fval)
Out[93]: float
In [94]: int(fval)
Out[94]: 3
In [95]: bool(fval)
Out[95]: True
In [96]: bool(0)
Out[96]: False
None
None是Python空值类型。 如果一个函数没有显式地返回一个值,它会隐含地返回None:
In [97]: a = None
In [98]: a is None
Out[98]: True
In [99]: b = 5
In [100]: b is not None
Out[100]: True
None也是函数参数的常用默认值:
def add_and_maybe_multiply(a, b, c=None):
    result = a + b
    if c is not None:
        result = result * c
    return result

虽然技术点,值得注意的是,None不仅是一个保留关键字,也是一个独特的NoneType实例:

In [101]: type(None)
Out[101]: NoneType



日期和时间

内置的Python日期时间模块提供日期时间,日期和时间类型。 如您所想,日期时间类型将日期和时间中存储的信息结合起来,并且是最常用的信息:

In [102]: from datetime import datetime, date, time
In [103]: dt = datetime(2011, 10, 29, 20, 30, 21)
In [104]: dt.day
Out[104]: 29
In [105]: dt.minute
Out[105]: 30
给定日期时间实例,可以通过调用同名日期时间的方法来提取等效的日期和时间对象:
In [106]: dt.date()
Out[106]: datetime.date(2011, 10, 29)
In [107]: dt.time()
Out[107]: datetime.time(20, 30, 21)
strftime方法将日期时间格式化为字符串:
In [108]: dt.strftime('%m/%d/%Y %H:%M')
Out[108]: '10/29/2011 20:30'

使用strptime函数可以将字符串转换(解析)为日期时间对象:

In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)
有关格式规范的完整列表,请参阅表2-5。

在汇总时间序列数据或以其他方式对时间序列数据进行分组时,它有时会用于替换一系列日期时间的时间字段 - 例如,将分钟和第二个字段替换为零:

In [110]: dt.replace(minute=0, second=0)
Out[110]: datetime.datetime(2011, 10, 29, 20, 0)
由于datetime.datetime是不可变的类型,像这样的方法总是产生新的对象。

两个日期时间对象的差异会产生一个datetime.timedelta类型:

In [111]: dt2 = datetime(2011, 11, 15, 22, 30)
In [112]: delta = dt2 - dt
In [113]: delta
Out[113]: datetime.timedelta(17, 7179)
In [114]: type(delta)
Out[114]: datetime.timedelta
输出timedelta(17,7179)指示timedelta编码17天和7,179秒的偏移量。
将datedelta添加到日期时间会生成新的移位日期时间:
In [115]: dt
Out[115]: datetime.datetime(2011, 10, 29, 20, 30, 21)
In [116]: dt + delta
Out[116]: datetime.datetime(2011, 11, 15, 22, 30)

表2-5    日期时间格式规范(与ISO C89兼容)

类型      描述
%Y        四位数年份

%y        两位数年份

%m       两位数月份[01,12]

%d        两位数日[01,31]
%H        小时(24小时制)[00,23]
%I         小时(12小时制)[01,12]
%M       两位数分钟[00,59]
%S         秒[00,61](秒60,61占闰秒)
%w        平日为整数[0(星期日),6]
%U        年的周数[00,53]; 星期日被认为是一周的第一天,并且在该年的第一个星期日之前的几天是“第0周”
%W       年的周数[00,53]; 星期一被认为是一周的第一天,并且在该年的第一个星期一之前的几天是“第0周”
%z         UTC时区偏移为+ HHMM或-HHMM; 如果时区naive,则为空
%F         %Y-%m-%d的短日期(例如2012-4-18)

%D        %m /%d /%y的短日期(例如,04/18/12)


控制流

Python有几个内置的关键字,用于条件逻辑,循环和其他编程语言中的其他标准控制流概念。

if, elif, and else

if语句是最着名的控制流语句类型之一。 它检查一个条件,如果为True,则评估下面代码块中的代码:

if x < 0:
print('It's negative')
如果所有条件均为False,if语句可以选择跟随一个或多个elif块,并且可以选择其他块:
if x < 0:
    print('It's negative')
elif x == 0:
    print('Equal to zero')
elif 0 < x < 5:
    print('Positive but smaller than 5')
else:
    print('Positive and larger than or equal to 5')
如果任何条件为真,则不会再有ELIF或其他块。 对于使用和或或的复合条件,条件从左到右进行评估并将短路:
In [117]: a = 5; b = 7
In [118]: c = 8; d = 4
In [119]: if a < b or c > d:
.....: print('Made it')
Made it
在这个例子中,比较c> d永远不会被评估,因为第一个比较是真的。
链接比较也是可能的:
In [120]: 4 > 3 > 2 > 1
Out[120]: True


for循环

for循环用于迭代集合(如列表或元组)或迭代器。 for循环的标准语法是:
for value in collection:
    # do something with value

您可以使用continue关键字跳过for循环到下一个迭代,跳过块的其余部分。 考虑这个代码,其中汇总了列表中的整数并跳过了None值:

sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
    if value is None:
        continue
    total += value
for循环可以用break关键字完全退出。 此代码对列表中的元素进行求和直至达到5:
sequence = [1, 2, 0, 4, 6, 5, 2, 1]
total_until_5 = 0
for value in sequence:
    if value == 5:
        break
    total_until_5 += value
break关键字只会终止最内层的for循环; 任何外循环将继续运行:
In [121]: for i in range(4):
.....: for j in range(4):
.....: if j > i:
.....: break
.....: print((i, j))
.....:
(0, 0)
(1, 0)
(1, 1)
(2, 0)
(2, 1)
(2, 2)
(3, 0)
(3, 1)
(3, 2)
(3, 3)
正如我们将更详细地看到的那样,如果集合或迭代器中的元素是序列(元组或列表,例如),则可以方便地将它们解压缩到for循环语句中的变量中:
for a, b, c in iterator:
    # do something
while循环
while循环指定一个条件和一个要执行的代码块,直到条件计算结果为False或循环明确以break结束:
x = 256
total = 0
while x > 0:
    if total > 500:
        break
    total += x
    x = x // 2
通过
pass是Python中的“no-op”语句。 它可以用于不采取任何操作的块(或作为代码的占位符尚未实现); 它只是必需的,因为Python使用空格来分隔块:
if x < 0:
    print('negative!')
elif x == 0:
    # TODO: put something smart here
    pass
else:
    print('positive!')
范围
range函数返回一个产生一系列均匀间隔整数的迭代器:
In [122]: range(10)
Out[122]: range(0, 10)
In [123]: list(range(10))
Out[123]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
可以给出开始,结束和步骤(可能为负数):
In [124]: list(range(0, 20, 2))
Out[124]: [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
In [125]: list(range(5, 0, -1))
Out[125]: [5, 4, 3, 2, 1]
正如你所看到的,range产生了整数,但不包括端点。 range的一个常见用途是通过索引遍历序列:
seq = [1, 2, 3, 4]
for i in range(len(seq)):
    val = seq[i]
虽然你可以使用list之类的函数来存储范围在其他数据结构中生成的所有整数,但通常默认的迭代器形式将是你想要的。 这段代码将0到99,999之间的所有数字相加,它们是3或5的倍数:
sum = 0
for i in range(100000):
    # % is the modulo operator
    if i % 3 == 0 or i % 5 == 0:
        sum += i
尽管产生的范围可以是任意大的,但是在任何给定时间的存储器使用可能非常小。


三元表达式

Python中的三元表达式允许您将产生值的if-else块组合到单个行或表达式中。 这在Python中的语法是:

value = true-expr if condition else false-expr
在这里,true-expr和false-expr可以是任何Python表达式。 它具有与更详细的相同的效果:
if condition:
    value = true-expr
else:
    value = false-expr
这是一个更具体的例子:
In [126]: x = 5
In [127]: 'Non-negative' if x >= 0 else 'Negative'
Out[127]: 'Non-negative'
和if-else块一样,只有一个表达式会被执行。 因此,三元表达式的“if”和“else”边可能包含昂贵的计算,但只有真正的分支才会被评估。

虽然可能总是使用三元表达式来浓缩代码,但要意识到如果条件以及真假表达式非常复杂,您可能会牺牲可读性。

#第二章结束~



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这本书主要是用 pandas 连接 SciPy 和 NumPy,用pandas做数据处理是Pycon2012上一个很热门的话题。另一个功能强大的东西是Sage,它将很多开源的软件集成到统一的 Python 接口。, Python for Data Analysis is concerned with the nuts and bolts of manipulating, processing, cleaning, and crunching data in Python. It is also a practical, modern introduction to scientific computing in Python, tailored for data-intensive applications. This is a book about the parts of the Python language and libraries you’ll need to effectively solve a broad set of data analysis problems. This book is not an exposition on analytical methods using Python as the implementation language., Written by Wes McKinney, the main author of the pandas library, this hands-on book is packed with practical cases studies. It’s ideal for analysts new to Python and for Python programmers new to scientific computing., Use the IPython interactive shell as your primary development environment, Learn basic and advanced NumPy (Numerical Python) features, Get started with data analysis tools in the pandas library, Use high-performance tools to load, clean, transform, merge, and reshape data, Create scatter plots and static or interactive visualizations with matplotlib, Apply the pandas groupby facility to slice, dice, and summarize datasets, Measure data by points in time, whether it’s specific instances, fixed periods, or intervals, Learn how to solve problems in web analytics, social sciences, finance, and economics, through detailed examples
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值