《简明python教程》学习笔记,长文
引号:
单引号:如果包含的字符串里有单引号的话,需要在那个单引号里加转义符号,或者使用双引号
例:print 'he"llo' or print 'he\'llo' ===> he'llo
双引号:规则同上
例:print “he\"llo” or print 'he"llo' ===> he"llo
三引号: 用于多行注释
注意:在python中,单引号字符串和双引号字符串没有任何不同
在一个字符串中,行末的单独一个反斜杠表示字符串在下一行继续,而不是开始一个新的行,这点在很多长的linux命令中得到体现
例: print "a\
b " ====> ab
自然字符串:在字符串前面加上r或者R,如果字符串里有转义字符,那么将不会进行处理
例:print r"hello\n"===>hello\n
缩进:
python相同级别的字段是靠缩进来区分的
运算符:
除去常规的运算符,我没有见到过的运算符如下
//:取整运算符,返回商的整数部分,如4//3.0 ==>1.0
~:按位翻转,~x = -(x+1),如 ~5 ==> -6
运算符优先级:
想要改变运算符的优先级,需要增加括号
运算符 | 描述 |
---|---|
lambda | Lambda表达式 |
or | 布尔“或” |
and | 布尔“与” |
not x | 布尔“非” |
in,not in | 成员测试 |
is,is not | 同一性测试 |
<,<=,>,>=,!=,== | 比较 |
| | 按位或 |
^ | 按位异或 |
& | 按位与 |
<<,>> | 移位 |
+,- | 加法与减法 |
*,/,% | 乘法、除法与取余 |
+x,-x | 正负号 |
~x | 按位翻转 |
** | 指数 |
x.attribute | 属性参考 |
x[index] | 下标 |
x[index:index] | 寻址段 |
f(arguments...) | 函数调用 |
(experession,...) | 绑定或元组显示 |
[expression,...] | 列表显示 |
{key:datum,...} | 字典显示 |
'expression,...' | 字符串转换 |
控制流程:
python只有三种控制流程,if,while,for,没有switch控制流程
每种流程后都能加一个else语句表示流程结束
break语句
注意,每个控制流程的条件后面需要加个冒号:
for i in range(1,5): 等价于 for i in [1,2,3,4]:
do something
函数:
定义: def语句,语法:def fun_name():
函数中的参数叫做形参,我们提供给函数的参数叫做实参
变量的作用范围:
局部变量:
块内定义,一旦出了块的范围,变量失效
全局变量:
global语句:使得变量在整个程序体里都能被调用和修改
默认参数:
例子:
#!/usr/bin/python
# Filename: func_default.py def
say
(message, times =
1
):
print
message * times
say(
'Hello'
)
say(
'World'
,
5
)
输出结果如下
hello一遍,world输出5遍
注意:
只有在形参表末尾的那些参数可以有默认参数值,即你不能在声明函数形参的时候,先声明有默认值的形参而后声明没有默认值的形参。
这是因为赋给形参的值是根据位置而赋值的。例如,def func(a, b=5)
是有效的,但是def func(a=5, b)
是 无效的。
关键参数:
如果你的某个函数有许多参数,而你只想指定其中的一部分,那么你可以通过命名来为这些参数赋值——这被称作 :关键参数 我们使用名字(关键字)而不是位置(我们前面所一直使用的方法)来给函数指定实参。
这样做有两个 优势 :一,由于我们不必担心参数的顺序,使用函数变得更加简单了。二、假设其他参数都有默认值,我们可以只给我们想要的那些参数赋值。
例:
#!/usr/bin/python
# Filename: func_key.py 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 10a is 25 and b is 5 and c is 24
a is 100 and b is 5 and c is 50
return 语句:
相信大家都不会陌生,但是需要注意,没有返回值的return
语句等价于return None
。
None
是Python中表示没有任何东西的特殊类型。例如,如果一个变量的值为None
,可以表示它没有值。
例子:
def someFunc():
pass
pass语句表示一个空的语句块
DocString:
比较有趣的一个特性。
模块:
import sys
sys.argv是一个数组,argv[0] 为python解释编译的文件名
脚本名称总是sys.argv数组的第一个元素
字节编译的.pyc文件
输入一个模块相对来说是一个比较费时的事情,所以Python做了一些技巧,以便使输入模块更加快一些。一种方法是创建 字节编译的文件 ,这些文件以.pyc
作为扩展名。字节编译的文件与Python变换程序的中间状态有关。当你在下次从别的程序输入这个模块的时候,.pyc
文件是十分有用的——它会快得多,因为一部分输入模块所需的处理已经完成了。另外,这些字节编译的文件也是与平台无关的。所以,现在你知道了那些.pyc
文件事实上是什么了。
from..import语句
如果你想要直接输入argv
变量到你的程序中(避免在每次使用它时打sys.
),那么你可以使用from sys import argv
语句。如果你想要输入所有sys
模块使用的名字,那么你可以使用from sys import *
语句。这对于所有模块都适用。一般说来,应该避免使用from..import
而使用import
语句,因为这样可以使你的程序更加易读,也可以避免名称的冲突。
模块的__name__
每个模块都有一个名称,在模块中可以通过语句来找出模块的名称。这在一个场合特别有用——就如前面所提到的,当一个模块被第一次输入的时候,这个模块的主块将被运行。假如我们只想在程序本身被使用的时候运行主块,而在它被别的模块输入的时候不运行主块,我们该怎么做呢?这可以通过模块的__name__属性完成。
例:
#!/usr/bin/python
# Filename: using_name.py
if
__name__ ==
'__main__'
:
print
'This program is being run by itself'
else
:
print
'I am being imported from another module'
输出:
$ python using_name.pyThis program is being run by itself
$ python
>>> import using_name
I am being imported from another module
>>>
每个Python模块都有它的__name__
,如果它是'__main__'
,这说明这个模块被用户单独运行,我们可以进行相应的恰当操作。
dir()函数
可以使用内建的dir
函数来列出模块定义的标识符。标识符有函数、类和变量。
当你为dir()
提供一个模块名的时候,它返回模块定义的名称列表。
如果不提供参数,它返回当前模块中定义的名称列表。
例子内容太多,贴一个地址:http://sebug.net/paper/python/ch08s06.html
模块的用处在于它能为你在别的程序中重用它提供的服务和功能。Python附带的标准库就是这样一组模块的例子
python的一些数据结构
有三种数据结构:列表,元组和字典
列表:
处理一组有序项目的数据结构,每个项目之间用逗号分割 http://sebug.net/paper/python/ch09s02.html
元组:
元组和列表十分类似,只不过元组和字符串一样是 不可变的 即你不能修改元组。
元组通过圆括号中用逗号分割的项目定义。
元组通常用在使语句或用户定义的函数能够安全地采用一组值的时候,即被使用的元组的值不会改变。
元组之内的元组不会失去它的身份。
含有0个或1个项目的元组:
一个空的元组由一对空的圆括号组成,如myempty = ()。
然而,含有单个元素的元组就不那么简单了。
你必须在第一个(唯一一个)项目后跟一个逗号,这样Python才能区分元组和表达式中一个带圆括号的对象。
即如果你想要的是一个包含项目2的元组的时候,你应该指明singleton = (2 , )。
给Perl程序员的注释:
列表之中的列表不会失去它的身份,即列表不会像Perl中那样被打散。
同样元组中的元组,或列表中的元组,或元组中的列表等等都是如此。
只要是Python,它们就只是使用另一个对象存储的对象。
元组与打印语句:
#!/usr/bin/python
# Filename: print_tuple.pyage =
22
name =
'Swaroop'
print
'%s is %d years old'
% (name, age)
print
'Why is %s playing with that python?'
% name
输出:
Swaroop is 22 years oldWhy is Swaroop playing with that python?
定制让输出满足某种特定的格式。定制可以是%s表示字符串或%d表示整数。元组必须按照相同的顺序来对应这些定制。
然而,你可能希望使用正确的定制,从而可以避免多一层的检验程序是否正确。
在第二个print语句中,我们使用了一个定制,后面跟着%符号后的单个项目——没有圆括号。
这只在字符串中只有一个定制的时候有效。
字典: http://sebug.net/paper/python/ch09s04.html
字典类似于你通过联系人名字查找地址和联系人详细情况的地址簿,即,我们把键(名字)和值(详细情况)联系在一起。注意,键必须是唯一的,就像如果有两个人恰巧同名的话,你无法找到正确的信息。
注意,你只能使用不可变的对象(比如字符串)来作为字典的键,但是你可以不可变或可变的对象作为字典的值。基本说来就是,你应该只使用简单的对象作为键。
键值对在字典中以这样的方式标记:d = {key1 : value1, key2 : value2 }
。注意它们的键/值对用冒号分割,而各个对用逗号分割,所有这些都包括在花括号中。
记住字典中的键/值对是没有顺序的。如果你想要一个特定的顺序,那么你应该在使用前自己对它们排序。
字典是dict
类的实例/对象。
序列:
列表、元组和字符串都是序列。
序列的两个主要特点是索引操作符和切片操作符。
索引操作符让我们可以从序列中抓取一个特定项目。
切片操作符让我们能够获取序列的一个切片,即一部分序列。
#!/usr/bin/python
# Filename: seq.pyshoplist = [
'apple'
,
'mango'
,
'carrot'
,
'banana'
]
# Indexing or 'Subscription' operation
print
'Item 0 is'
, shoplist[
0
]
print
'Item 1 is'
, shoplist[
1
]
print
'Item 2 is'
, shoplist[
2
]
print
'Item 3 is'
, shoplist[
3
]
print
'Item -1 is'
, shoplist[
-1
]
print
'Item -2 is'
, shoplist[
-2
]
# Slicing on a list
print
'Item 1 to 3 is'
, shoplist[
1
:
3
]
print
'Item 2 to end is'
, shoplist[
2
:
]
print
'Item 1 to -1 is'
, shoplist[
1
:
-1
]
print
'Item start to end is'
, shoplist[:]
# Slicing on a string
name =
'swaroop'
print
'characters 1 to 3 is'
, name[
1
:
3
]
print
'characters 2 to end is'
, name[
2
:]
print
'characters 1 to -1 is'
, name[
1
:
-1
]
print
'characters start to end is'
, name[:]
输出:
Item 0 is appleItem 1 is mango
Item 2 is carrot
Item 3 is banana
Item -1 is banana
Item -2 is carrot
Item 1 to 3 is ['mango', 'carrot']
Item 2 to end is ['carrot', 'banana']
Item 1 to -1 is ['mango', 'carrot']
Item start to end is ['apple', 'mango', 'carrot', 'banana']
characters 1 to 3 is wa
characters 2 to end is aroop
characters 1 to -1 is waroo
characters start to end is swaroop
特别需要注意的是, 切片操作中索引的范围和range一样,截止到第二个索引值的前一个值
如果不指定第一个数,Python就从序列首开始。如果没有指定第二个数,则Python会停止在序列尾。注意,返回的序列从开始位置 开始 ,刚好在 结束 位置之前结束。即开始位置是包含在序列切片中的,而结束位置被排斥在切片外。
可以用负数做切片。负数用在从序列尾开始计算的位置
对象与参考:http://sebug.net/paper/python/ch09s06.html
用python编写脚本
问题描述:我想要一个可以为我的所有重要文件创建备份的程序
问题思路:
需要备份的文件和目录由一个列表指定。
备份应该保存在主备份目录中。
文件备份成一个zip文件。
zip存档的名称是当前的日期和时间。
我们使用标准的zip命令,它通常默认地随Linux/Unix发行版提供。Windows用户可以使用Info-Zip程序。注意你可以使用任何地存档命令,只要它有命令行界面就可以了,那样的话我们可以从我们的脚本中传递参数给它。
问题的脚本语言描述
#!/usr/bin/python
# Filename: backup_ver1.pyimport
os
import
time
# 1. The files and directories to be backed up are specified in a list.
source = [
'/home/swaroop/byte'
,
'/home/swaroop/bin'
]
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that
# 2. The backup must be stored in a main backup directorytarget_dir =
'/mnt/e/backup/'
# Remember to change this to what you will be using
# 3. The files are backed up into a zip file.
# 4. The name of the zip archive is the current date and timetarget = target_dir +
time
.strftime(
'%Y_%m_%d_%H:%M:%S'
) +
'.zip'
# 5. We use the zip command (in Unix/Linux) to put the files in a zip archive
zip_command =
"zip -qr %s %s"
% (target,
' '
.join(source))
# Run the backup
if
os
.system(zip_command) ==
0
:
print
'Successful backup to'
, target
else
:
print
'Backup FAILED'
运行了以上程序后会提示备份成功,输出文件为
dist2013_07_25_10:56:03.zip
程序详细解释:
我们使用了os
和time
模块,所以我们输入它们。然后,我们在source
列表中指定需要备份的文件和目录。目标目录是我们想要存储备份文件的地方,它由target_dir
变量指定。zip归档的名称是目前的日期和时间,我们使用time.strftime()
函数获得。它还包括.zip
扩展名,将被保存在target_dir
目录中。
time.strftime()
函数需要我们在上面的程序中使用的那种定制。%Y
会被无世纪的年份所替代。%m
会被01到12之间的一个十进制月份数替代,其他依次类推。这些定制的详细情况可以在《Python参考手册》中获得。《Python参考手册》包含在你的Python发行版中。注意这些定制与用于print
语句的定制(%
后跟一个元组)类似(但不完全相同)
我们使用加法操作符来 级连 字符串,即把两个字符串连接在一起返回一个新的字符串。通过这种方式,我们创建了目标zip文件的名称。接着我们创建了zip_command
字符串,它包含我们将要执行的命令。你可以在shell(Linux终端或者DOS提示符)中运行它,以检验它是否工作。
zip命令有一些选项和参数。-q
选项用来表示zip命令安静地工作。-r
选项表示zip命令对目录递归地工作,即它包括子目录以及子目录中的文件。两个选项可以组合成缩写形式-qr
。选项后面跟着待创建的zip归档的名称,然后再是待备份的文件和目录列表。我们使用已经学习过的字符串join
方法把source
列表转换为字符串。
最后,我们使用os.system
函数 运行 命令,利用这个函数就好像在 系统 中运行命令一样。即在shell中运行命令——如果命令成功运行,它返回0,否则它返回错误号。
根据命令的输出,我们打印对应的消息,显示备份是否创建成功。好了,就是这样我们已经创建了一个脚本来对我们的重要文件做备份!
给Windows用户的注释
你可以把source
列表和target
目录设置成任何文件和目录名,但是在Windows中你得小心一些。问题是Windows把反斜杠(\)作为目录分隔符,而Python用反斜杠表示转义符!
所以,你得使用转义符来表示反斜杠本身或者使用自然字符串。例如,使用'C:\\Documents'
或r'C:\Documents'
而不是'C:\Documents'
——你在使用一个不知名的转义符\D
!
现在省略掉中间的两个版本,最新的版本如下:
#!/usr/bin/python
# Filename: backup_ver4.py
import
os
import
time
# 1. The files and directories to be backed up are specified in a list.
source = [
'/home/swaroop/byte'
,
'/home/swaroop/bin'
]
# If you are using Windows, use source = [r'C:\Documents', r'D:\Work'] or something like that
# 2. The backup must be stored in a main backup directory
target_dir =
'/mnt/e/backup/'
# Remember to change this to what you will be using
# 3. The files are backed up into a zip file.
# 4. The current day is the name of the subdirectory in the main directory
today = target_dir +
time
.strftime(
'%Y%m%d'
)
# The current time is the name of the zip archive
now =
time
.strftime(
'%H%M%S'
)
# Take a comment from the user to create the name of the zip file
comment =
raw_input
(
'Enter a comment --> '
)
if
len
(comment) ==
0
:
# check if a comment was entered
target = today +
os
.sep + now +
'.zip'
else
:
target = today +
os
.sep + now +
'_'
+ \
comment.replace(
' '
,
'_'
) +
'.zip'
#这句话的意思是去掉注释中的空格,将其替换为下划线
# Notice the backslash!
# Create the subdirectory if it isn't already there
if not
os
.path.exists(today):
os
.mkdir(today)
# make directory
print
'Successfully created directory'
, today
# 5. We use the zip command (in Unix/Linux) to put the files in a zip archive
zip_command =
"zip -qr '%s' %s"
% (target,
' '
.join(source))
# Run the backup
if
os
.system(zip_command) ==
0
:
print
'Successful backup to'
, target
else
:
print
'Backup FAILED'
进一步优化
对于大多数用户来说,第四个版本是一个满意的工作脚本了,但是它仍然有进一步改进的空间。比如,你可以在程序中包含 交互 程度——你可以用-v
选项来使你的程序更具交互性。
另一个可能的改进是使文件和目录能够通过命令行直接传递给脚本。我们可以通过sys.argv
列表来获取它们,然后我们可以使用list
类提供的extend
方法把它们加到source
列表中去。
我还希望有的一个优化是使用tar命令替代zip命令。这样做的一个优势是在你结合使用tar和gzip命令的时候,备份会更快更小。如果你想要在Windows中使用这些归档,WinZip也能方便地处理这些.tar.gz
文件。tar命令在大多数Linux/Unix系统中都是默认可用的。Windows用户也可以下载安装它。
OOP:
程序中根据操作数据的函数或语句块来设计程序,被称为 面向过程的 编程。
还有一种把数据和功能结合起来,用称为对象的东西包裹起来组织程序的方法。这种方法称为面向对象的编程理念。
在大多数时候你可以使用过程性编程,但是有些时候当你想要编写大型程序或是寻求一个更加合适的解决方案的时候,你就得使用面向对象的编程技术。
类和对象是面向对象编程的两个主要方面。类创建一个新类型,而对象创建这个类的实例 。
类似于你有一个int
类型的变量,这存储整数的变量是int
类的实例(对象)。
注意,即便是整数也被作为对象(属于int
类)。这和C++、Java(1.5版之前)把整数纯粹作为类型是不同的。
通过help(int)
了解更多这个类的详情。
C#和Java 1.5程序员会熟悉这个概念,因为它类似 封装与解封装 的概念。
对象可以使用普通的 属于 对象的变量存储数据。属于一个对象或类的变量被称为域。。这些术语帮助我们把它们与孤立的函数和变量区分开来。域和方法可以合称为类的属性。
对象也可以使用 属于 类的函数来具有功能。这样的函数被称为类的方法
域有两种类型——属于每个实例/类的对象或属于类本身。它们分别被称为实例变量和类变量。
__init__方法:
在Python的类中有很多方法的名字有特殊的重要意义。现在我们将学习__init__
方法的意义。
__init__
方法在类的一个对象被建立时,马上运行。
这个方法可以用来对你的对象做一些你希望的 初始化 。注意,这个名称的开始和结尾都是双下划线。
使用__init__方法
#!/usr/bin/python
# Filename: class_init.py
class
Person
:
def
__init__
(self, name):
self.name = name
def
sayHi
(self):
print
'Hello, my name is'
, self.name
p = Person(
'Swaroop'
)
p.sayHi()
输出:
xxxx,swaroop
给C++/Java/C#程序员的注释
__init__
方法类似于C++、C#和Java中的 constructor 。(构造函数)
给C++/Java/C#程序员的注释
Python中所有的类成员(包括数据成员)都是 公共的 ,所有的方法都是 有效的 。
只有一个例外:如果你使用的数据成员名称以 双下划线前缀 比如__privatevar
,Python的名称管理体系会有效地把它作为私有变量。
这样就有一个惯例,如果某个变量只想在类或对象中使用,就应该以单下划线前缀。而其他的名称都将作为公共的,可以被其他类/对象使用。记住这只是一个惯例,并不是Python所要求的(与双下划线前缀不同)。
同样,注意__del__
方法与 destructor 的概念类似。
储存器
Python提供一个标准的模块,称为pickle
。使用它你可以在一个文件中储存任何Python对象,之后你又可以把它完整无缺地取出来。这被称为 持久地 储存对象。
还有另一个模块称为cPickle
,它的功能和pickle
模块完全相同,只不过它是用C语言编写的,因此要快得多(比pickle
快1000倍)。你可以使用它们中的任一个,而我们在这里将使用cPickle
模块。记住,我们把这两个模块都简称为pickle
模块。
储存与取储存
#!/usr/bin/python
# Filename: pickling.pyimport
cPickle
as p
#import pickle as p
shoplistfile =
'shoplist.data'
# the name of the file where we will store the object
shoplist = [
'apple'
,
'mango'
,
'carrot'
]
# Write to the file
f =
file
(shoplistfile,
'w'
)
p.dump(shoplist, f) # dump the object to a file
f.close()
del
shoplist
# remove the shoplist
# Read back from the storagef =
file
(shoplistfile)
storedlist = p.load(f)print
storedlist
(源文件:code/pickling.py)
输出
$ python pickling.py
['apple', 'mango', 'carrot']
它如何工作
首先,请注意我们使用了import..as
语法。这是一种便利方法,以便于我们可以使用更短的模块名称。在这个例子中,它还让我们能够通过简单地改变一行就切换到另一个模块(cPickle
或者pickle
)!在程序的其余部分的时候,我们简单地把这个模块称为p
。
为了在文件里储存一个对象,首先以写模式打开一个file
对象,然后调用储存器模块的dump
函数,把对象储存到打开的文件中。这个过程称为 储存。
接下来,我们使用pickle
模块的load
函数的返回来取回对象。这个过程称为 取储存
异常:
把所有可能引发错误的语句放在try
块中,然后在except
从句/块中处理所有的错误和异常。except
从句可以专门处理单一的错误或异常,或者一组包括在圆括号内的错误/异常。如果没有给出错误或异常的名称,它会处理 所有的 错误和异常。对于每个try
从句,至少都有一个相关联的except
从句。
如果某个错误或异常没有被处理,默认的Python处理器就会被调用。它会终止程序的运行,并且打印一个消息,我们已经看到了这样的处理。
你还可以让try..catch
块关联上一个else
从句。当没有异常发生的时候,else
从句将被执行。
我们还可以得到异常对象,从而获取更多有个这个异常的信息。
引发异常:
#!/usr/bin/python
# Filename: raising.py
class
ShortInputException
(Exception):
'''A user-defined exception class.'''
def
__init__
(self, length, atleast):
Exception.__init__(self)
self.length = length
self.atleast = atleast
try
:
s =
raw_input
(
'Enter something --> '
)
if
len
(s) <
3
:
raise ShortInputException(
len
(s),
3
)
# Other work can continue as usual here
except
EOFError:
print
'\nWhy did you do an EOF on me?'
except
ShortInputException, x:
print
'ShortInputException: The input was of length %d, \
was expecting at least %d'
% (x.length, x.atleast)
else
:
print
'No exception was raised.'