Python基础

来源:互联网 发布:vivo手机清除数据之后 编辑:程序博客网 时间:2024/05/04 07:43

Python

前段时间看了看python语言的一些基本语法,把python指南中一些关键点的东西摘抄下来了,就发上来吧。以下的东西都是摘抄的,没有原创的部分,大家要看仔细点的请自己去阅读《python指南》

数值

  • 赋值语句和c语言一样使用“=”号。
  • 整形数通过运算直接转换为浮点数。
  • 复数可以直接使用,3+5j,或者使用函数complex(3,5)来创造复数,可以直接取得复数的实部和虚部和模a.real,a.imag,abs(a)。
  • "_"存储最后一次运算的内容

字符串

如果我们创建一个“行”("raw")字符串,/ n序列就不会转为换行,源码中的反斜杠和换行符n都会做为字符串中的数据处理。如下所示:

hello = r"This is a rather long string containing/n/several lines of text much as you would do in C."print hello

会打印为:

This is a rather long string containing/n/several lines of text much as you would do in C.

  • 字符串可以用 + 号联接(或者说粘合),也可以用 * 号循环。
  • 字符串可以用下标(索引)查询;就像 C 一样,字符串的第一个字符下标是 0。这里没有独立的字符类型,字符仅仅是大小为一的字符串。就像在 Icon 中那样,字符串的子串可以通过切片标志来表示:两个由冒号隔开的索引。
  • 字符串中的单个字符不能修改
  • 下界比上界大的返回空字符 word[4:1],word[60:100]
  • 索引可以是负数 word[-4]
  • len() 返回字符串长度
  • Python 中定义一个 Unicode 字符串:u'Hello/u0020World !'

链表

链表中的子项不一定是同一类型的值:

a = ['spam', 'eggs', 100, 1234]

可以进行切片操作,甚至还可以改变链表的大小:

# Replace some items:
a[0:2] = [1, 12]
>>> a
[1, 12, 123, 1234]
>>> # Remove some:
... a[0:2] = []
>>> a
[123, 1234]
>>> # Insert some:
... a[1:1] = ['bletch', 'xyzzy']
>>> a
[123, 'bletch', 'xyzzy', 1234]
>>> a[:0] = a # Insert (a copy of) itself at the beginning
>>> a
[123, 'bletch', 'xyzzy', 1234, 123, 'bletch', 'xyzzy', 1234]

len()同样适用于链表

if语句

>>> x = int(raw_input("Please enter an integer: "))
>>> if x < 0:
... ... ... x = 0
... ... ... print 'Negative changed to zero'
... ... elif x == 0:
... ... ... print 'Zero'
... ... elif x == 1:
... ... ... print 'Single'
... ... else:
... ... ... print 'More'

for语句

Python 的 for 语句依据任意序列(链表或字符串)中的子项,按它们在序列中的顺序来进行迭代。例如(没有暗指):

# Measure some strings:
... a = ['cat', 'window', 'defenestrate']
for x in a:
... print x, len(x)
...
cat 3
window 6
defenestrate 12

range() 函数

range(5, 10)
[5, 6, 7, 8, 9]
range(0, 10, 3)
[0, 3, 6, 9]

range(-10, -100, -30)
[-10, -40, -70]

需要迭代链表索引的话,如下所示结合使 用range() 和 len() :

a = ['Mary', 'had', 'a', 'little', 'lamb']
for i in range(len(a)):
... print i, a[i]
...
0 Mary
1 had
2 a
3 little
4 lamb

for或者while中的else子语句

循环可以有一个 else 子句;它在循环迭代完整个列表(对于 for )或执行条件为 false (对于 while )时执行,但循环被 break 中止的情况下不会执行。以下搜索素数的示例程序演示了这个子句:

for n in range(2, 10):
... for x in range(2, n):
... if n % x == 0:
... print n, 'equals', x, '*', n/x
... break
... else:
... # loop fell through without finding a factor
... print n, 'is a prime number'
...
2 is a prime number
3 is a prime number
4 equals 2 * 2
5 is a prime number
6 equals 2 * 3
7 is a prime number
8 equals 2 * 4
9 equals 3 * 3

函数定义

关键字 def 引入了一个函数定义。

  • 在其后必须跟有函数名和包括形式参数的圆括号。
  • 函数体语句从下一行开始,必须是缩进的。
  • 函数体的第一行可以是一个字符串值,这个字符串是该函数的 (文档字符串(documentation string)),也可称作 docstring 。

def fib2(n): # return Fibonacci series up to n... """Return a list containing the Fibonacci series up to n."""
... result = []
... a, b = 0, 1
... while b < n:
... result.append(b) # see below
... a, b = b, a+b
... return result
...f100 = fib2(100) # call it
f100 # write the result
[1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

深入链表结构

  • append(x) 把一个元素添加到链表的结尾,相当于 a[len(a):] = [x]
  • extend( L)通过添加指定链表的所有元素来扩充链表,相当于 a[len(a):] = L。
  • insert( i, x) 在指定位置插入一个元素。第一个参数是准备插入到其前面的那个元素的索引,例如a.insert(0, x) 会插入到整个链表之前,而a.insert(len(a), x) 相当于 a.append(x)。
  • remove( x) 删除链表中值为x的第一个元素。如果没有这样的元素,就会返回一个错误。
  • pop( [i]) 从链表的指定位置删除元素,并将其返回。如果没有指定索引,a.pop()返回最后一个元素。元素随即从链表中被删除。(方法中i两边的方括号表示这个参数是可选的,而不是要求你输入一对方括号,你会经常在Python 库参考手册中遇到这样的标记。)
  • index( x) 返回链表中第一个值为x的元素的索引。如果没有匹配的元素就会返回一个错误
  • count( x) 返回x在链表中出现的次数。
  • sort( ) 对链表中的元素进行适当的排序。
  • reverse( ) 倒排链表中的元素。

把链表当作堆栈使用

链表方法使得链表可以很方便的做为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后一个被释放(后进先出)。

  • 用append() 方法可以把一个元素添加到堆栈顶。
  • 用不指定索引的pop() 方法可以把一个元素从堆栈顶释放出来。例如:

stack = [3, 4, 5]
stack.append(6)
stack.append(7)
stack
[3, 4, 5, 6, 7]
stack.pop()
7
stack
[3, 4, 5, 6]
stack.pop()
6
stack.pop()
5
stack
[3, 4]

把链表当作队列使用

你也可以把链表当做队列使用,队列作为特定的数据结构,最先进入的元素最先释放(先进先出)。

  • 使用 append()方法可以把元素添加到队列最后,
  • 以0为参数调用 pop() 方法可以把最先进入的元素释放出来。

例如:

queue = ["Eric", "John", "Michael"]
queue.append("Terry") # Terry arrives
queue.append("Graham") # Graham arrives
queue.pop(0)
'Eric'
queue.pop(0)
'John'
queue
['Michael', 'Terry', 'Graham']

函数化编程工具

对于链表来讲,有三个内置函数非常有用:filter(), map(), 和 reduce()。

  • "filter(function, sequence)"返回一个序列(sequence),包括了给定序列中所有调用function(item)后返回值为true的元素。(如果可能的话,会返回相同的类型)。例如,以下程序可以计算部分素数:

def f(x): return x % 2 != 0 and x % 3 != 0
filter(f, range(2, 25))
[5, 7, 11, 13, 17, 19, 23]

  • "map(function, sequence)" 为每一个元素依次调用function(item)并将返回值组成一个链表返回。例如,以下程序计算立方:

def cube(x): return xxx
map(cube, range(1, 11))
[1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]

可以传入多个序列,函数也必须要有对应数量的参数,执行时会依次用各序列上对应的元素来调用函数(如果某些序列比其它的短,就用None来代替)。如果把None做为一个函数传入,则直接返回参数做为替代。例如:

seq = range(8)
def add(x, y): return x+y
map(add, seq, seq)
[0, 2, 4, 6, 8, 10, 12, 14]

  • "reduce(func, sequence)" 返回一个单值,它是这样构造的:首先以序列的前两个元素调用函数,再以返回值和第三个参数调用,依次执行下去。例如,以下程序计算1到10的整数之和:

def add(x,y): return x+y
reduce(add, range(1, 11))
55

字典

字典在某些语言中可能称为“联合内存”(associative memories'')或“联合数组”(associative arrays'')。

  • 序列是以连续的整数为索引,与此不同的是,字典以关键字为索引,关键字可以是任意不可变类型,通常用字符串或数值。
  • 如果元组中只包含字符串和数字,它可以做为关键字,如果它直接或间接的包含了可变对象,就不能当做关键字。
  • 不能用链表做关键字,因为链表可以用它们的append() 和 extend()方法,或者用切片、或者通过检索变量来即时改变。
  • 理解字典的最佳方式是把它看做无序的关键字:值 对(key:value pairs)集合,关键字必须是互不相同的(在同一个字典之内)。
  • 一对大括号创建一个空的字典:{}。
  • 初始化链表时,在大括号内放置一组逗号分隔的关键字:值对,这也是字典输出的方式。
  • 字典的主要操作是依据关键字来存储和析取值。也可以用 del来删除关键字:值对。如果你用一个已经存在的关键字存储值,以前为该关键字分配的值就会被遗忘。试图析取从一个不存在的关键字中读取值会导致错误。
  • 字典的 keys()方法返回由所有关键字组成的链表,该链表的顺序不定(如果你需要它有序,只能调用关键字链表的sort() 方法)。
  • 使用字典的 has_key()方法可以检查字典中是否存在某一关键字。

tel = {'jack': 4098, 'sape': 4139}
tel['guido'] = 4127
tel
{'sape': 4139, 'guido': 4127, 'jack': 4098}
tel['jack']
4098
del tel['sape']
tel['irv'] = 4127
tel
{'guido': 4127, 'irv': 4127, 'jack': 4098}
tel.keys()
['guido', 'irv', 'jack']
tel.has_key('guido')
True

循环技巧

在字典中循环时,关键字和对应的值可以使用 iteritems()方法同时解读出来。

knights = {'gallahad': 'the pure', 'robin': 'the brave'}
for k, v in knights.iteritems():
... print k, v
...
gallahad the pure
robin the brave

在序列中循环时,索引位置和对应值可以使用enumerate()函数同时得到。

for i, v in enumerate(['tic', 'tac', 'toe']):
... print i, v
...
0 tic
1 tac
2 toe

同时循环两个或更多的序列,可以使用 zip() 整体解读。

questions = ['name', 'quest', 'favorite color']
answers = ['lancelot', 'the holy grail', 'blue']
for q, a in zip(questions, answers):
... print 'What is your %s? It is %s.' % (q, a)
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
What is your favorite color? It is blue.

模块

用文本编辑器把函数定义等保存为.py文件,在python中使用import 文件名(不需要.py)倒入模块

用 模块名.函数名 调用如

import a
a.set()

模块可以像函数定义一样包含执行语句。这些语句通常用于初始化模块。它们只在模块第一次导入时执行一次。

import 语句的一个变体直接从被导入的模块中导入命名到本模块的语义表中。例如:

from fibo import fib, fib2
fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

这样不会从局域语义表中导入模块名(如上所示, fibo没有定义)。

这样可以导入所有除了以下划线(_)开头的命名。

from fibo import *
fib(500)
1 1 2 3 5 8 13 21 34 55 89 144 233 377

包通常是使用用“圆点模块名”的结构化模块命名空间。
例如,名为 A.B 的模块表示了名为 "B" 的包中名为 "A" 的子模块。
正如同用模块来保存不同的模块架构可以避免全局变量之间的相互冲突,使用圆点模块名保存像 NumPy 或 Python Imaging Library 之类的不同类库架构可以避免模块之间的命名冲突。

import Sound.Effects.echo
from Sound.Effects import *

Sound是包名

输入和输出

Python总是把任意值传入 repr() 或 str() 函数,转为字符串。

  • 函数 str() 用于将值转化为适于人阅读的形式,而 repr() 转化为供解释器读取的形式(如果没有等价的语法,则会发生 SyntaxError 异常) 某对象没有适于人阅读的解释形式的话, str() 会返回与 repr() 等同的值。
  • 很多类型,诸如数值或链表、字典这样的结构,针对各函数都有着统一的解读方式。字符串和浮点数,有着独特的解读方式。(精确度)

读写文件

open() 返回一个文件对象,通常的用法需要两个参数: "open(filename, mode)"

f=open('/tmp/workfile', 'w')
print f
<open file '/tmp/workfile', mode 'w' at 80a0960>

  • 第一个参数是一个标识文件名的字符串。
  • 第二个参数是由有限的字母组成的字符串,描述了文件将会被如何使用。可选的模式 有: 'r' ,此选项使文件只读; 'w',此选项使文件只写(对于同名文件,该操作使原有文件被覆盖); 'a' ,此选项以追加方式打开文件; 'r+' ,此选项以读写方式打开文件;如果没有指定,默认为 'r' 模式。
  • 要读取文件内容,需要调用 f.read(size),该方法读取若干数量的数据并以字符串形式返回其内容,字符串长度为数值size 所指定的大小。如果没有指定 size或者指定为负数,就会读取并返回整个文件。
  • 当文件大小为当前机器内存两倍时,就会产生问题。正常情况下,会尽可能按比较大的size 读取和返回数据。如果到了文件末尾,f.read()会返回一个空字符串("")。

f.read()
'This is the entire file./n'
f.read()
''

f.readline()从文件中读取单独一行,字符串结尾会自动加上一个换行符,只有当文件最后一行没有以换行符结尾时,这一操作才会被忽略。这样返回值就不会有什么混淆不清,如果如果 f.readline()返回一个空字符串,那就表示到达了文件末尾,如果是一个空行,就会描述为'/n′ ,一个只包含换行符的字符串。

f.readline()
'This is the first line of the file./n'
f.readline()
'Second line of the file/n'
f.readline()
''

f.write(string) 将 string 的内容写入文件,返回 None 。

f.write('This is a test/n')

如果需要写入字符串以外的数据,就要先把这些数据转换为字符串。

value = ('the answer', 42)
s = str(value)
f.write(s)

  • f.tell()返回一个整数,代表文件对象在文件中的指针位置,该数值计量了自文件开头到指针处的比特数。
  • 需要改变文件对象指针话话,使用f.seek(offset,from_what) 。指针在该操作中从指定的引用位置移动offset 比特,引用位置由 fromwhat 参数指定。 fromwhat值为0表示自文件起初处开始,1表示自当前文件指针位置开始,2表示自文件末尾开始。 from_what 可以忽略,其默认值为零,此时从文件头开始。

f = open('/tmp/workfile', 'r+')
f.write('0123456789abcdef')
f.seek(5) # Go to the 6th byte in the file
f.read(1)
'5'
f.seek(-3, 2) # Go to the 3rd byte before the end
f.read(1)
'd'

文件使用完后,调用 f.close()可以关闭文件,释放打开文件后占用的系统资源。调用 f.close()之后,再调用文件对象会自动引发错误。

pickle 模块 如果你有一个对象 x ,一个以写模式打开的文件对象 f,封装对像的最简单的方法只需要一行代码:

pickle.dump(x, f)

如果 f是一个以读模式打开的文件对象,就可以重装拆封这个对象: x = pickle.load(f)

最简单的类定义形式如下:

class ClassName:
<statement-1>
.
.
.
<statement-N>

类可能会定义一个名为 __init__() 的特殊方法,像下面这样: >def init(self):
self.data = []

用来初始化类,相当于构造器

同名的数据属性会覆盖方法属性,为了避免可能的命名冲突--这在大型程序中可能会导致难以发现的 bug --最好以某种命名约定来避免冲突。

可选的约定包括方法的首字母大写,数据属性名前缀小写(可能只是一个下划线),或者方法使用动词而数据属性使用名词。

数据属性可以由方法引用,也可以由普通用户(客户)调用。换句话说,类不能实现纯的数据类型。事实上 Python 中没有什么办法可以强制隐藏数据--一切都基本约定的惯例。(另一方法讲,Python 的实现是用 C 写成的,如果有必要,可以用 C 来编写 Python 扩展,完全隐藏实现的细节,控制对象的访问。)

客户应该小心使用数据属性--客户可能会因为随意修改数据属性而破坏了本来由方法维护的数据一致性。需要注意的是,客户只要注意避免命名冲突,就可以随意向实例中添加数据属性而不会影响方法的有效性--再次强调,命名约定可以省去很多麻烦。

从方法内部引用数据属性(以及其它方法!)没有什么快捷的方式。我认为这事实上增加了方法的可读性:即使粗略的浏览一个方法,也不会有混淆局部变量和实例变量的机会。

习惯上,方法的第一个参数命名为 self 。这仅仅是一个约定:对 Python 而言,self 绝对没有任何特殊含义。(然而要注意的是,如果不遵守这个约定,别的 Python 程序员阅读你的代码时会有不便,而且有些类浏览程序也是遵循此约定开发的。)

通过 self 参数的方法属性,方法可以调用其它的方法:

class Bag:
def init(self):
self.data = []
def add(self, x):
self.data.append(x)
def addtwice(self, x):
self.add(x)
self.add(x)

派生类的定义如下所示:

class DerivedClassName(Base1,Base2, Base3):
<statement-1>
.
.
.
<statement-N>

这里唯一需要解释的语义是解析类属性的规则。顺序是深度优先,从左到右。

因此,如果在 DerivedClassName (示例中的派生类)中没有找到某个属性,就会搜索 Base1 ,然后(递归的)搜索其基类,如果最终没有找到,就搜索 Base2,以此类推。

原创粉丝点击