Python基础用法

在这一节并不涉及Python的特殊规则和细节, 目的是把Python先用起来。 不同于 C 等语言需要先编译才能运行, Python 具有交互操作的能力, 而且也可以像脚本文件一样运行。

Python运行方式

Python交互运行方式

为了快速开始使用,先看一下交互式运行的用法:

Linux下, 打开终端, 在其中键入 python3 (若安装 ipython,可以键入 ipython3 )。 这样就打开了交互式的Python Shell。

在Shell下键入的内容.

In [26]:
print('Hello, Python World!')
Hello, Python World!

print() 格式化输出函数,输出括号里的参数,参数可以是字符串,也可以是数字。如果参数是空,输出结果也是空。

In [27]:
strval1 = 'Welcome '
strval2 = 'Python World!'     
strval1 + strval2
Out[27]:
'Welcome Python World!'

给变量strval1,strcal2赋值。格式化输出变量。

Python运行程序文件

还有一种方式是将 Python 代码写入到文件中(不是一行行的粘贴), 在 Linux 下,可以通过终端、文本编辑器(配置了运行环境的VIM)或 IDE(如 PyCharm ) 中来运行; 在Windows下,可以在终端,或在 IDLE 中打开然后运行。 这样的文件,被称为脚本文件。通过这种方式,能够修改和实验这些设置,然后重新运行脚本。

使用文本编辑器新建一个文件,输入下面代码:

In [28]:
print('Hello, Python World!')
strval1 = 'Welcome'
strval2 = 'Python World!'
print(strval1)
print(strval1 + strval2)
Hello, Python World!
Welcome
WelcomePython World!

保存文件, 注意后缀为 py 。 例如, 保存为 demo1.py 。 然后Windows下打开DOS窗口, 输入:

python3 path_to_filedemo1.py

Linux下类似。 若提示没有python程序, 参考前面环境变量设置部分。

Linux下面的运行方式

在Linux下,创建一个空白的纯文本文件,然后给其添加可执行的权限:

chmod +x world.py

然后,在脚本文件的头部添加如下的代码行:

#!/usr/bin/env python3

在下面,就如同交互模式一样,将代码写入到文件中。当然代码要注意其语法。 最后就是保存文件,保存的时候,有的编辑器或操作系统中,要注意文本文件的编码。 使用 Python 3 ,要将文件保存为 UTF-8 编码的文件。

关于中文的处理,在Python也是一个经常会遇到的问题,尽管在 Python3中已经大大简化了文件编码的问题, 但是在 GIS 的应用,还有许多的类库在继续使用 Python 2。 这个问题的阐述足够使用一个单独的章来说明,但是不适合在本书中展开说明,所以在本书中不会做过多的说明。

代码结构、基本类型与保留字、运算符

程序编码

Python脚本文件的默认后缀为 .py ,Python 2中文件默认是ASCII编码。 如果文件中有中文的话,在显示时会做一个ASCII到系统默认编码的转换, 这时就会出错:SyntaxError: Non-ASCII character。 需要在代码文件的第一行或第二行添加编码指示:

# -*- coding:utf-8 -*-

编码可以是utf-8, gbk, cp936, gb2312。 Windows下使用IDLE, 若代码中使用了非ASCII代码, 则在保存的时候会提示, 一般是cp936;新版本的Eclipse一般都默认是UTF-8。 建议都使用 UTF-8。

行结构/缩进

程序中的每个语句都是以换行符结束。 特别长的语句可以使用续行符()来分成几个短小的行, 如下例:

In [29]:
import math

import math 导入数学模块。

In [30]:
n,x,y = 2, 8, 9

n,x,y = 2, 8, 9 分别给n,x,y赋值。

In [31]:
a = (math.cos(3*(x-n)) + math.sin(3*(y-n)))
print(a)
1.4969723467801361

变量a赋值,调用数学模块cos、sin

sin() 返回的x弧度的正弦值。 语法:

In [32]:
import math
x = 8
math.sin(x)
Out[32]:
0.9893582466233818

cos() 返回x的弧度的余弦值。 语法:

In [33]:
import math
x = 8
math.cos(x)
Out[33]:
-0.14550003380861354

注意:cos() 和 sin()是不能直接访问的,需要导入 math 模块,然后通过 math 静态对象调用该方法。

  • 格式化输出变量a。

当你定义一个三引号字符串、列表、tuple 或者字典的时候不需要使用续行符来分割语句。 即,在程序中, 凡是圆括号 (, , , ) 、方括号\ [, , , ]\ 、 花括号\ {, , , }\ 及三引号\ '''\ 或\ """\ 字符串内的部分均不需要使用续行符。

缩进

缩进被用来指示不同的代码块, 比如函数的主体代码块, 条件执行代码块, 循环体代码块及类定义代码块。 缩进的空格(制表符)数目可以是任意的, 但是在整个块中的缩进必须一致。

根据目前大多数程序员的习惯,以及 Python 编码的相关规范 , 这里强烈要求使用4个空格来进行缩进。 使用其他的缩进方式也可以,但是在交流中会遇到大量的问题。

In [34]:
a = 13
b = 50
if a > b:
     print('A is greater than B.')
else:
    print('B is greater than A.')
B is greater than A.

条件判断语句,变量a大于b 执行后面语句。否则执行else下语句。

条件代码块缩进。

v3.0后,确切的讲, int 型(依赖运行环境C编译器中long型的精度)消失了,long型替代 int 型, 成为新的、不依赖运行环境的、无精度限制的(只要内存装得下)int型。

Python内建数据类型

Python 有多种内置数据类型。 以下是比较重要的一些:

  • Booleans[布尔型] 或为 True[真] 或为 False[假]。
  • Numbers[数值型] 可以是 Integers[整数](1 和 2)、Floats[浮点数](1.1 和 1.2)、Fractions[分数](1/2 和 2/3);甚至是 Complex Number[复数]。
  • Strings[字符串型] 是 Unicode 字符序列, 例如: 一份 HTML 文档。
  • Bytes[字节] 和 Byte Arrays[字节数组], 例如: 一份 JPEG 图像文件。
  • Lists[列表] 是值的有序序列。
  • Tuples[元组] 是有序而不可变的值序列。
  • Sets[集合] 是装满无序值的包裹。
  • Dictionaries[字典] 是键值对的无序包裹。

当然, 还有更多的类型。 在 Python 中存在像 module [模块]、 function [函数]、 class [类]、 method [方法]、 file [文件] 甚至 compiled code [已编译代码] 这样的类型。

True False

布尔类型或为真或为假。 Python 有两个命名为 True 和 False 的常量, 用于对布尔类型的直接赋值。 表达式也可以计算为布尔类型的值。 在某些地方(如 if 语句), Python 就是一个可计算出布尔类型值的表达式。 这些地方则称为 布尔类型上下文环境。 事实上,可以在布尔类型上下文环境中使用任何表达式, Python 将试图判断其真值。 在布尔类型上下文环境中, 不同的数据类型对于何值为真假有着不同的规则。

In [35]:
print ( 4 > 30 )
print(True | False)
False
True

print()参数为表达式,所以输出后为布尔类型。

数值类型

Python中有四种内建的数值类型:整数、长整数、浮点数和复数。

In [36]:
import math
int_a = 3
int_b = 4
int_c =  5

定义变量a,b,c为整数型。

在Python 3里,只有一种整数类型int,大多数情况下,它很像Python 2里的长整型。由于已经不存在两种类型的整数,所以就没有必要使用特殊的语法去区别他们。

In [37]:
print( int_b / int_a)
print( int_b * 1.0 / int_a)
1.3333333333333333
1.3333333333333333

注意不同类型变量参加计算的精度

In [38]:
print(divmod ( int_b, int_a))
print(divmod ( int_b * 1.0, int_a))
(1, 1)
(1.0, 1.0)

内建的除法函数,返回商与余数

In [39]:
com_i = int_a + int_b * 1j

复数类型

In [40]:
print(abs(com_i))
print( math.sqrt(int_a**2 +  int_b**2))
5.0
5.0

求向量长度

尽管Python的内建数据类型很强大, 但是作为计算机语言, 不能等同于数据公式来使用。 例如, 我想表示一下欧拉恒等式 [2]

print(math.pow(math.e, math.pi * (0 + 1j)) + 1)

这个是不行的。

字符串

Python目前支持两种类型的字符串:8位字符数据 (ASCII)、16位宽字符数据 (Unicode)。

最常用的是ASCII字符串, 因为这个字符集刚好只用一个字节就可以表示字符集中的任意一个字符。 通常情况下, ASCII字符串用单引号( ' ), 双引号( " ), 或者三引号( '''""" )来定义,且字符串前后的引号类型必须一致。 反斜杠( \)用来转义特殊字符, 如换行符、反斜杠本身、引号以及其他非打印字符。 Table 2.1中列出了公认的特殊字符的表示方法, 无法识别的转义字符串将被原样保留(包括前边的反斜杠)。 此外, 字符串可以包含嵌入的空字节和二进制数据。 三引号字符串中可以包含不必转义的换行符和引号。

In [41]:
print('abcd')
print("abcd")
print('''abcd''')

print('ab"cd')
print("ab'cd")
print('''a'b"c'd''')
abcd
abcd
abcd
ab"cd
ab'cd
a'b"c'd
In [42]:
print('abcd      efgh')
abcd      efgh
In [43]:
print('abcdnefgh')
abcdnefgh
In [44]:
print('''abcd
    fdsf''')
abcd
    fdsf

目前只考虑ASCII字符串。 另外需要注意字符的转义,因为这在每种语言中都会碰到。

标识符及保留字、运算符、分隔符及特殊符号

有了前面的介绍, 这几部分自己找资料看吧。

流程控制

控制流语句的作用是改变语句流的执行顺序。 在Python中有三种控制流语句—— ifforwhile , 以及关键字: breakcontinue

if语句

if 语句用来检验一个条件, 如果条件为真, 运行一块语句(称为 if- 块), 否则 处理另外一块语句(称为 else- 块 )。 else 从句是可选的

In [45]:
number = 23

guess = 3

if guess == number:   #注意if语句在结尾处包含一个冒号,下面跟着一个相应的语句块(当然还包括正确的缩进)。
    
    print ('Congratulations, you guessed it.')
    print ("(but you do not win any prizes!)") 
    
elif guess < number:      #elif和else从句也必须在逻辑行结尾处有一个冒号
    print ('No, it is a little higher than that') 
else:
    print ('No, it is a little lower than that')     
print ('Done')
No, it is a little higher than that
Done

raw_input 函数是为了从终端得到一个输入。这里要保证输入的是数值, 程序没有针对异常进行处理。

在Python中没有switch语句。 可以使用if..elif..else语句来完成同样的工作(在某些场合,使用字典会更加快捷。 )

while语句

只要在一个条件为真的情况下, while语句允许你重复执行一块语句。 while语句是所谓 循环 语句的一个例子。 while语句有一个可选的else从句(这一点与C等也不一样)。

while 循环条件变为 False 的时候,else 块才被执行。 如果while循环有一个else从句, 它将始终被执行, 除非while循环将永远循环下去不会结束。

else 块事实上是多余的, 因为可以把其中的语句放在同一块(与while相同)中, 跟在while语句之后, 这样可以取得相同的效果。

循环语句 for语句

for..in是另外一个循环语句, 它在一序列的对象上 递归, 即逐一使用队列中的每个项目。

In [46]:
rangs = range(1,5)
print(rangs)
for val in rangs:
    print (val)
else:
    print ('The for loop is over')
range(1, 5)
1
2
3
4
The for loop is over

这里使用了内建的range()函数来生成序列。

for循环在这个范围内递归——for i in range(1,5)等价于for i in [1, 2, 3, 4], 这就如同把序列中的每个数(或对象)赋值给i, 一次一个, 然后以每个i的值执行这个程序块。

与while一样, else部分是可选的。 如果包含else, 它总是在for循环结束后执行一次, 除非遇到break语句。

Python的for循环从根本上不同于C/C++的for循环。 C# 程序员会注意到Python的for循环与 C# 中的foreach循环十分类似。 Java程序员会注意到它与Java 1.5中的for (int i : IntArray)相似。

在C/C++中, 如果你想要写 for (int i = 0; i &lt; 5; i++) , 那么用Python, 你将写成 for i in range(0,5) 。 你会注意到, Python的 for 循环更加简单、明白、不易出错。

break语句

break语句是用来 终止循环语句的, 即使循环条件没有称为False或序列还没有被完全递归, 也停止执行循环语句。

如果你从for或while循环中终止 , 任何对应的循环else块将不执行。

在这个程序中, 我们反复地取得用户进行输入,然后打印每次输入的长度。 我们提供了一个特别的条件来停止程序, 即检验用户的输入是否是’quit’。 通过 终止循环来停止程序。

输入字符串的长度通过内建的len函数取得。

注意:break语句也可以在for循环中使用。

continue语句

continue语句被用来告诉Python跳过当前循环块中的剩余语句, 然后继续 进行下一轮循环。

In [47]:
for i in range(1, 20):
    if i % 2 == 1:
        print(i)
    else:
        continue
1
3
5
7
9
11
13
15
17
19

上面程序是将20以下的奇数打印出来。 continue与break不一样, 它并不退出循环, 但会什么也不做, 然后开始下一次循环。

In [ ]:
 

函数

函数概述

函数是重要的程序段。 它允许你给一块语句一个名称, 然后你可以在你的程序的任何地方使用这个名称任意多次地运行这个语句块。 这被称为调用函数。

函数通过 def 关键字定义。 def 关键字后跟一个函数的标识符名称, 然后跟一对圆括号。 圆括号之中可以包括一些变量名, 该行以冒号结尾。 接下来是一块语句, 它们是函数体。

In [48]:
def sayHello():
    print('Hello World!')
sayHello()
Hello World!

def sayHello() 通过def关键字定义sayHello函数。并且带有语句。

上面的函数打印了一些字符;但有时, 函数若有返回值会更有用。 如给定了半径, 得到圆的面积, 可以在以后使用。

In [49]:
import math
def get_circle_area(r):
    area = math.pi * r * r
    return(area)
val_r = 3
the_area = get_circle_area(val_r)
print(the_area)
28.274333882308138

return(area) 返回area的值。

注意, 所有的 Python函数都有返回值。 没有显式声明 return 语句的函数等价于 return NoneNone 是Python中表示没有任何东西的特殊类型,如果一个变量的值为 None , 表示它没有值。 除非你提供你自己的return语句, 每个函数都在结尾暗含有return None语句。

函数取得的参数是你提供给函数的值, 这样函数就可以利用这些值做一些事情。 这些参数就像变量一样, 只不过它们的值是在我们调用函数的时候定义的, 而非在函数本身内赋值。

参数在函数定义的圆括号对内指定, 用逗号分割。 当我们调用函数的时候, 我们以同样的方式提供值。 注意我们使用过的术语——函数中的参数名称为形参, 而你提供给函数调用的值称为实参 。

变量作用域

当你在函数定义内声明变量的时候, 它们与函数外具有相同名称的其他变量没有任何关系, 即变量名称对于函数来说是 局部 的。 这称为变量的 作用域 。 所有变量的作用域是它们被定义的块, 从它们的名称被定义的那点开始。

In [50]:
def func(x):
    print ('x is', x)
    x = 2
    print ('Changed local x to', x)
x = 50
func(x)
print ('x is still', x)
x is 50
Changed local x to 2
x is still 50

函数func(x) 中的x对于func()是局部的。

如果你想要为一个定义在函数外的变量赋值, 那么你就得告诉Python这个变量名不是局部的, 而是 全局 的。 我们使用global语句完成这一功能。 没有global语句, 是不可能为定义在函数外的变量赋值的。

因为全局变量会带来很多问题,所有在写代码的过程中, 一定避免使用这一功能。

使用参数的默认值

对于一些函数, 你可能希望它的一些参数是 可选 的, 如果用户不想要为这些参数提供值的话, 这些参数就使用默认值。 这个功能借助于默认参数值完成。 你可以在函数定义的形参名后加上赋值运算符(=)和默认值, 从而给形参指定默认参数值。

注意, 默认参数值应该是一个参数。 更加准确的说, 默认参数值应该是不可变的。

In [51]:
def say(message, times = 1):  
    print (message * times)
say('Hello')
say('World', 5)
Hello
WorldWorldWorldWorldWorld

注意:若函数定义处 times参数没有默认值, 则say(’Hello’)会出错。

关键字参数

如果你的某个函数有许多参数, 而你只想指定其中的一部分, 那么你可以通过命名来为这些参数赋值——这被称作 关键参数字 ——我们使用名字(关键字)而不是位置(我们前面所一直使用的方法)来给函数指定实参。

这样做有两个优势,一、我们不必担心参数的顺序, 使用函数变得更加简单了。 二、假设其他参数都有默认值, 我们可以只给我们想要的那些参数赋值。

In [52]:
def func(a, b=5, c=10):
    print ('a is', a, 'and b is', b, 'and c is', c)
func(3, 7)
func(25, c=24)
func(c=50, a=100)
a is 3 and b is 7 and c is 10
a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50

当非关键字可变长参数和关键字可变长参数出现在同一个函数中时,他们应当遵守如下的顺序约定:

In [53]:
def newfoo(normal_arg1, normal_arg2, *argv, ** keywords):
    pass

当然,你也可以直接向函数中传入元组和字典对象,如:

In [54]:
newfoo(2, 4, *(6, 8), **{'foo': 10, 'bar': 12})

也可以来个“混搭”,孤立的可变长参数将会被放入对应的tuple或dict中,如:

In [55]:
aTuple = [3,4]
aDict = {'m': 1, 'n':2}
newfoo(2, 4, 3, x=4, y=5, *aTuple, **aDict) 

在这个例子中,参数3会被放入aTuple,参数x=4和y=5会被放入aDict

模块的基本语法

你已经学习了如何在你的程序中定义一次函数而重用代码。

如果你想要在其他程序中重用很多函数,

那么你该如何编写程序呢?就是使用模块。

模块基本上就是一个包含了所有你定义的函数和变量的文件。

为了在其他程序中重用模块, 模块的文件名必须以.py为扩展名。

使用import语句

模块可以从其他程序 输入 以便利用它的功能。

这也是我们使用Python标准库的方法。 首先, 我们将学习如何使用标准库模块。

以os模块为例, 下面程序打印出给定目录下满足特定条件(文件名中含’wx’,后缀为’py’)的文件的路径。

In [56]:
import os
def print_file_path(indir):
    for wroot, wdirs, wfiles in os.walk(indir):
        for wfile in wfiles:
            (file_name, file_ext) = os.path.splitext(wfile)
            if ('wx' in file_name ) and ( file_ext == '.py'):
                filepath = os.path.join(wroot, wfile)
                print(filepath)
if __name__ == '__main__':
    inws = '/home/bk/progs'
    print_file_path(inws)
  • 此例短小强悍, 充分体现了Python语言简洁的特点。 此处使用了os模块,
  • os.walk()对文件夹进行遍历, 返回元组, 其中第一个为起始路径,
  • 第二个为起始路径下的文件夹,第三个是起始路径下的文件。
  • os.path.splitext()的作用是分离文件名与扩展名。
  • os.path.join()的作用是合成文件的路径。

from..import语句

可以像内建函数一样直接使用math模块下面的sqrt(), pow()函数。如下程序:

In [57]:
from math import *
def math_demo():
    x = 3
    y = 4
    z = sqrt(pow(x,2) + pow(y,2))
    print(z)
if __name__ == '__main__':
    math_demo()
5.0

这样的优点是使得程序比较简洁,

避免使用math.sqrt()与math.pow()这样的形式。

但是, 一般说来, 应该避免使用from..import。

使用import语句, 可以使你的程序更加易读, 也可以避免名称的冲突。

即使是非常常用的math模块中的一些函数, 在其他模块,

如numpy中也能进行实现。 这样, 当同时使用这两个类库时, 就会出现冲突。

创建自己的模块

创建你自己的模块是十分简单的, 每个Python程序也是一个模块。 其扩展名为.py。 下面这个例子将会使它更加清晰。

In [58]:
def sayhi():
    print ('Hi, this is mymodule speaking.')
version = '0.1'

上面是一个模块的例子。 你已经看到, 它与我们普通的Python程序相比并没有什么特别之处。 我们接下来将看看如何在我们别的Python程序中使用这个模块。 注意这个模块应该被放置在我们输入它的程序的同一个目录中, 或者在sys.path所列目录之一, 文件名保存为mymodule.py。

import mymodule
mymodule.sayhi()
print ('Version', mymodule.version)

通过使用自定义的模块, 可以将程序放到不同的文件中进行组织, 从而方便大型程序的编写与多人协作。

pprint模块

pprint模块提供了可以按照某个格式正确的显示Python已知类型数据的一种方法,这种格式可被解析器解析, 又很易读。 但是,如果已知格式的数据对象不是python的基础类型,这种表示方法就有可能加载失败。 pprint 包含一个“美观打印机”,用于生成数据结构的一个美观视图。格式化工具会生成数据结构的一些表示, 不仅可以由解释器正确地解析,而且便于人类阅读。输出尽可能放在一行上,分解为多行时则需要缩进。

Python中的序列

列表

list是处理一组有序项目的数据结构, 即你可以在一个列表中存储一个 序列 的项目。 假想你有一个购物列表, 上面记载着你要买的东西, 你就容易理解列表了。 只不过在你的购物表上, 可能每样东西都独自占有一行, 而在Python中, 你在每个项目之间用逗号分割。

列表中的项目应该包括在方括号中, 这样Python就知道你是在指明一个列表。 一旦你创建了一个列表, 你可以添加、删除或是搜索列表中的项目。 由于你可以增加或删除项目, 我们说列表是 可变的 数据类型, 即这种类型是可以被改变的。

注意, 列表与数组不同(尽管都是在方括号中)。 Python的列表中可以存储不同的数据类型:

In [59]:
list_val = [1, '3', 5 ,'4']

python3 range() 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以打印的时候不会打印列表。

In [60]:
list_val = [1, '3', 5 ,'4'] 
list_val = range(5,0, -1) 
print(list_val)
range(5, 0, -1)

list() 函数是对象迭代器,把对象转为一个列表。返回的变量类型为列表。

In [61]:
list_val = [1, '3', 5 ,'4']
list_val = list(range(5,0, -1)) 
print(list_val)
[5, 4, 3, 2, 1]

append() 方法用于在列表末尾添加新的对象。

In [62]:
list_val = [1, '3', 5 ,'4']
list_val.append(6) 
print(list_val)
[1, '3', 5, '4', 6]
In [63]:
list_val = [1, '3', 5 ,'4']
list_val = list_val + [7,8]
print(list_val)
[1, '3', 5, '4', 7, 8]

extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)

In [64]:
list_val = [1, '3', 5 ,'4']
list_val.extend([9, 10])  
list_val
Out[64]:
[1, '3', 5, '4', 9, 10]

insert() 函数用于将指定对象插入列表的指定位置。

In [65]:
list_val = [1, '3', 5 ,'4']
list_val.insert(7, 6)   
print(list_val)
[1, '3', 5, '4', 6]

pop() 函数用于移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。

In [66]:
list_val = [1, '3', 5 ,'4']
tep_a = list_val.pop()   
print(list_val)
print(tep_a)
[1, '3', 5]
4
In [67]:
list_val = [1, '3', 5 ,'4']
tep_a = list_val.pop(3)  
print(list_val)
print(tep_a)
[1, '3', 5]
4

Python index() 方法检测字符串中是否包含子字符串 str ,如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内,该方法与 python find()方法一样,只不过如果str不在 string中会报一个异常。

In [68]:
list_val = [1, '3', 5 ,'4','3']
val_index = list_val.index('4')   
print(list_val)
print(val_index)
[1, '3', 5, '4', '3']
3

remove() 函数用于移除列表中某个值的第一个匹配项。

In [69]:
list_val = [1, '3', 5 ,'4']
list_val.remove('3')   
print(list_val)
[1, 5, '4']
In [70]:
list_val = [1, '3', 5 ,'4']
for val in list_val:
    print(val)
1
3
5
4
In [71]:
list_val = [1, '3', 5 ,'4']
print(len(list_val))
4

sort() 函数用于对原列表进行排序,如果指定参数,则使用比较函数指定的比较函数。

In [72]:
list_val = ['1', '3', '5' ,'4']
list_val.sort()  
print(list_val)
['1', '3', '4', '5']

reverse() 函数用于反向列表中元素。

In [73]:
list_val = [1, '3', 5 ,'4']
list_val.reverse()  
print(list_val)
['4', 5, '3', 1]

元组

元组和列表十分类似, 只不过元组和字符串一样是 不可变的 即你不能修改元组。 元组通过圆括号中用逗号分割的项目定义。 元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候, 即被使用的元组的值不会改变。

元组和列表可以进行转换:

In [74]:
a = range(8)
print(a)
b = tuple(a)
print(b)
c = list(b)
print(c)
range(0, 8)
(0, 1, 2, 3, 4, 5, 6, 7)
[0, 1, 2, 3, 4, 5, 6, 7]

序列

列表、元组和字符串都是序列, 但是序列是什么, 它们为什么如此特别呢?序列的两个主要特点是索引操作符和切片操作符。 索引操作符让我们可以从序列中抓取一个特定项目。 切片操作符让我们能够获取序列的一个切片, 即一部分序列。

下面例子以列表为例, 但对于元组、字符串也都是适用的。

In [75]:
list_val = range(8,0, -1)
print(list_val)
index_list = range(8)
for index in index_list:
    print('  Index: %d'%(index))
    print(list_val[index])
print(list_val[-1])
print(list_val[-2])
print(list_val[2:])
print(list_val[:-2])
print(list_val[2:-2])
print(list_val[:])
range(8, 0, -1)
  Index: 0
8
  Index: 1
7
  Index: 2
6
  Index: 3
5
  Index: 4
4
  Index: 5
3
  Index: 6
2
  Index: 7
1
1
2
range(6, 0, -1)
range(8, 2, -1)
range(6, 2, -1)
range(8, 0, -1)

字符串处理

字符串的基本操作

Python字符串:一个有序的字符集合, 用来存储和表现基于文本的信息。 用于表示和存储文本, 是单个字符的序列, 符合序列操作。 python中字符串是不可变的, 一旦声明, 不能改变。 通常由单引号(’ ), 双引号(“ ), 三引号(”’ ”“”)包围,其中单引号和双引号可互换,三引号可以由多行组成。 三引号, 多行字符串块, 编写多行文本的快捷语法, 常用语文档字符串, 在文件的特定地点, 被当做注释。

字符是非常常用的类型。 下面是基本的用法。 还有更多的关于字符串的类库, 如string, 以及正则表达式。

In [76]:
path = r'e:\book'

print(path)
e:\book
In [77]:
print('** \n\t"\r **')
** 
 **

转义符

In [78]:
len(path)
Out[78]:
7

长度

In [79]:
str_val = 's ' + 'pam'
print(str_val)
str_val = 's '  'pam'
print(str_val)
s pam
s pam

连接's ' + 'pam' 或 's''pam' 建议使用前者,可读性

In [80]:
print('=' * 10)
==========

重复输出

In [81]:
print('abc'+str(9))
abc9

Python不允许在+表达式中出现其他类型,需要手工转换:

In [82]:
val = int('42')
print(val)
val  =str(42)
print(val)
val = float('42.0')
print(val)
42
42
42.0

字符串转换

In [83]:
print(ord('s')) #转ASCII
print(type(ord('s'))) #转ASCII
print(chr(115)) #转字符
print(type(chr(115)))
115
<class 'int'>
s
<class 'str'>

转换ASCII与字符

In [84]:
s='spam'
k = '|'.join(s)
print(k)
s='spam'
l  = list(s)
print(l)
k = '|'.join(l)
print(k)
s|p|a|m
['s', 'p', 'a', 'm']
s|p|a|m

合并与分割

In [85]:
s =  s+'a'
s = s[3:] + 'b'
s = s.replace('pl','pa')

字符串无法进行修改,但可以通过重新赋值的方法变通

In [86]:
s = 'abcdefg'
print(s[1:])
print(s[1:-1])
bcdefg
bcdef

字符串的索引和切片,前面刚讲过

In [87]:
str_val = 'abcd'
str_val = str_val.capitalize()
print(str_val)
Abcd

字符串第一个字符大写

In [88]:
str_val = str_val.lower()
print(str_val)
abcd

全变小写

In [89]:
print(str_val.isalpha())
print(str_val.isdigit())
True
False

isxxx 函数。更多请找参考手册

In [90]:
str_val = '  abcdfgxabcdyzcdba '
str_val = str_val.strip()
print(str_val)
str_val = str_val.strip('a')
print(str_val)
abcdfgxabcdyzcdba
bcdfgxabcdyzcdb

去掉字符

In [91]:
tepstr = str_val
str_val = str_val.strip('bc')
print(str_val)
str_val = tepstr.strip('cb')
print(str_val)
dfgxabcdyzcd
dfgxabcdyzcd
In [92]:
str_val = list(str_val)
str_val.sort()
str_val = ''.join(str_val)
print(str_val)
abccdddfgxyz

字符串排序

In [93]:
str_val = str_val.upper()
print(str_val)
ABCCDDDFGXYZ

全部大写

In [94]:
ind_list = range(5, 15)
ind_list = [str(x) for x in ind_list]
print(ind_list)
str_list = [ind.zfill(3) for ind in ind_list]
print(str_list)
''' 格式化输出 :
%c 单个字符
%d 十进制整数
%o 八进制整数
%s 字符串
%x 十六进制整数,
其中字母小写
%X 十六进制整数,
 其中字母大写
    '''
str_val = 'The are %d %s in the team.' % (2, 'girls')
print(str_val)
['5', '6', '7', '8', '9', '10', '11', '12', '13', '14']
['005', '006', '007', '008', '009', '010', '011', '012', '013', '014']
The are 2 girls in the team.

返回长度width的字符串,原字符串右对齐,前面填充0

像元组一样看待字符串

字符串具备很多元组的特征。 字符串与元组不同的是, 字符串内部的各个成员都是字符。

In [95]:
str_val = 'Hello, Python!'
print(len(str_val))
14

print(len(str_val)) 输出字符串长度。

In [96]:
print(str_val.index('P'))
7

输出字符P的位置

In [97]:
for x in str_val:
    print(x)
H
e
l
l
o
,
 
P
y
t
h
o
n
!

循环输出字符串的内容。

字典

字典数据结构可以理解为自然语言中的“字典”, 这种数据结构可以通过检索的文字, 来查找相关的内容。 也可以理解为通过联系人名字查找地址和联系人详细情况的地址簿, 即, 我们把键(名字)和值(详细情况)联系在一起。

注意, 键必须是唯一的, 就像如果有两个人恰巧同名的话, 你无法找到正确的信息。 当然可以再通过其它方法来变通。

更专业一点讲, 字典就是一个关联数组(或称为哈希表)。 它是一个通过关键字索引的对象的集合。 使用大括号来创建一个字典。

注意它们的键/值对用冒号分割, 而各个对用逗号分割, 所有这些都包括在花括号中。

尽管字符串是最常见的 关键字(key)类型, 你还是可以使用很多其它的 python对象做为字典的关键字, 比如 数字 和tuple, 只要是不可修改对象, 都可以用来做字典的key。

有些对象, 例如列表和字典, 不可以用来做字典的关键词, 因为他们的内容是允许更改的。

字典中的键/值对是没有顺序的。 如果你想要一个特定的顺序, 那么你应该在使用前自己对它们排序。

In [98]:
dict_demo = {'GIS': 'Geographic Information System',
        'RS': 'Remote Sencing', 
        'GPS': 'Global Positioning System',
        'DEM': 'Dynamic Effect Model'}
print(dict_demo['GPS'])
print(dict_demo['DEM'])
print(dict_demo.items())
dict_demo['DEM'] = 'Digital Elevation Model'
print(dict_demo['DEM'])
Global Positioning System
Dynamic Effect Model
dict_items([('GPS', 'Global Positioning System'), ('DEM', 'Dynamic Effect Model'), ('RS', 'Remote Sencing'), ('GIS', 'Geographic Information System')])
Digital Elevation Model

上面定义了字典, 并且说明了怎样引用。

下面我们继续来看一下字典的一些常用方法:

In [99]:
print( 'RS' in dict_demo)
print( 'rs' in dict_demo)
dict_demo['rs'] = 'Remote Sencing'
print(dict_demo.keys())
del(dict_demo['rs'])
dict_demo.keys()
for short_name, long_name in dict_demo.items():
    print(('Short Name: %4s -> Long Name: %s') % (short_name, long_name)) 
True
False
dict_keys(['rs', 'GPS', 'DEM', 'RS', 'GIS'])
Short Name:  GPS -> Long Name: Global Positioning System
Short Name:  DEM -> Long Name: Digital Elevation Model
Short Name:   RS -> Long Name: Remote Sencing
Short Name:  GIS -> Long Name: Geographic Information System

文件读写

创建、读和写文件的能力是许多程序员所必需会的。 读取一个文件, 对其中的内容进行一些处理, 然后把结果写入到另外一个文件, 应该是非常常用的一种处理模式。

In [100]:
'''
第一列为序号,后面是测量的数据。分别是萼片的长、宽,花瓣的长、宽。 把上面数据存储为data.dat,放到程序的同一目录下。
程序的目的是计算萼片与花瓣的长宽比。注意读写文件的用法。
'''

'''
id    Sepal.Length Sepal.Width Petal.Length Petal.Width
1            5.1         3.5          1.4         0.2
2            4.9         3.0          1.4         0.2
3            4.7         3.2          1.3         0.2
4            4.6         3.1          1.5         0.2
5            5.0         3.6          1.4         0.2
6            5.4         3.9          1.7         0.4
7            4.6         3.4          1.4         0.3
8            5.0         3.4          1.5         0.2
9            4.4         2.9          1.4         0.2
10           4.9         3.1          1.5         0.1
11           5.4         3.7          1.5         0.2
12           4.8         3.4          1.6         0.2
13           4.8         3.0          1.4         0.1
14           4.3         3.0          1.1         0.1
15           5.8         4.0          1.2         0.2
16           5.7         4.4          1.5         0.4
'''

fi = open('/gdata/data_io.dat')
cnts = fi.readlines()
fo = open('xx_result.dat', 'w')
for cnt in cnts:
    cnt = cnt.strip()
    if len(cnt) > 0:
        recs = cnt.split()
        if recs[0] == 'id':
            fo.write('id Sepal Petal\n')
        else:
            vals = [float(x) for x in recs[1:]]
            v1 = vals[0] / vals[1]
            v2 = vals[2] / vals[3]
            fo.write('%s %10.2f %10.2f\n' % (recs[0], v1, v2))
fo.close()
fi.close()

文件目录操作

  • os和os.path模块
  • os.listdir(dirname):列出dirname下的目录和文件
  • os.getcwd():获得当前工作目录
  • os.curdir:返回但前目录('.')
  • os.chdir(dirname):改变工作目录到dirname
  • os.path.isdir(name):判断name是不是一个目录,name不是目录就返回false
  • os.path.isfile(name):判断name是不是一个文件,不存在name也返回false
  • os.path.exists(name):判断是否存在文件或目录name
  • os.path.getsize(name):获得文件大小,如果name是目录返回0L
  • os.path.abspath(name):获得绝对路径
  • os.path.normpath(path):规范path字符串形式
  • os.path.split(name):分割文件名与目录(事实上,如果你完全使用目录,它也会将最后一个目录作为文件名而分离,同时它不会判断文件或目录是否存在)
  • os.path.splitext():分离文件名与扩展名
  • os.path.join(path,name):连接目录与文件名或目录
  • os.path.basename(path):返回文件名
  • os.path.dirname(path):返回文件路径
  • os.sep 可以取代操作系统特定的路径分割符。
  • os.name字符串指示你正在使用的平台。比如对于Windows,它是'nt',而对于Linux/Unix用户,它是'posix'。
  • os.getenv()和os.putenv()函数分别用来读取和设置环境变量。
  • os.remove()函数用来删除一个文件。
  • os.system()函数用来运行shell命令。
  • os.linesep字符串给出当前平台使用的行终止符。例如,Windows使用'/r/n',Linux使用'/n'而Mac使用'/r'。
  • os.path.isfile()和os.path.isdir()函数分别检验给出的路径是一个文件还是目录。
  • os.curdir:返回但前目录('.')可使用abspath来获取绝对路劲
  • os.mkdir(path) path:要创建目录的路径。
  • os.rmdir(path) path:要删除的目录的路径。
  • 需要说明的是,使用os.rmdir删除的目录必须为空目录,否则函数出错。
  • 若想删除非空目录,先删除目录下的文件,然后再删除目录,递归过程。

读取文件

下面是一个简单的例子。 数据是R自带的数据, 进行了简化。 数据如下:

第一列为序号, 后面是测量的数据。 分别是萼片的长、宽, 花瓣的长、宽。

数据存储为data.dat, 放到程序的同一目录下。

程序的目的是计算萼片与花瓣的长宽比。 注意读写文件的用法。

通过指明我们希望打开的文件和模式来创建一个file类的实例。

模式可以为读模式(’r’)、写模式(’w’)或追加模式(’a’)。

事实上还有多得多的模式可以使用。 如果我们没有指定模式,

读模式会作为默认的模式。

写文件

在写模式下打开文件, 采用fo.write()函数进行格式化输出, 上一节中给出了写文本文件的一个实例。

存储器

Python提供一个标准的模块, 称为pickle。 使用它你可以在一个文件中储存任何Python对象, 之后你又可以把它完整无缺地取出来。 这被称为 持久地 储存对象。

还有另一个模块称为cPickle, 它的功能和pickle模块完全相同, 只不过它是用C语言编写的, 因此要快得多(比pickle快1000倍)。 你可以使用它们中的任一个, 而我们在这里将使用cPickle模块。 记住, 我们把这两个模块都简称为pickle模块。

为了在文件里储存一个对象, 首先以写模式打开一个file对象,

然后调用储存器模块的dump函数, 把对象储存到打开的文件中。 这个过程称为 储存 。

接下来, 我们使用pickle模块的load函数的返回来取回对象。 这个过程称为 取储存 。

In [ ]: