乐趣区

关于数据挖掘:Python语法基础快速回顾

文章和代码等曾经归档至【Github 仓库:https://github.com/timerring/dive-into-AI】或者公众号【AIShareLab】回复 python 数据分析 也可获取。

缩进

倡议应用四个空格 (tab) 作为默认的缩进。

Python 的语句不须要用分号结尾。然而,分号却能够用来给同在一行的语句切分:

a = 5; b = 6; c = 7

Python 不倡议将多条语句放到一行,这会升高代码的可读性。

函数和对象办法调用

你能够用圆括号调用函数,传递零个或几个参数,或者将返回值给一个变量:

result = f(x, y, z)
g()

简直 Python 中的每个对象都有附加的函数,称作办法,能够用来拜访对象的内容。能够用上面的语句调用:

obj.some_method(x, y, z)

变量和参数传递

在 Python 中,a 和 b 实际上是同一个对象,即原有列表[1, 2, 3]。能够在 a 中增加一个元素,而后查看 b:

In [8]: a = [1, 2, 3]
In [9]: b = a
In [10]: a.append(4)

In [11]: b
Out[11]: [1, 2, 3, 4]

赋值也被称作绑定,咱们是把一个名字绑定给一个对象。变量名有时可能被称为绑定变量。

当你将对象作为参数传递给函数时,新的局域变量创立了 对原始对象的援用,而不是复制。

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]

强类型

变量是在非凡命名空间中的对象的名字,类型信息保留在对象本身中。一些人可能会说 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 [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 函数和相干的 hasattrsetattr函数,应用这些函数能够高效编写原生的、可重复使用的代码。

鸭子类型

常常地,你可能不关怀对象的类型,只关怀对象是否有某些办法或用处。这通常被称为“鸭子类型”,来自“走起来像鸭子、叫起来像鸭子,那么它就是鸭子”的说法。例如,你能够通过验证一个对象是否遵循迭代协定,判断它是可迭代的。对于许多对象,这意味着它有一个 __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

我总是用这个性能编写能够承受多种输出类型的函数。

常见的例子是编写一个函数能够承受任意类型的序列(list、tuple、ndarray)或是迭代器。你可先测验对象是否是列表(或是 NUmPy 数组),如果不是的话,将其转变成列表:

if not isinstance(x, list) and isiterable(x):
    x = list(x)

引入

在 Python 中,模块就是一个有 .py 扩展名、蕴含 Python 代码的文件。假如有以下模块:

# 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)

二元运算符和比拟运算符

判断两个援用是否指向同一个对象,能够应用 is 办法。is not能够判断两个对象是不同的:

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

因为 list 总是创立一个新的 Python 列表(即复制),咱们能够判定 c 是不同于 a 的。应用 is 比拟与 == 运算符不同,如下:

In [40]: a == c
Out[40]: True

isis not 罕用来判断一个变量是否为 None,因为只有一个None 的实例:

In [41]: a = None

In [42]: a is None
Out[42]: True

可变与不可变对象

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 的规范库中有一些内建的类型,用于解决数值数据、字符串、布尔值,和日期工夫。这些单值类型被称为标量类型,本书中称其为标量。日期和工夫解决会另外探讨,因为它们是规范库的 datetime 模块提供的。

数值类型

Python 的次要数值类型是 intfloatint能够存储任意大的数

In [48]: ival = 17239871

In [49]: ival ** 6
Out[49]: 26254519291092456596965462913230729701102721

浮点数应用 Python 的 float 类型。每个数都是双精度(64 位)的值。也能够用迷信计数法示意:

In [50]: fval = 7.243

In [51]: fval2 = 6.78e-5

不能失去整数的除法会失去浮点数:

In [52]: 3 / 2
Out[52]: 1.5

要取得 C - 格调的整除(去掉小数局部),能够应用 底除运算符 //

In [53]: 3 // 2
Out[53]: 1

字符串

能够用单引号或双引号来写字符串:

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

对于有换行符的字符串,能够应用三引号,”’ 或 ””” 都行:

c = """
This is a longer string that
spans multiple lines
"""

字符串 c 理论蕴含四行文本,””” 前面和 lines 前面的换行符。能够用 count 办法计算 c 中的新的行:

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 序列。

反斜杠是转义字符,意思是它备用来示意特殊字符,比方换行符 \n 或 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 示意 raw。

将两个字符串合并,会产生一个新的字符串:

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 拓展了此类的办法,这里只介绍一些。字符串对象有 format 办法,能够替换格式化的参数为字符串,产生一个新的字符串:

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 官网文档。

字节和 Unicode

在 Python 3 及以上版本中,Unicode 是一级的字符串类型,这样能够更统一的解决 ASCII 和 Non-ASCII 文本。在老的 Python 版本中,字符串都是字节,不应用 Unicode 编码 。如果 晓得字符编码,能够将其转化为 Unicode。看一个例子:

In [76]: val = "español"

In [77]: val
Out[77]: 'español'

能够 encode将这个 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 编码,decode 办法能够解码

In [81]: val_utf8.decode('utf-8')
Out[81]: 'español'

工作中碰到的文件很多都是字节对象,自觉地将所有数据编码为 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'

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 内建的 datetime 模块提供了 datetimedatetime类型。datetime类型联合了 datetime,是最常应用的:

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

依据 datetime 实例,你能够用 datetime提取出各自的对象:

In [106]: dt.date()
Out[106]: datetime.date(2011, 10, 29)

In [107]: dt.time()
Out[107]: datetime.time(20, 30, 21)

strftime办法能够将 datetime 格式化为字符串:

In [108]: dt.strftime('%m/%d/%Y %H:%M')
Out[108]: '10/29/2011 20:30'

strptime能够将字符串转换成 datetime 对象:

In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)

表 2 - 5 列出了所有的格式化命令。

当你聚类或对工夫序列进行分组,替换 datetimes 的 time 字段有时会很有用。例如,用 0 替换分和秒:

In [110]: dt.replace(minute=0, second=0)
Out[110]: datetime.datetime(2011, 10, 29, 20, 0)

因为 datetime.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 天、7179 秒的编码方式。

timedelta 增加到datetime,会产生一个新的偏移datetime

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)

控制流

if、elif 和 else

if前面能够跟一个或多个elif,所有条件都是 False 时,还能够增加一个else

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')

如果某个条件为 True,前面的 elif 就不会被执行。当应用 and 和 or 时,复合条件语句是从左到右执行,也能够把比拟式串在一起:

In [120]: 4 > 3 > 2 > 1
Out[120]: True

for 循环

for 循环是在一个汇合(列表或元组)中进行迭代,或者就是一个迭代器。for 循环的规范语法是:

for value in collection:
    # do something with value

你能够用 continue 使 for 循环提前,跳过剩下的局部。看上面这个例子,将一个列表中的整数相加,跳过 None。

break 只中断 for 循环的最内层,其余的 for 循环仍会运行。

如果汇合或迭代器中的元素序列(元组或列表),能够用 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

pass 是 Python 中的非操作语句。代码块不须要任何动作时能够应用(作为未执行代码的占位符);因为 Python 须要应用空白字符划定代码块,所以须要 pass:

if x < 0:
    print('negative!')
elif x == 0:
    # TODO: put something smart here
    pass
else:
    print('positive!')

range

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]

range 的三个参数是(终点,起点,步进):

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 来存储 range 在其余数据结构中生成的所有整数,默认的迭代器模式通常是你想要的。尽管 range 能够产生任意大的数,但任意时刻耗用的内存却很小。

三元表达式

Python 中的三元表达式能够将 if-else 语句放到一行里。语法如下:

value = true-expr if condition else false-expr

true-exprfalse-expr 能够是任何 Python 代码。它和上面的代码成果雷同:

if condition:
    value = true-expr
else:
    value = false-expr

尽管应用三元表达式能够压缩代码,但会升高代码可读性。

退出移动版