In [ ]:
%run appendix-A/simple01.py
python语言的设计特点是重视可读性、简洁性和明确性。
python是通过空白符(制表符或者空格)来阻止代码的,不像R、C++等用的是大括号。该书原作者建议使用4空格作为缩进量。
python语言的一个重要特点就是其对象模型的一致性。任何数值、字符串等都待在自己的“盒子”里,而这些“盒子”就是python的对象。
注释符使用#
几乎所有的python对象都有一些附属函数(也就是方法),它们可以访问该对象的内部数据。方法的调用时这样写的:
obj.some_method(x, y, z)
在python中对变量赋值时,你其实是在创建等号右侧对象的一个引用。用实际的例子来说,看看下面这个整数列表:
In [14]:
a = [1, 2, 3]
b = a
a.append(4)
print(a)
print(b)
用小卡特的爹(好吧,这其实是某本python书的作者,但是我实在想不起来名字了)的话就是:相当于把a和b都贴在了[1,2,3]这个上面,上面a.append[4]之后,相当于把又贴在了[1,2,3,4]上面,因为b是贴在a上的,所以b的值也被改变,成为了[1,2,3,4]。
赋值操作assignment也可以被叫做binding绑定,因为这其实是将一个名称和对象进行了捆绑。因此被赋值了得变量名有时也被称作binding variables。
当我们把对象以参数的形式传入函数时候,我们其实传入的只是引用而已,不会发生任何复制。这是python区别于一些其他语言的重要特征之一。
例如下面这个例子
In [15]:
def append_element(fanglist, element):
fanglist.append(element)
data = [1,2,3]
append_element(data, 5)
print(data)
In [23]:
a = 5
type(a)
Out[23]:
In [24]:
a = 2.5
type(a)
Out[24]:
变量其实是对象在特定命名空间中的名称而已。对象的类型信息是保存在它自己内部的。如果你因为这样就认为python不是类型语言,那就是错了。 例如我们发现把字符串和整型数据直接相加在python中是不能进行的:
In [26]:
a = 'hello'
b = 5
print('a is %s, and b is %s' % (type(a), type(b)))
c = a + b
从上面可以看出类型必须一致才能进行四则运算。从上面我们可以看出type可以用来查看一个对象的类型;反过来,python中,可以通过isinstance函数来检查一个对象是否是某个数据类型的实例。
In [29]:
a = 5
isinstance(a, int)
Out[29]:
In [30]:
a = 2.2
isinstance(a, int)
Out[30]:
instance 可以接受由类型组成的元祖。如果想检查某个对象的类型是否属于元祖中所制定的类型,可以用如下例子中的方法:
In [8]:
a = 5
b = 2.2
isinstance(a,(int,float))
Out[8]:
In [10]:
a = 5
b = 2.2
isinstance(b,(int,float))
Out[10]:
In [11]:
a = 'foo' #定义了对象
In [18]:
a.count #访问对象的方法
Out[18]:
In [19]:
#访问对象的方法还可以使用 getattr 函数 (getattr 是 getattribute 的缩写)
getattr(a, 'center')
Out[19]:
In [ ]:
__inter__
魔术方法。当然,还有一个更好一些的验证办法,即利用 iter 函数:
In [24]:
def isiterable(obj):
try:
iter(obj)
return True
except TypeError: #不可迭代
return False
#对于字符串以及大部分Python集合类型,该函数返回True:
print(isiterable([1,2]))
print(isiterable((1,2)))
print(isiterable('1'))
print(isiterable(1))
常常在编写需要处理多类型输入的函数时使用这个功能,此外还有一个常见的应用场景是:编写可以接受任何序列(列表、元祖、ndarry)或迭代器的函数。例如我们可以先检查对象是不是列表(或NumPy数组),如果不是,就将其转换成是:
In [38]:
x = (1,2) #定义了一个tuple
print(type(x))
print(isinstance(x,list) )#因为x是tuple,不是list,所以返回 False
print(isiterable(x))
if not isinstance(x,list) and isiterable(x):
#if not isiterable(x):
x = list(x)
print(x)
In [ ]:
#set up a module
PI = 3.14159
def f(x):
return (x + 2 )
def g(a, b):
return (a + b)
如果我们想要引入 simple02.py 中定义的变量和函数,我们可以在同目录下创建另一个文件,取名为 simple03.py
In [1]:
import simple02 as s2
result = s2.f(5)
print(result)
pi = s2.PI
print(pi)
sumvalue = s2.g(2,2)
print(sumvalue)
运行它:python simple03.py
(如果是在windows系统的git bash中运行python,需要先设置一下python的路径,方法是在git bash terminal中运行PATH=$PATH:/c/ProgramData/Anaconda3/,然后就可以使用python了, see referene)
或者我们也可以直接在jupyter notebook中运行,但是需要增加一些代码让系统知道module在什么位置。此处我使用了import sys的方法,这种方法参考自名为shuang的github用户:链接
以下是我摘自这位用户的wiki:
为了让我们自己写的模块能够被 Python 解释器知道,需要用sys.path.append("~/sample.py")。其实,在 Python 中,所有模块都被加入到了 sys.path 里面了。用下面的方法可以看到模块所在位置:
import sys
import pprint
pprint.pprint(sys.path)
In [20]:
#Fang code
import sys
sys.path.append("./appendix-A/simple02.py")
import simple02
result=simple02.f(5)
print(result)
In [ ]:
a + b # 求和
a - b
a*b
a/b
a//b # a 除以 b后向下圆整,丢弃小数部分
a**b # a 的 b次方
a & b # 如果a和b均为True,则结果为True. 对于整数,执行按位与操作 https://zh.wikipedia.org/wiki/%E4%BD%8D%E6%93%8D%E4%BD%9C
a|b #如果a或者b为True, 则结果为True. 对于整数,执行按位与操作
a^b #对于布尔值,如果a或者b为True(但不都为True),则结果为True. 对于整数,执行按位异或操作
a==b #如果a等于b,则结果为True
a !=b #不等,则True
a <= b、a<b # 如果a小于等于(或小于)b,则结果为True
a > b、a >= b # 如果a大于(或大于等于)b,则结果为True
a is b #如果引用a和引用b都指向同一个python对象,则结果为True
a is not b #如果引用a和引用不指向同一个python对象,则结果为True
In [37]:
#举例子来运用这些算符
a = (1,2,3)
b = a
c = 1.2
d = 2.0
e = 2
f = 3
sumtuple = a + b
print (sumtuple)
suminteger = e + f
print(suminteger)
print(c/d)
print(c//d)
print(e/f)
print(e//f)
print(e & f)
print (True & True)
print(e is f)
print (e is not f)
print (True^True)
print (True^False)
if a == b:
print('a=b')
In [ ]:
a=b=c=5
d=a+b*c
在python中,只要这些句子被求值,相关计算就会立即发生。上述的例子中,d的值会被立即设定为30。而在其他一些语言(eg. Haskell), d的值在被使用之前是不会被计算出来的。
在一些特定环境下,我们希望求值计算并不是立即进行的。特别是在密集型计算中,计算负荷重,延迟计算就可以发挥作用。Python 提供了一些技术来实现这样的计算,但是在本书中并没有做介绍。
In [39]:
a = [1,2,3,4]
a[0]=2
print(a)
另外一些对象,诸如tuple元组和字符串是不可变的immutable。 下面这个例子中,我们试图去改变tuple,但是python告诉我们这样的操作是不被支持的。
In [43]:
a_tuple = (2,3,4)
a_tuple[1]=2
Python 有一些用于处理数值数据、字符串、布尔值(True or False)以及日期/时间的内置类型。
这里我们列出主要的标量类型。后面我们将单独讨论日期/时间的处理,因为它们是由标准库中的datetime模块提供的。
标准的Python标量类型
类型 | 说明 |
---|---|
None | Python的'null'值(None只存在一个实例对象) |
str | 字符串类型。Python 2.x 中只有 ASCII 值,而Python 3中则是Unicode |
unicode | Unicode 字符串类型 |
float | 双精度(64)浮点数。注意这里没有专门的doubl类型 |
bool | True或者False |
int | 有符号整数,其最大值由平台系统决定 |
long | 任意精度的有符号整数。大的itn值会被自动转换为long |
因为我在这里使用了Markdown输入表格,所以顺便介绍下Markdown中关于表格的一些小细节
语法说明:
|、-、:之间的多余空格会被忽略,不影响布局。
默认标题栏居中对齐,内容居左对齐。
-:表示内容和标题栏居右对齐,:-表示内容和标题栏居左对齐,:-:表示内容和标题栏居中对齐。
内容和|之间的多余空格会被忽略,每行第一个|和最后一个|可以省略,-的数量至少有一个。
In [1]:
3/2
Out[1]:
但是在python2.x中,并不能默认产生这个浮点解。要产生浮点解,需要在python2.x的程序中写入
In [ ]:
from __future__ import division
如果不加这句话,也可以用显示的方式来转化,如
In [2]:
3/float(2)
Out[2]:
4)如果要得到C风格的整数除法,即除不尽时候丢弃小树,可以使用“除后圆整运算符//”
In [3]:
3//2
Out[3]:
5)在python中,复数的虚部用j表示,例如
In [5]:
a=1+2j
b=3-3j
c=a-b
print(c)
In [6]:
a='Hi, this is Yue-Wen FANG from NYU SHANGHAI'
b="He is a visiting researcher!"
c='''
##########################
##########################
##########################
'''
print(a)
print(b)
print(c)
前面我们已经提到过,字符串在python中是不可以被改变的,即immutable,如果要修改字符串就必须创建一个新的。
In [7]:
a="He is a visiting researcher!"
b=a.replace('is a visiting researcher','graduated from East China Normal University') #创建了一个新的字符串,b引用了这个新的字符串
print(a)
print(b)
In [ ]:
python中允许将其他类型转化成字符串,用str函数,例如
In [8]:
a=5
str(a)
print(a)
由于字符串其实是一串字符序列,所以可以被当作某种序列类型(类似列表、元祖等)进行处理
In [18]:
a="ALOHA!"
print(a)
list(a)
print(a[:3])
如果一个字符串包含很反斜杠,这会很让人懊恼,因为反斜杠常常会将字符进行转移。在python中,为了使得反斜杠就代表反斜杠本身而不去进行转移,可以在字符串前面加上字母r。这个在matplot里面画图添加希腊字母标注时候会显得比较有用。
In [23]:
s = 'This\\is\\a\\flower'
s1 = r'This\\is\\a\\flower'
print(s,'\t',s1)
这里重点讲一讲python 3带来的一些新的字符串格式化的手段,其实我在平时也已经在用了,但是这里再进行简短的讨论。因为在数据分析中这个经常会用到。
这里简单说一下主要的机制:以一个%开头且后面跟着一个或者多个格式字符的字符串是需要插入值的目标。这句话读起来也很拗口,让我们看例子
In [24]:
template = '%s was born in %d'
template % ('yue-wen',1990)
Out[24]:
上述,%s代表将参数格式化为字符串,%d将参数格式化为整数,这些地方都是需要实际参数来替换的,因此在上述代码的第二行中,我们使用了由值组成的元组,将这些值传入形参的位置。
In [1]:
# 再看一个例子
a=2e6
b=2.9
print('a is %d and b is %f' %(a, b))
In [2]:
True and False
Out[2]:
In [4]:
True or False
Out[4]:
** 几乎所有内置的python类型以及任何定义了nonzero魔术方法的类都能在if语句中被解释为True或者False:
In [16]:
a = [1,2,3]
b = a[:]
c = []
if a:
print('a is %s' % a)
if not b:
print('b is %s' % b)
if not c: # 因为c是空的,所以会当作False处理,not False则为True
print('c is none')
如果想知道一个对象会被强制转换成哪个布尔值,可以使用bool函数。
In [17]:
a = [1,2,3]
b = a[:]
c = []
print('The bool values of a, b, and c are %s, %s, and %s, respectively' % (bool(a), bool(b), bool(c)))
In [18]:
bool([]), bool([1]), bool('hello'), bool()
Out[18]:
In [47]:
import math
s = math.pi
a = str(s)
print(type(s))
print(type(a))
b = float(a)
int(float(a))
print(type(a))
In [48]:
a = None
a is None
Out[48]:
In [56]:
b = 5
print(b is not None)
if b is None:
print(b)
None 还是函数可选参数的一种常见默认值;(不过,虽然我知道可以这样用,但是我暂时联想不到有什么场景可以用到)
In [59]:
def add_and_maybe_multipy(a, b, c=None):
if a is not None and b is not None and c is None:
return(a+b)
else:
return(a*c)
x = add_and_maybe_multipy(1, 1, None)
y = add_and_maybe_multipy(1, 2, 3)
print('x = %d and y = %d' % (x, y))
值得注意的是, None并非是保留关键字,它只是NoneType的一个实例
In [64]:
from datetime import datetime, date, time
dt = datetime(2017, 10, 28, 19, 20, 22)
day = dt.day
print(day)
min = dt.minute
print(min)
In [65]:
dt.date()
Out[65]:
In [66]:
dt.time()
Out[66]:
strftime 方法用于将datetime格式化为字符串:
In [14]:
from datetime import datetime, date, time
dt = datetime(2017, 9, 22, 12, 30, 20)
print(dt.day)
datetime.strptime('20170923', '%Y%m%d')
#完整的格式化定义请参考表书本10-2
Out[14]:
In [ ]:
#Page 417
In [32]:
x=-1
if x<0:
print(repr("hello"))
print("%s" % ("hello"))
a = [2, 3, 4, 5, 6, 8, 10]
if type(a)==list:
print(a)
if 可以和多个 elif 以及一个“滴水不漏”的 else 块(如果所有条件都为False),例如
In [34]:
x = 10
if x<0:
print('x is negative')
elif x == 0:
print('x = 0')
elif x > 0:
print('x > 0')
else:
print('x is a complex')
In [38]:
sequence = [1, 2, None, 4, None, 5]
total = 0
for value in sequence:
if value is None:
continue
total += value
print('total is %f in this cyle' % (total))
后面我们会看到,如果集合或者迭代器的元素是序列类型,例如元组或者列表,那么还可以方便将这些元素拆散成for语句中的多个变量.
In [53]:
#使用的语法是
#for a,b,c in iterator:
# do something
#我这里只写一个简单的例子,但是这个例子可能还不是上述语法最正统的例子。
# date: 20170923
sequence = [(1,2,3),(4,5,6)]
total = 0
for (i,j,k) in sequence:
print((i,j,k))
coor = (i,j,k)
for i in coor:
i=i+1
print(i, end=' ')
print('\n')
In [55]:
x = 256
total = 0
while x > 0:
if total > 500:
break
total += x
print('total = %d' %total)
x = x//2
print('x = %d' %x)
In [ ]:
if x < 0:
print 'negative'
elif x==0:
#TO DO: here you can add codes in future
pass
else:
print 'positive'
在开发一个新功能时,常常会将pass用作代码中的占位符:
In [ ]:
def f(x,y,z):
#TODO: realize a function here
pass
In [57]:
float('1.2345')
Out[57]:
In [58]:
float('something')
In [ ]: