python核心编程--第六章

本文深入讲解Python中的序列操作,包括字符串、列表和元组的基本概念、常用操作符及内建函数。并提供了丰富的代码示例,帮助读者理解序列类型的特性和应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

开始学习python最关键的一章:序列:字符串,列表和元祖可怜

6.1 序列

6.1.2 序列类型操作符

1) 成员关系操作符(in, not in)

成员关系操作符使用来判断一个元素是否属于一个序列的。比如对字符串类型来说,就是判断一个字符是否属于这个字符串,对元祖类型来说,就代表了一个对象是否属于该对象序列。in/not in操作符的返回值一般来讲就是True/False,满足成员关系就返回True,否则返回False。

seq[ind] 获得下标为Ind的元素

seq[ind1:ind2] 获得下标从ind1到ind2间的元素集合

seq * expr 序列重复expr次

seq1 + seq2 连接序列seq1和seq2

obj in seq 判断obj元素是否包含在seq中

obj not in seq 判断obj元素是否不包含在seq中


如果我们顺序显示一个字符串,然后最后一个字符切掉,代码如下,这里用到了一个小技巧:None

>>> s = "abcde"
>>> for i in [None] + range(-1, -len(s), -1):
	print s[:i]

	
abcde
abcd
abc
ab
a
>>> [None] + range(-1, -len(s), -1)
[None, -1, -2, -3, -4]

6.1.3 内建函数

类型转换

list(iter) 把可迭代对象转换为列表

str(obj) 把obj对象转换为字符串

tuple(iter) 把一个可迭代对象转换成一个元祖对象


为什么python里面不简单把一个对象转换成另一个对象呢?因为一旦一个python的对象被建立,我们就不能更改其身份或类型。如果你把一个列表对象传给list()函数,便会创建这个对象的一个浅拷贝,然后将其插入新的列表中,在做连接操作和重复操作时也一样。

所谓浅拷贝就是只拷贝了对对象的索引,而不是重新建立了一个对象!如果你想完全的拷贝一个对象,你需要用到深拷贝。

一些内建函数:

enumerate(iter) 接受一个可迭代对象作为参数,返回一个enumerate对象(同时也是一个迭代器),该对象生成由iter每个元素的index值和item值组成的元祖。

len(seq) 返回seq的长度

max(iter, key = None) or

max(arg0, arg1, ..., key = None) 返回iter或(arg0, arg1...)中的最大值,如果指定了key,这个key必须是一个可以传给sort()方法的,用于比较多回调函数

min(iter, key = None) or

min(arg0, arg1, ..., key = None) 返回iter或(arg0, arg1...)中的最小值,如果指定了key,这个key必须是一个可以传给sort()方法的,用于比较多回调函数

reversed(seq) 接受一个序列作为参数,返回一个以逆序访问的迭代器

sorted(iter,func = None, key = None, reverse = False) 接受一个可迭代对象作为参数,返回一个有序的列表

sum(seq, init = 0) 返回seq和可选参数init的总和。

zip([it0, it1, it2...]) 返回一个列表,其第一个元素是it0, it1,...这些元素的第一个元素组成的一个元祖,第二个。。。,类推

代码如下:

>>> num = enumerate([1,2,3,4,6,5])
>>> dict(num)
{0: 1, 1: 2, 2: 3, 3: 4, 4: 6, 5: 5}
>>> num = [1,2,3,4,5]
>>> list(reversed(num))
[5, 4, 3, 2, 1]
>>> zip([1,2,3,4,5])
[(1,), (2,), (3,), (4,), (5,)]


6.2 字符串

如果我们要判断数字,字母,则需要以下信息:

>>> import string
>>> string.ascii_uppercase
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.ascii_lowercase
'abcdefghijklmnopqrstuvwxyz'
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.digits
'0123456789'

八进制和十六进制的输出:
>>> "%o" % 108
'154'
>>> "%#o" % 108
'0154'
>>> "%x" % 108
'6c'
>>> "%#x" % 108
'0x6c'
#的作用是:八进制显示0,而十六进制显示0x


6.4.2 字符串模板:更简单的替代品

Template对象有两个方法,substitute()和safe_substitute()。前者更为严谨,在key缺少的情况下它会报一个keyError的异常,而后者在缺少key时,直接原封不动的把字符串显示出来。

>>> from string import Template
>>> s = Template("there are ${howmany} ${lang} quotation symbols")
>>> print s.substitute(lang = "python", howmany = 3)
there are 3 python quotation symbols
>>> print s.substitute(lang = "python")

Traceback (most recent call last):
  File "<pyshell#43>", line 1, in <module>
    print s.substitute(lang = "python")
  File "C:\Python27\lib\string.py", line 172, in substitute
    return self.pattern.sub(convert, self.template)
  File "C:\Python27\lib\string.py", line 162, in convert
    val = mapping[named]
KeyError: 'howmany'
>>> print s.safe_substitute(lang = "python")
there are ${howmany} python quotation symbols

6.6 字符串内建函数

string.capitalize() 把字符串的第一个字符大写

string.center(width) 返回一个原字符串居中,并使用空格填充至长度width的新字符串

string.count(str, beg = 0, end = len(string)) 返回str在string里面出现的次数,如果beg或者end指定则返回指定范围内str出现的次数

string.endswith(obj, beg = 0, end = len(string))检查字符串是否以obj结束,如果beg或者end指定则检查指定的范围内是否以obj结束,是返回True,否则返回False

string.find(str, beg = 0, end = len(string)) 检查str是否包含在string中,如果beg和end指定范围,则检查是否包含在范围内,如果是返回开始的索引值,否则返回-1

string.index(str, beg = 0, end = len(string)) 跟find方法一样,只不过如果str不在string中会报一个异常

string.isalnum() 如果string至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False

string.isalpha() 如果string至少有一个字符并且所有字符都是字母则返回True,否则返回False

string.isdigit() 如果string只包含数字则返回True,否则返回False

string.islower() 如果string中包含至少一个区分大小写的字符,并且所有这些字符都是小写,则返回True,否则返回False

string.isnumeric() 如果string中只包含数字字符,则返回True,否则返回False

string.isspace() 如果string中只包含空格,则返回True,否则返回False

类似isupper,join,lower,

太多了,不写了。


现在貌似对unicode不太感兴趣,故没细看关于unicode的一切知识。

整个人看的有点烦躁其实!!


静下心来看书吧。看书不可烦躁,如果你没有比别人聪明,那么请比别人勤奋。(PS:天气好闷,浑身难受)

6.10 字符串关键点总结

不可分字符类型

字符串是唯一的字面上的字符序列类型。不过,字符本身并不是一种类型,所以,字符串是字符存储操作的最基本单位。字符应该视为长度为1的字符串。


字符串格式化操作符(%)提供类似于printf()那样的功能

三引号

在三引号字符串中可以包含诸如换行回车或者tab这样特殊的字符。


原始字符串(r)对每个特殊字符串都是用它的原意


python字符串不是通过NUL或者‘\0’来结束的


6.11 列表

如何更新列表:

通过赋值或者append函数来完成


如何删除列表中的元素或者列表:

可以用del或者remove()方法

>>> aList = [123,"abc","float replacer",["inner","list"],(7-9j)]
>>> del aList[1]
>>> aList
[123, 'float replacer', ['inner', 'list'], (7-9j)]
>>> aList.remove(123)
>>> aList
['float replacer', ['inner', 'list'], (7-9j)]
一般来说,程序员不需要去删除一个列表对象。列表对象出了作用域后它会自动被析构,但是如果你想明确的删除一整个列表,你可以用del语句。

del aList

6.12 操作符

切片--貌似没什么好说的

成员关系操作(in, not in)---貌似也没什么好说的

连接操作符(+):

连接操作符允许我们把多个列表对象合并在一起。注意,列表类型的连接操作也只能在同类型之间进行,我们不能把两个不同的类型的对象连接在一起,即便他们都是序列类型也不行。但是目前可以用extend()方法来代替连接操作符。

>>> num1 = [1,2,3,4,5]
>>> strLst = ["hello", "world"]
>>> num1 + strLst
[1, 2, 3, 4, 5, 'hello', 'world']
>>> num1.extend(strLst)
>>> num1
[1, 2, 3, 4, 5, 'hello', 'world']
>>> num1 + 5

Traceback (most recent call last):
  File "<pyshell#13>", line 1, in <module>
    num1 + 5
TypeError: can only concatenate list (not "int") to list
>>> num1.append(5)
>>> num1
[1, 2, 3, 4, 5, 'hello', 'world', 5]
append操作在添加元素方面起着至关重要的作用。

重复操作符:貌似也没什么好说的。

列表推导式:(很帅,但是相比于LISP中的map等,就感觉没多少技术含量了。)

>>> [i * 2 for i in [8, -2, 5]]
[16, -4, 10]
>>> [i for i in range(8) if i % 2 == 0]
[0, 2, 4, 6]


6.13 内建函数

cmp():比较函数

>>> list1, list2 = [123, "xyz"], [456, "abc"]
>>> cmp(list1, list2)
-1
>>> cmp(list2, list1)
1
>>> list3 = list2 + [789]
>>> list3
[456, 'abc', 789]
>>> cmp(list2, list3)
-1

序列类型函数:

len(), max(), min()----貌似没什么好讲的

sorted()和reversed()

>>> s = ["they","stamp","them","when","thre're","small"]
>>> for t in reversed(s):
	print t,

	
small thre're when them stamp they
>>> sorted(s)
['small', 'stamp', 'them', 'they', "thre're", 'when']
enumerate()和zip()
>>> albums = ["tales","robot","pyramid"]
>>> for i, album in enumerate(albums):
	print i, album

	
0 tales
1 robot
2 pyramid
>>> fn = ["ian","stuart","david"]
>>> ln = ["bairnson","elliott","paton"]
>>> for i, j in zip(fn, ln):
	print ("%s %s" % (i, j)).title()

	
Ian Bairnson
Stuart Elliott
David Paton

sum()
>>> a = [6,4,5]
>>> import operator
>>> reduce(operator.add, a)
15
>>> sum(a)
15
list(), tuple():

列表和元祖的转换


6.14 列表类型的内建函数

>>> dir(list)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

核心笔记:那些可以改变对象值的可变对象方法是没有返回值的!
>>> num = [2,1,3]
>>> num.sort()
>>> num
[1, 2, 3]
如果想要返回值,请调用内建函数sorted(),reversed()
>>> num = [2,1,3]
>>> sorted(num)
[1, 2, 3]

6.15 列表的特殊特性

堆栈

我看书上的代码有点乱,于是决定自己写一下堆栈的列表实现

"""堆栈的实现,简单的入栈,出栈,显示栈的内容"""

class stack(object):
    """pop method: pop element
        push method: push element
        view: show the stack"""
    def __init__(self, stk = []):
        self._stk = stk
    def pop(self):
        if len(self._stk) == 0:
            return "sorry, stack is empty, can not pop"
        else:
            return self._stk.pop()
    def push(self, element):
        self._stk.append(element)
    def view(self):
        return self._stk
if __name__ == "__main__":
    ss = stack()
    ss.push(1)
    ss.push(2)
    ss.push(3)
    print ss.pop()
    ss.push(4)
    print ss.view()
程序输入输出:
>>> 
3
[1, 2, 4]
用类只是为了更好地封装性。


然后是队列的实现:

"""队列的实现,先进先出,有入队,出队,显示队列的操作"""

class queue(object):
    """push method: push the element to queue
       pop method: pop the first in element
       view: show the queue"""
    def __init__(self, lst = []):
        self._lst = lst
    def push(self, element):
        self._lst.append(element)
    def pop(self):
        outelement = self._lst[0]
        self._lst = self._lst[1:]
        return outelement
    def view(self):
        return self._lst

程序输入输出:
>>> q = queue()
>>> q.push(1)
>>> q.push(2)
>>> q.push(3)
>>> q.pop()
1
>>> q.push(4)
>>> q.view()
[2, 3, 4]
>>> q.pop()
2
>>> q.view()
[3, 4]

6.16 元祖

创建一个元祖并给他赋值实际上跟创建一个列表并给它赋值完全一样,除了一点,只有一个元素的元祖需要在元祖分隔符里面加上一个逗号(,)用以防止跟普通的分组操作符混淆。
元祖的操作方法和列表一样,所以讲讲元祖的特性


6.18 元祖的特殊特性

元祖不可变性的一个用途是:元祖可以作为字典的key

另外的用途就是:元祖可以作为一些内建函数的返回值


所有的多对象的,逗号分隔的,没有明确用符号定义的,都是默认的元祖:

>>> "hello", 2, "world"
('hello', 2, 'world')

所有函数返回的多对象(不包括有符号封装的)都是元祖类型。注意,有符号封装的多对象集合其实是返回的一个单一的容器对象

但是推荐用显示的括号代表元祖。


核心笔记: 列表VS元祖

最好使用不可变类型变量的一个情况是,如果你在维护一些敏感的数据,并且需要把这些数据传递给一个并不了解到函数,作为一个只负责一个软件某一部分的工程师,如果你确信你的数据不会被调用的函数篡改,你会觉得安全了许多。

一个需要可变类型参数的例子是,如果你在管理动态数据集合时,你需要先把它们创建出来,逐渐的或者不定期的添加它们,或者有时还要移除一些单个的元素。这是一个必须使用可变类型对象的典型例子。幸运的是,通过内建的list()和tuple()转换函数,你可以非常轻松的在两者之间进行转换。


关于浅拷贝copy和深拷贝的理解:

简单来说,浅拷贝是对同一对象进行操作,但是深拷贝则是对两个对象进行操作。

有以下三种方式进行浅拷贝:1)完全切片操作[:] 2)利用工厂函数,比如list(), dict()等 3)使用copy模块的copy函数

如果要使用深拷贝,调用deepcopy()函数即可。


啊,又到习题了。

其实一直在问自己,为什么一定要把python的基础书籍都看完。有时候不是浪费时间吗?

最后想了想,其实不是!每次看书不是说你学习到了什么,这是一种习惯。

温故而知新,可以为师矣。


6–1. 字符串.string 模块中是否有一种字符串方法或者函数可以帮我鉴定一下一个字符串是否是另一个大字符串的一部分?

我第一个想到的是find函数,不知道可不可以。

>>> str1 = "hello world i love python"
>>> str2 = "python"
>>> if str1.find(str2) != -1:
	print "find it"

	
find it
>>> str3 = "what?"
>>> if str1.find(str3) != -1:
	print "find it"
else:
	print "no in old string"

	
no in old string
用find函数可以达到要求的,而且并不会产生异常,没找到返回-1而已,可进行判断。


6–2. 字符串标识符.修改例6-1 的idcheck.py 脚本,使之可以检测长度为一的标识符,并且可以识别Python 关键字,对后一个要求,你可以使用keyword 模块(特别是keyword.kelist)来帮你.

"""判断输入的字符是否为合法字符串,不可为python关键字"""
import string
import keyword

def idcheck(strCheck):
    stralpha = string.ascii_letters
    strnum = string.digits
    if strCheck in keyword.kwlist or strCheck[0] in strnum:
        return False
    else:
        for i in range(1, len(strCheck)):
            if strCheck[i] not in stralpha + strnum:
                return False
    return True

if __name__ == "__main__":
    while True:
        strCheck = raw_input("please enter the string(-1 to quit):")
        if strCheck == "-1":
            break
        if idcheck(strCheck):
            print "the string is valid"
        else:
            print "the string is invalid"
程序输入输出:
>>> 
please enter the string(-1 to quit):hello
the string is valid
please enter the string(-1 to quit):5hel
the string is invalid
please enter the string(-1 to quit):_34hfoaf
the string is valid
please enter the string(-1 to quit):-1

6–3. 排序
(a) 输入一串数字,从大到小排列之.
(b) 跟a 一样,不过要用字典序从大到小排列之.
def new_sort1(strNum):
    num = []
    num = strNum.split(" ")
    num.sort()
    return num
def new_sort2(strNum):
    num = []
    num = strNum.split(" ")
    return sorted([int(x) for x in num])
    

if __name__ == "__main__":
    strNum = raw_input("please enter the numbers:")
    print "after sorted, the number is:"
    print new_sort1(strNum)
    print new_sort2(strNum)
程序输入输出:
>>> 
please enter the numbers:1 3 23 42 56 7 4 32
after sorted, the number is:
['1', '23', '3', '32', '4', '42', '56', '7']
[1, 3, 4, 7, 23, 32, 42, 56]


6–5. 字符串
(a)更新你在练习2-7 里面的方案,使之可以每次向前向后都显示一个字符串的一个字符.
(b)通过扫描来判断两个字符串是否匹配(不能使用比较操作符或者cmp()内建函数)。附加题:在你的方案里加入大小写区分.
(c)判断一个字符串是否重现(后面跟前面的一致).附加题:在处理除了严格的回文之外,加入对例如控制符号和空格的支持。
(d)接受一个字符,在其后面加一个反向的拷贝,构成一个回文字符串.
a)
def showStr(strTemp):
    try:
        num = []
        length = len(strTemp)
        for i in range(length // 2):
            num.append(strTemp[i])
            num.append(strTemp[length - i - 1])
    except IndexError:
        pass
    finally:
        if length % 2 == 1:
            num.append(strTemp[length // 2])
        return num

if __name__ == "__main__":
    while True:
        strTemp = raw_input("please enter the string(-1 to quit):")
        if strTemp == "-1":
            break
        print "the strange string is:"
        print showStr(strTemp)
程序输入输出:
>>> 
please enter the string(-1 to quit):1234567
the strange string is:
['1', '7', '2', '6', '3', '5', '4']
please enter the string(-1 to quit):abcdefgh
the strange string is:
['a', 'h', 'b', 'g', 'c', 'f', 'd', 'e']
please enter the string(-1 to quit):-1

b)
def isSame(str1, str2):
    if str1 == str2:
        return 0
    elif str1.find(str2) != -1:
        return 1
    elif str2.find(str1) != -1:
        return -1
    else:
        for i in range(min(len(str1), len(str2))):
            if str1[i] > str2[i]:
                return 1
            elif str2[i] > str1[i]:
                return -1
    return 0 #函数的末尾总有返回值是良好的编程习惯,但是这里有点牵强就是了。

if __name__ == "__main__":
    print "two string same to -1 mean to quit:"
    while True:
        str1 = raw_input("please enter string1:")
        str2 = raw_input("please enter string2:")
        if str1 == str2 == "-1":
            break
        print "cmd(str1, str2) is:"
        print isSame(str1, str2)
程序输入输出:
>>> 
two string same to -1 mean to quit:
please enter string1:hfe
please enter string2:rewf
cmd(str1, str2) is:
-1
please enter string1:1
please enter string2:2
cmd(str1, str2) is:
-1
please enter string1:2
please enter string2:1
cmd(str1, str2) is:
1
please enter string1:-1
please enter string2:-1

c)
def fun1(strTemp):
    sameLst = []
    i = 0
    while i  < len(strTemp) - 1:
        if strTemp[i] == strTemp[i + 1]:
            sameLst.append(strTemp[i])
            i += 2
        else:
            i += 1
    newLst = []
    for i in sameLst:
        if i not in newLst:
            newLst.append(i)
    return newLst

if __name__ == "__main__":
    while True:
        str1 = raw_input("please enter the string(-1 to quit):")
        if str1 == "-1":
            break
        print "the result is:"
        print fun1(str1)
程序输入输出:
>>> 
please enter the string(-1 to quit):abbaabbbecdcd
the result is:
['b', 'a']
please enter the string(-1 to quit):abbccdddefefggh
the result is:
['b', 'c', 'd', 'g']
please enter the string(-1 to quit):-1

d)
def sameStr(strTemp):
    lst = list(strTemp)
    lst.extend(lst[::-1])
    return lst
print "".join(sameStr("hello"))
程序输出:
>>> 
helloolleh


6–6. 字符串.创建一个string.strip()的替代函数:接受一个字符串,去掉它前面和后面的空格(如果使用string.*strip()函数那本练习就没有意义了)
原本一直想用正则表达式做的,结果发现写不出来,我去。

还是乖乖的写算法来解决:

def new_strip(strTemp):
    newstr = list(strTemp)
    length = len(newstr)
    i = 0
    while i < length - 1:
        if newstr[i] == " ":
            del newstr[i]   #这里i不能递增,因为del导致后面的元素前移
        else:
            break
    length = len(newstr)
    for i in range(length):
        if newstr[length - i - 1] == " ":
            del newstr[length - i - 1]
        else:
            break
    return "".join(newstr)
print new_strip("    hello  world   ")
程序输出:
>>> 
hello  world

我去,习题6.7的代码居然在后面,看电子书果真有时挺不方便的,不过电子书代码有点乱,果断不看。


6–8. 列表.给出一个整数值,返回代表该值的英文,比如输入89 返回"eight-nine"。附加题:能够返回符合英文语法规则的形式,比如输入“89”返回“eighty-nine”。本练习中的值限定在家0到1,000.

dict1 = {"1":"one","2":"two","3":"three","4":"four","5":"five",
         "6":"six","7":"seven","8":"eight","9":"nine","0":""}
dict2 = {"1":"ten","2":"twenty","3":"thirty","4":"fourty","5":"fifty",
         "6":"sixty","7":"seventy","8":"eighty","9":"ninety","0":""}
dict3 = {"1":"one hundred","2":"two hundred","3":"three hundred","4":"four hundred","5":"five hundred",
         "6":"six hundred","7":"seven hundred","8":"eight hundred","9":"nine hundred","0":""}
dictAll = {1:dict1, 2:dict2, 3:dict3}
def fun1(strNum):
    if int(strNum) > 1000 or int(strNum) < 0:
        return "error number"
    length = len(strNum)
    strTemp = ""
    if length == 4:
        strTemp = "one thousand "
        return strTemp
    for i in range(length):
        strTemp += dictAll[length - i][strNum[i]] + " "
    return strTemp
if __name__ == "__main__":
    while True:
        strNum = raw_input("please enter the num(q to quit):")
        if strNum.lower() == "q":
            break
        print "the num is: %s" % (fun1(strNum))
程序输入输出:
>>> 
please enter the num(q to quit):1000
the num is: one thousand 
please enter the num(q to quit):987
the num is: nine hundred eighty seven 
please enter the num(q to quit):130
the num is: one hundred thirty  
please enter the num(q to quit):103
the num is: one hundred  three 
please enter the num(q to quit):q
用到表格驱动法,则这道题就异常的简单了。


6–9. 转换.为练习5-13 写一个姊妹函数, 接受分钟数, 返回小时数和分钟数. 总时间不变,并且要求小时数尽可能大.

"""minutes to hour:minute"""

def minToHourMin(strMin):
    if int(strMin) >= 60 * 24:
        return "sorry, the minutes is too large"
    hour, minute = divmod(int(strMin), 60)
    return str(hour) + ":" + str(minute)

if __name__ == "__main__":
    while True:
        minutes = raw_input("please enter the minutes(q to quit):")
        if minutes.lower() == "q":
            break
        print "the minutes same to : %s" % (minToHourMin(minutes))
程序输入输出:
>>> 
please enter the minutes(q to quit):123
the minutes same to : 2:3
please enter the minutes(q to quit):345
the minutes same to : 5:45
please enter the minutes(q to quit):456
the minutes same to : 7:36
please enter the minutes(q to quit):987
the minutes same to : 16:27
please enter the minutes(q to quit):9999
the minutes same to : sorry, the minutes is too large
please enter the minutes(q to quit):q


6–10.字符串.写一个函数,返回一个跟输入字符串相似的字符串,要求字符串的大小写反转.比如,输入"Mr.Ed",应该返回"mR.eD"作为输出.
import string
def Tran(strTemp):
    lst = list(strTemp)
    for i in range(len(lst)):
        if lst[i] in string.lowercase:
            lst[i] = lst[i].upper()
        elif lst[i] in string.uppercase:
            lst[i] = lst[i].lower()
    return "".join(lst)

if __name__ == "__main__":
    while True:
        name = raw_input("please enter the string(-1 to quit):")
        if name == "-1":
            break
        print "the new strange string is:%s" % (Tran(name))
程序输入输出:
>>> 
please enter the string(-1 to quit):fdsaJIOFEjifoew..fds
the new strange string is:FDSAjiofeJIFOEW..FDS
please enter the string(-1 to quit):hello WORLD
the new strange string is:HELLO world
please enter the string(-1 to quit):-1

6–11.转换
(a)创建一个从整数到IP 地址的转换程序,如下格式: WWW.XXX.YYY.ZZZ.
(b)更新你的程序,使之可以逆转换.
def tranFromIPToInt(strIP):
    lst = strIP.split(".")
    if len(lst) != 4:
        return "error ip"
    return int(lst[0]) * (256 ** 3) + int(lst[1]) * (256 ** 2) +\
           int(lst[2]) * 256 + int(lst[3])
def tranFromIntToIP(strInt):
    ip1 = 0
    ip2 = 0
    ip3 = 0
    ip4 = 0
    ip1 = int(strInt) / (256 ** 3)
    ip2 = (int(strInt) % (256 ** 3)) / (256 ** 2)
    ip3 = (int(strInt) % (256 ** 2)) / 256
    ip4 = int(strInt) % 256
    return str(ip1) + "." + str(ip2) + "." + str(ip3) + "." + str(ip4)
print tranFromIPToInt("183.62.9.178")
print tranFromIntToIP(tranFromIPToInt("183.62.9.178"))
程序输入输出:
>>> 
3074296242
183.62.9.178

6–12.字符串
(a)创建一个名字为findchr()的函数,函数声明如下:
def findchr(string, char)
findchr()要在字符串string 中查找字符char,找到就返回该值的索引,否则返回-1.不能用
string.*find()或者string.*index()函数和方法
(b)创建另一个叫rfindchr()的函数,查找字符char 最后一次出现的位置.它跟findchr()工作
类似,不过它是从字符串的最后开始向前查找的.
(c)创建第三个函数,名字叫subchr(),声明如下:
def subchr(string, origchar, newchar)
subchr()跟findchr()类似,不同的是,如果找到匹配的字符就用新的字符替换原先字符.返回
修改后的字符串.

简单休息了一下,继续做习题。

希望今晚能把第六章的习题全部做完吧。

def findchr(string, char):
    length = len(string)
    for i in range(length):
        if string[i] == char:
            return i
    return -1
def rfindchr(string, char):
    length = len(string)
    for i in range(length):
        if string[length - i - 1] == char:
            return length - i - 1
    return -1

def subchr(string, origchar, newchar):
    """更智能些,支持字符串的替换"""
    length = len(origchar)
    largeLength = len(string)
    newstring = ""
    i = 0
    while i < largeLength:
        if string[i:i + length] == origchar:
            newstring += newchar
            i += length
        else:
            newstring += string[i]
            i += 1
    return newstring
if __name__ == "__main__":
    print findchr("hello world", "r")
    print findchr("hello world", "m")
    print rfindchr("hello world", "l")
    print rfindchr("hello world", "m")
    print subchr("hello worlld","ll","?")

6.13 atoc的实现
def atoc(strComplex):
    i = 0
    length = len(strComplex)
    while i < length:
        if strComplex[length - i - 2] in ["+","-"]:
            return complex(float(strComplex[0:length - i - 2]), float(strComplex[length - i - 2:length - 1]))
        else:
            i += 1
print atoc("-1.23e+4-5.67j")
程序输出:
>>> 
(-12300-5.67j)


6–14.随机数.设计一个"石头,剪子,布"游戏,有时又叫"Rochambeau",你小时候可能玩过,下面
是规则.你和你的对手,在同一时间做出特定的手势,必须是下面一种手势:石头,剪子,布.胜利者从
下面的规则中产生,这个规则本身是个悖论.
(a) the paper covers the rock,
布包石头.
(b)石头砸剪子,
(c)剪子剪破布.在你的计算机版本中,用户输入她/他的选项,计算机找一个随机选项,然后由你
的程序来决定一个胜利者或者平手.注意:最好的算法是尽量少的使用if 语句.
import random
def Rochambeau(string):
    dict1 = {"stone":"1","shears":"2","cloth":"3"}
    dictAll = {"12":"lose","23":"lose","31":"lose","11":"equal","22":"equal","33":"equal","21":"win","32":"win","13":"win"}
    randomNum = random.randrange(1,4)
    return "you are:%s" % dictAll[dict1[string] + str(randomNum)]

if __name__ == "__main__":
    while True:
        string = raw_input("please enter stone,shears or cloth(q to quit):")
        if string.lower() == "q":
            break
        if (string != "stone") and (string != "shears") and (string != "cloth"):
            print "error input."
            continue
        print Rochambeau(string)
程序输入输出:
>>> 
please enter stone,shears or cloth(q to quit):stone
you are:equal
please enter stone,shears or cloth(q to quit):shears
you are:equal
please enter stone,shears or cloth(q to quit):stone
you are:win
please enter stone,shears or cloth(q to quit):cloth
you are:lose
please enter stone,shears or cloth(q to quit):q
表格驱动法,受益无穷。得找段时间把代码大全好好的研究一遍。


我去,后面的题目,有点难啊。

6–15.转换
(a)给出两个可识别格式的日期,比如 MM/DD/YY 或者 DD/MM/YY 格式,计算出两个日期间的天
数.
(b)给出一个人的生日,计算从此人出生到现在的天数,包括所有的闰月.
(c)还是上面的例子,计算出到此人下次过生日还有多少天.

import datetime
def Birthday(string):
    lst = list(string.split("-"))
    Birth = datetime.date(int(lst[0]), int(lst[1]), int(lst[2]))
    today = datetime.date.today()
    num = []
    num.append(today - Birth)

    new_birth = Birth.replace(year = today.timetuple().tm_year)
    if new_birth < today:
        new_birth = Birth.replace(year = today.tm_year + 1)
    num.append(new_birth - today)
    return num

if __name__ == "__main__":
    birth = raw_input("input your birthday,like 1989-10-12:")
    print "the days is: " , (Birthday(birth)[0])
    print "have ", (Birthday(birth)[1]),"days, you will birthday!"
程序输出:
>>> 
input your birthday,like 1989-10-12:1989-10-12
the days is:  8630 days, 0:00:00
have  136 days, 0:00:00 days, you will birthday!
哈哈,也快生日了,农历生日怎么算就不知道了。


6–16.矩阵.处理矩阵M 和N 的加和乘操作
我一看到这道题,有点傻眼了。先把矩阵表示出来吧。

def Add(lst1, lst2):
    """矩阵的加法"""
    row = len(lst1)
    col = len(lst1[0])
    for i in range(row):
        for j in range(col):
            lst1[i][j] += lst2[i][j]
    return lst1
def MulLst(lst1, lst2):
    """将两个列表进行相乘"""
    length = len(lst1)
    num = 0
    for i in range(length):
        num += lst1[i] * lst2[i]
    return num
def chanLst(lst):
    """将矩阵反转,只为更好的计算矩阵的乘法"""
    row = len(lst)
    col = len(lst[0])
    num = []
    subNum = []
    for i in range(col):
        for j in range(row):
            subNum.append(lst[j][i])
        num.append(subNum)
        subNum = []
    return num
def Mul(lst1, lst2):
    """两个矩阵进行相乘"""
    lst2 = chanLst(lst2)
    num = []
    subNum = []
    row1 = len(lst1)
    row2 = len(lst2)
    for i in range(row1):
        for j in range(row2):
            subNum.append(MulLst(lst1[i] , lst2[j]))
        num.append(subNum)
        subNum = []
    return num

lst1 = [[1,2,3],[4,5,6]]
lst2 = [[1,2],[3,4],[5,6]]
print Mul(lst1, lst2)
程序输出:
>>> 
[[22, 28], [49, 64]]


6–17.方法.实现一个叫myPop()的函数,功能类似于列表的pop()方法,用一个列表作为输入,移除列表的最新一个元素,并返回它.

这个题目本身就有问题,我写了代码如下:

def myPop(lst):
    lst = lst[:-1]
    return lst
>>> item = [1,2,3,4,5]
>>> myPop(item)
[1, 2, 3, 4]
>>> myPop(item)
[1, 2, 3, 4]
这里的问题是:对于函数来说,它根本就无法改变传入的对象,它只会操作起副本。除非你声明一个类,然后把myPop当作一个类的方法,才可以满足。

这个类就不写了,前面写过堆栈和队列的实现方式,方法一样。


习题6.18:

zip返回元祖!!!


6–19.多列输出.有任意项的序列或者其他容器,把它们等距离分列显示.由调用者提供数据和输出格式.例如,如果你传入100 个项并定义3 列输出,按照需要的模式显示这些数据.这种情况下,应该是两列显示33 个项,最后一列显示34 个.你可以让用户来选择水平排序或者垂直排序.
这道题说难也难,说简单也简单。因为之前矩阵计算的时候编写了矩阵的反转,故水平排序可以通过反转来达到垂直排序的目的。

def chanLst(lst):
    """将矩阵反转,只为更好的计算矩阵的乘法"""
    row = len(lst)
    col = len(lst[0])
    num = []
    subNum = []
    for i in range(col):
        for j in range(row):
            subNum.append(lst[j][i])
        num.append(subNum)
        subNum = []
    return num

def show(lst, count, style = True):
    lst.sort()
    length = len(lst)
    num = []
    interval = length / count
    i = 0
    j = 0
    while j < count - 1:
        num.append(lst[i:i + interval])
        i += interval
        j += 1
    num.append(lst[i:length])
    if not style:
        return chanLst(num)
    return num

if __name__ == "__main__":
    num = []
    for i in range(100):
        num.append(i)
    new_num = []
    new_num = show(num, 6)
    print "水平排序"
    for i in new_num:
        print i
    print "垂直排序"
    new_num = show(num, 6, False)
    for i in new_num:
        print i
程序输出:
>>> 
水平排序
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
[64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
垂直排序
[0, 16, 32, 48, 64, 80]
[1, 17, 33, 49, 65, 81]
[2, 18, 34, 50, 66, 82]
[3, 19, 35, 51, 67, 83]
[4, 20, 36, 52, 68, 84]
[5, 21, 37, 53, 69, 85]
[6, 22, 38, 54, 70, 86]
[7, 23, 39, 55, 71, 87]
[8, 24, 40, 56, 72, 88]
[9, 25, 41, 57, 73, 89]
[10, 26, 42, 58, 74, 90]
[11, 27, 43, 59, 75, 91]
[12, 28, 44, 60, 76, 92]
[13, 29, 45, 61, 77, 93]
[14, 30, 46, 62, 78, 94]
[15, 31, 47, 63, 79, 95]
这里垂直排序就出现问题了。因为对于矩阵反转来说,他的每一行都应该是相等的,但是在这里不是,那么怎么改呢?

最后用“×”来补足没出现的字符,在反转函数里面进行修改即可:

def chanLst(lst):
    """将矩阵反转,只为更好的计算矩阵的乘法"""
    row = len(lst)
    col = len(lst[0])
    num = []
    subNum = []
    for i in range(col):
        for j in range(row):
            subNum.append(lst[j][i])
        num.append(subNum)
        subNum = []
    sub = 0
    if row > 2:
        sub = len(num[0]) - (len(lst[row - 1]) - len(lst[row - 2]))
        print sub
    if sub != 0:
        num.append(["*"] * sub + lst[row - 1][col:len(lst[row - 1])])
    return num

def show(lst, count, style = True):
    lst.sort()
    length = len(lst)
    num = []
    interval = length / count
    i = 0
    j = 0
    while j < count - 1:
        num.append(lst[i:i + interval])
        i += interval
        j += 1
    num.append(lst[i:length])
    if not style:
        return chanLst(num)
    return num

if __name__ == "__main__":
    num = []
    for i in range(100):
        num.append(i)
    new_num = []
    new_num = show(num, 6)
    print "水平排序"
    for i in new_num:
        print i
    print "垂直排序"
    new_num = show(num, 6, False)
    for i in new_num:
        print i
程序输出:


>>> 
水平排序
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]
[32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
[48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]
[64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79]
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99]
垂直排序
2
[0, 16, 32, 48, 64, 80]
[1, 17, 33, 49, 65, 81]
[2, 18, 34, 50, 66, 82]
[3, 19, 35, 51, 67, 83]
[4, 20, 36, 52, 68, 84]
[5, 21, 37, 53, 69, 85]
[6, 22, 38, 54, 70, 86]
[7, 23, 39, 55, 71, 87]
[8, 24, 40, 56, 72, 88]
[9, 25, 41, 57, 73, 89]
[10, 26, 42, 58, 74, 90]
[11, 27, 43, 59, 75, 91]
[12, 28, 44, 60, 76, 92]
[13, 29, 45, 61, 77, 93]
[14, 30, 46, 62, 78, 94]
[15, 31, 47, 63, 79, 95]
['*', '*', 96, 97, 98, 99]

不过发现做错了,应该是垂直下来,如果这样更简单,今晚完成(只要增加元素即可。)

修改后的版本如下:

def chanLst(lst):
    """将矩阵反转,只为更好的计算矩阵的乘法"""
    row = len(lst)
    col = len(lst[0])
    num = []
    subNum = []
    for i in range(col):
        for j in range(row):
            subNum.append(lst[j][i])
        num.append(subNum)
        subNum = []
    return num

def show(lst, count, style = True):
    lst.sort()
    length = len(lst)
    num = []
    interval = length / count
    i = 0
    j = 0
    while j < count - 1:
        num.append(lst[i:i + interval])
        i += interval
        j += 1
    num.append(lst[i:length])
    if not style:
        return chanLst(num)
    return num

if __name__ == "__main__":
    num = []
    for i in range(100):
        num.append(i)
    count = 6
    for i in range(count - (len(num) % 6)):
        num.append("*")
    new_num = []
    new_num = show(num, 6)
    print "水平排序"
    for i in new_num:
        print i
    print "垂直排序"
    new_num = show(num, 6, False)
    for i in new_num:
        print i
程序输出:
>>> 
水平排序
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
[17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]
[34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]
[51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67]
[68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84]
[85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, '*', '*']
垂直排序
[0, 17, 34, 51, 68, 85]
[1, 18, 35, 52, 69, 86]
[2, 19, 36, 53, 70, 87]
[3, 20, 37, 54, 71, 88]
[4, 21, 38, 55, 72, 89]
[5, 22, 39, 56, 73, 90]
[6, 23, 40, 57, 74, 91]
[7, 24, 41, 58, 75, 92]
[8, 25, 42, 59, 76, 93]
[9, 26, 43, 60, 77, 94]
[10, 27, 44, 61, 78, 95]
[11, 28, 45, 62, 79, 96]
[12, 29, 46, 63, 80, 97]
[13, 30, 47, 64, 81, 98]
[14, 31, 48, 65, 82, 99]
[15, 32, 49, 66, 83, '*']
[16, 33, 50, 67, 84, '*']

转载于:https://my.oschina.net/voler/blog/138196

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值