Python的list、tuple和str是基于数组的序列,list和tuple是存放的对象的引用,str存放的是实际值(an array of characters (not an array of references)),字符在内存中是连续存储的。list、tuple和str都可以通过索引和切片进行操作。模块array可以用于创建存放值的数组,有一个限制是ctype的,不支持自定义的类型。操作方式如:primes = array( 'i' , [2, 3, 5, 7, 11, 13, 17, 19])。
字符串类型在使用时的一个常见的低效的使用方式和优化后的写法。低效的原因是没增加一个 字符就要先生成一个新的字符串实例,然后再连接。改进后的写法先放到列表( list)里,然后再 jion。
# 低效的代码片段
# WARNING: do not do this
letters = '' # start with empty string
for c in document:
if c.isalpha( ):
letters += c # concatenate alphabetic character
# 好的写法
temp = [ ] # start with empty list
for c in document:
if c.isalpha( ): # append alphabetic character
temp.append(c)
letters = ''.join(temp) # compose overall result
#更简洁的写法
letters = ''.join([c for c in document if c.isalpha( )])
letters = ''.join(c for c in document if c.isalpha( ))
import ctypes
class DynamicArray:
""" A dynamic array class akin to a simplified Python list."""
def __init__(self):
""" Create an empty array."""
self._n = 0 #count actual elements
self._capacity = 1 #default array capacity
self._A = self._make_array(self._capacity) #low-level array
def __len__(self):
"""Return number of elements stored in the array."""
return self._n
def __getitem__(self,k):
"""Return element at index k."""
if not 0 <= k < self._n:
raise IndexError('invalid index')
return self._A[k] #retrieve from array
def append(self, obj):
"""Add object to end of the array."""
if self._n == self._capacity: # not enough room
self._resize(2*self._capacity) #so double capacity
self._A[self._n] = obj
self._n += 1
def _resize(self, c): # nonpublic utitity
"""Resize internal array to capacity c."""
B = self._make_array(c) # new (bigger) array
for k in range(self._n): # for each existing value
B[k] = self._A[k]
self._A = B
self._capacity = c
def _make_array(self, c): # nonpublic utitity
"""Return new array with capacity c."""
return (c * ctypes.py_object)() # see ctypes documentation
if __name__ == '__main__':
da = DynamicArray()
da.append(6)
da.append(2)
for o in da:
print o
书上的两个例子。
列表应用一,应用列表(list)实现一个游戏得分的排行榜。类GameEntry记录姓名和得分,类ScoreBoard实现排行榜,它要保证添加新得分时要保证得分是按照顺序排列的,如果空间不够,就要把最后一名挤出去。
class GameEntry:
"""Represents one entry of a list of high scores."""
def __init__(self, name, score):
self._name = name
self._score = score
def get_name(self):
return self_score
def __str__(self):
return '({0}, {1})'.format(self._name, self._score)
class Scoreboard:
"""Fixed-length sequence of high scores in nondecreasing order."""
def __init__(self, capacity=10):
"""Initialize scoreboard with given maximum capacity.
All entries are initially None.
"""
self._board = [None]*capacity #reserve space for future scores
self._n = 0
def __getitem__(self, k):
"""Return entry at index k."""
return self._board[k]
def __str__(self):
"""Return string representation of the high score list."""
return '\n'.join(str(self._board[j]) for j in range(self._n))
def add(self,entry):
"""Consider adding entry to high scores."""
score = entry.get_score()
# Does new entry qualify as a high score?
# answer is yes if board not full or score is higher than last entry
good = self._n < len(self._board) or score > self._board[-1].get_score()
if good:
if self._n < len(self._board): #no score drops form list
self._n += 1 #so overall number increases
# shift lower socres rightward to make room for new entry
j = self._n - 1
while j > 0 and self._board[j-1].get_score() < score:
self._board[j] = self._board[j-1] #shift entry from j-1 to j
j -= 1 #and decrement j
self._board[j] = entry #when done, and new entry
def insertion_sort(A):
"""Sort list of comparable elements into nondecreading order."""
for k in range(1, len(A)): # from 1 to n-1
cur = A[k] # current element to be inserted
j = k # find correct index j for current
while j > 0 and A[j-1] > cur: # element A[j-1] must be after current
A[j] = A[j-1]
j -= 1
A[j] = cur # cur is now in the right place
列表应用二,凯撒密码加密。
class CaesarCipher:
""" Class for doing encryption and decryption using a Caesar cipher. """
def __init__(self, shift):
"""Construct Caesar cipher using given integer shift for rotation."""
encoder = [None] * 26 #temp array for encryption
decoder = [None] * 26 #temp array for decryption
for k in range(26):
encoder[k] = chr((k + shift) % 26 + ord('A'))
decoder[k] = chr((k - shift) % 26 + ord('A'))
self._forward = ''.join(encoder) #will store as string
self._backward = ''.join(decoder) #since fixed
def encrypt(self, message):
"""Return string representing encripted message."""
return self._transform(message, self._forward)
def decrypt(self, secret):
"""Return decrypted message given encrypted secret."""
return self._transform(secret, self._backward)
def _transform(self, original, code):
"""Utility to perform transformation based on given code string."""
msg = list(original)
for k in range(len(msg)):
if msg[k].isupper():
j = ord(msg[k]) - ord('A') # index from 0 to 25
msg[k] = code[j] # replace this character
return ''.join(msg)
if __name__ == '__main__':
cipher = CaesarCipher(3)
message = "THE EAGLE IS IN PLAY; MEET AS JOE'S."
coded = cipher.encrypt(message)
print('Secret: ', coded)
answer = cipher.decrypt(coded)
print('Message: ', answer)
在python中二维数组表示为列表中的列表。但是要注意的是初始化时如不小心会犯错。
错误的初始化
In [1]: data = ([0]*2)*3
In [2]: print data
[0, 0, 0, 0, 0, 0]
In [3]: data = [[0]*2]*3
In [4]: data[0][1]=1
In [5]: print data
[[0, 1], [0, 1], [0, 1]]
正确的初始化
In [12]: data = [[0]*2 for j in range(3)]
In [13]: data
Out[13]: [[0, 0], [0, 0], [0, 0]]
In [14]: data[0][1]=1
In [15]: data
Out[15]: [[0, 1], [0, 0], [0, 0]]
二维数组可以用来表示平面上的位置,书上举了一个Tic-Tac-Toe游戏例子。_board是一个3×3的二维数组,记录每个位置放的是'X'、'O'或' '(无棋子); mark表示往[i][j]这个位置上放棋子(做标记), 放棋子时会进行校验;_is_win判断输赢,返回None表示未结束,还可以下。
class TicTacToe:
"""Management of a Tic-Tac-Toe game(does not do strategy)."""
def __init__(self):
"""Start a new game."""
self._board = [[' ']*3 for j in range(3)]
self._player = 'x'
def mark(self, i, j):
"""Put an X or O mark at position (i,j) for next player's turn."""
if not (0 <= i <= 2 and 0 <= j <= 2):
raise ValueError('Invalid board position')
if self._board[i][j] != ' ' :
raise ValueError('Board position occupied')
if self.winner() is not None:
raise ValueError('Game is already complete')
self._board[i][j] = self._player
if self._player == 'X':
self._player = 'O'
else:
self._player = 'X'
def _is_win(self, mark):
"""Check whether the board configuration is a win for the given player."""
board = self._board #local variable for shorthand
return (mark == board[0][0] == board[0][1] == board[0][2] or #row 0
mark == board[1][0] == board[1][1] == board[1][2] or #row 1
mark == board[2][0] == board[2][1] == board[2][2] or #row 2
mark == board[0][0] == board[1][0] == board[2][1] or #column 0
mark == board[0][0] == board[1][1] == board[2][2] or #column 1
mark == board[0][1] == board[1][2] == board[2][2] or #column 2
mark == board[0][0] == board[1][1] == board[2][2] or #diagonal
mark == board[0][2] == board[1][1] == board[2][0] ) #rev diag)
def winner(self):
"""Return mark of winning player, or None to indicate a tie."""
for mark in 'XO':
if self._is_win(mark):
return mark
return None
def __str__(self):
"""Return string representation of current game board."""
rows = ['|'.join(self._board[r]) for r in range(3)]
return '\n-----\n'.join(rows)