python这门课也选了 所以自学的定位就是:
- 标记疑问点
- 重视实际操作
- 上课的时候可以边听边做
- 坐到第三排
之前刷过leetcode的pandas的题目,学完书里的pandas再去刷一遍
一周一共有三天是软件学习,因为R没有专门的课学而且之前一无所知,会以学R为主
以前断续接触过python 以查缺补漏+实际应用为主了
第一章:准备工作
pandas:方便完成重塑、切片和切块、聚合以及选取数据子集等
pandas的对象:
- dataframe:面向列的二维表结构
- series:一维的标签化数组对象
定位:设计为⼀款适⽤于⾦融 和商业分析的⼯具,pandas专注于深度时间序列功能和⼯具, 适⽤于时间索引化的数据。
matplotlib:绘制图表和可视化分析
IPython和Jupyter
第2章 Python语法基础,IPython和Jupyter Notebooks
- anaconda——找到jupyter notebooks——按new可以新建一个,按shift+enter执行
- 保存文件的时候会生成.ipynb文件
2.2 ipython 和jupyter 基础应用
自省
b=[1,2,3]
b?
def add_numbers(a, b):
return a + b
add_numbers?
add_numbers??
np.*load*?
# 可以获得所有包含load的顶级Numpy命名空间
- 变量前后使用?,可以显示对象信息
- ??可以显示源码
- 可以搜索ipython的命名空间。字符与通配符结合可以匹配所有名字
%run:运⾏所有的Python程序
这段脚本运⾏在空的命名空间(没有import和其它定义的变 量),因此结果和普通的运⾏⽅式python script.py相同。
# 假设有⼀个⽂件ipython_script_test.py:
def f(x, y, z):
return (x + y) / z
a = 5
b = 6
c = 7.5
result = f(a, b, c)
⽂ 件中所有定义的变量(import、函数和全局变量,除⾮抛出异 常),都可以在IPython shell中随%load后访问:
%run ipython_script_test.py
c
result
%load
在Jupyter notebook中,你也可以使⽤%load,它将脚本导⼊到 ⼀个代码格中:
%load ipython_script_test.py
def f(x, y, z):
return (x + y) / z
a = 5
b = 6
c = 7.5
result = f(a, b, c)
中断运⾏的代码:按Ctrl-C
从剪贴板执⾏程序:
- jupyter notebook:直接复制粘贴使用
- ipython:要用%paste或%cpaste
- 输入%paste即可
- 使⽤%cpaste,你可以粘贴任意多的代码再运⾏。你可能想在运 ⾏前,先看看代码。如果粘贴了错误的代码,可以⽤Ctrl-C中 断。
集成Matplotlib:jupyter notebook的做法
%matplotlib inline #读取matplotlib
# 试用
import matplotlib.pyplot as plt
import numpy as np
plt.plot(np.random.randn(50).cumsum())
2.3 python语法基础
- 冒号标志着缩进代码块的开始,冒号之后的所有代码的缩进量必 须相同,直到代码块结束。
笔记:我强烈建议你使⽤四个空格作为默认的缩进,可以使 ⽤tab代替四个空格。许多⽂本编辑器的设置是使⽤制表位替 代空格。某些⼈使⽤tabs或不同数⽬的空格数,常⻅的是使 ⽤两个空格。⼤多数情况下,四个空格是⼤多数⼈采⽤的⽅ 法,因此建议你也这样做。
- Python的语句不需要⽤分号结尾。但是,分号 却可以⽤来给同在⼀⾏的语句切分:
- # :做注释
函数和对象⽅法调⽤
⼏乎Python中的每个对象都有附加的函数,称作⽅法,可以⽤来 访问对象的内容。
可以用下面语句调用
obj.some_method(x, y, z)
函数可以使⽤位置和关键词参数:
result = f(a, b, c, d=5, e='foo')
变量和参数传递(没太懂)
比较两种:
- 当在Python中创建变量(或名字),你就在等号右边创建了⼀个 对这个变量的引⽤。
- 当你将对象作为参数传递给函数时,新的局域变量创建了对原始 对象的引⽤,⽽不是复制。如果在函数⾥绑定⼀个新对象到⼀个 变量,这个变动不会反映到上⼀层。因此可以改变可变参数的内 容。
理解Python的引⽤的含义,数据是何时、如何、为何复制的,是 ⾮常重要的。尤其是当你⽤Python处理⼤的数据集时。
赋值也被称作绑定,我们是把⼀个名字绑定给⼀个对 象。变量名有时可能被称为绑定变量。
动态引用,强类型
- 强类型:比如 '5'+5会报错,因为一个是字符串,一个是数字
- 用isinstance来检查:用类型元组(类型1,类型2)也可以
In [21]: a = 5
In [22]: isinstance(a, int)
Out[22]: True
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
属性和方法:⽤obj.attribute_name访问属性和⽅法
Python的对象通常都有:
- 属性(其它存储在对象内部的Python对 象)
- ⽅法(对象的附属函数可以访问对象的内部数据)
访问方法:先输入a. 然后按tab,就会弹出列表
也可以⽤getattr函数,通过名字访问属性和⽅法:
In [27]: getattr(a, 'split')
Out[27]: <function str.split>
鸭子类型(不太懂)
经常地,你可能不关⼼对象的类型,只关⼼对象是否有某些⽅法 或⽤途。这通常被称为“鸭⼦类型”,来⾃“⾛起来像鸭⼦、叫起来 像鸭⼦,那么它就是鸭⼦”的说法。
例如,你可以通过验证⼀个 对象是否遵循迭代协议,判断它是可迭代的。
对于许多对象,这 意味着它有⼀个__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)
引入:
模块:有.py扩展名、包含python代码的文件
例子:假设已经有一个模块(名称为some_module,所以文件名应该为some_module.py)
# some_module.py
PI = 3.14159
def f(x): return x + 2
def g(a, b): return a + b
则要引用的时候就用import
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
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、
In [40]: a == c
Out[40]: True
注:这里是因为 list()实际上是复制新的列表的意思,所以a、c用is not 就会得出来TRUE
相反的,==是绝对等于,比较的是值,所以a==c
可变与不可变对象:尽量用不可变方式,如果用可变,需要在文档或注释说明
可变: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)
51
<ipython-input-47-b7966a9ae0f1> in <module>()
----> 1 a_tuple[1] = 'four'
TypeError: 'tuple' object does not support item assig
标量类型
数值类型
Python的主要数值类型是int和float。
- int可以存储任意⼤的 数:
- 浮点数使⽤Python的float类型。;不能得到整数的除法会得到浮点数:
- 得C-⻛格的整除(去掉⼩数部分),可以使⽤底除运算 符//:
字符串:不可变,无法修改字符串
- "" 或''
- 有换⾏符的字符串,可以使⽤三引号,'''或"""都⾏:
c = """
This is a longer string that
spans multiple lines
"""
字符串c实际包含四⾏⽂本,"""后⾯和lines后⾯的换⾏符。
可以 ⽤count⽅法计算c中的新的⾏:
In [55]: c.count('\n')
Out[55]: 3
- 许多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] 被称作切⽚
- 反斜杠是转义字符,意思是它备⽤来表示特殊字符,⽐如换⾏符 \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'
将两个字符串合并,会产⽣⼀个新的字符串:
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 seco
模板化或格式化
{0:.2f} 表示格式化第⼀个参数为带有两位⼩数的浮点数。
{1:s} 表示格式化第⼆个参数为字符串。
{2:d} 表示格式化第三个参数为⼀个整数。
字节和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
⽤decode⽅法可以解 码
In [81]: val_utf8.decode('utf-8')
Out[81]: 'español'
日期和时间
Python内建的datetime模块提供了datetime、date和time类 型。
- 可以用date()、time()提取出各自对象
- strftime⽅法可以将datetime格式化为字符串:
- strptime可以将字符串转换成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
In [106]: dt.date()
Out[106]: datetime.date(2011, 10, 29)
In [107]: dt.time()
Out[107]: datetime.time(20, 30, 21)
In [108]: dt.strftime('%m/%d/%Y %H:%M')
Out[108]: '10/29/2011 20:30'
In [109]: datetime.strptime('20091031', '%Y%m%d')
Out[109]: datetime.datetime(2009, 10, 31, 0, 0)
当你聚类或对时间序列进⾏分组(也就是,比如说将29号的放在一起,这时候就希望分钟和秒钟都是0,就好分类,替换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
- delta = 两个时间结点相减
- 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是最⼴为⼈知的控制流语句。它检查⼀个条件,如果为True, 就执⾏后⾯的语句:
- if后⾯可以跟⼀个或多个elif,所有条件都是False时,还可以 添加⼀个else:
- 如果某个条件为True,后⾯的elif就不会被执⾏。
if x < 0:
print('It's negative')
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')
当使⽤and和 or时,复合条件语句是从左到右执⾏:
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不会被执⾏,因为第⼀个⽐较是True:
也可以把⽐较式串在⼀起:
In [120]: 4 > 3 > 2 > 1
Out[120]: True
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
+=是什么:【同理可推减法、乘法等】
+= | 加法赋值运算符 |
- 可以⽤break跳出for循环。下⾯的代码将各元素相加,直到遇到 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循环的最内层,其余的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:占一行
python中if ,for等复合语句通常是由一个语句头和语句体构成。
语句体中出现的语句数量并没有限制,但是至少需要一行。偶尔可能会需要一个语句体什么也不做(通常是标记一个你还没来得及写的代码的位置),这个时候就需要pass了。
pass是空语句,是为了保持程序结构的完整性,避免语法错误。
比如说:我觉得if的语句,需要true的时候返回1,但是false是没想好返回什么,这个时候不能空着,可以用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的三个参数是(起点,终点,步进):
可以看到,range产⽣的整数不包括终点。
初值为0,步长为1,可以省略
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的常⻅⽤法是⽤ 序号迭代序列:????
seq = [1, 2, 3, 4]
for i in range(len(seq)):
val = seq[i]
三元表达式
Python中的三元表达式可以将if-else语句放到⼀⾏⾥。
语法如 下:
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可以包含⼤量的计算,但只有True的分⽀会被执⾏。 虽然使⽤三元表达式可以压缩代码,但会降低代码可读性。