博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python Revisited Day 03 (组合数据类型)
阅读量:5351 次
发布时间:2019-06-15

本文共 14986 字,大约阅读时间需要 49 分钟。

文章目录

**

第三章 组合数据类型

**

3.1 序列类型

3.1.1 元组

元组和字符串类似,是固定的,不能替换或者删改包含的任意项

(1, 2, 3) + (1, 2, 3) #(1, 2, 3, 1, 2, 3)(1, 2, 3, 4) * 2 #(1, 2, 3, 4, 1, 2, 3, 4)(1, 2, 3, 4)[:3] #(1, 2, 3)(1, 2, 3, 1, 1, 3).count(1) #3(1, 2, 3, 1, 1, 3).index(3) #2hair = 'black', 'brown', 'blonde', 'red'hair[2]hair[-3:]hair[:2], 'gray', hair[2:] #(('black', 'brown'), 'gray', ('blonde', 'red'))hair[:2] + ('gray',) + hair[2:] #('black', 'brown', 'gray', 'blonde', 'red')#请注意上面一元组的写法,别弄错了things = (1, -7.5, ('pea', (5, 'XyZ'), 'queue'))things[2][1][1][2]  # 'Z'

3.1.2 命名的元组 (collections.nametuple())

collections 模块提供了 namedtuple() 函数,该函数用于创建自定义的元组数据类型。

import collectionsSale = collections.namedtuple('Sale', 'productid customerid data quantity price')sales = []sales.append(Sale(432, 932, '2008-9-14', 3, 7.99))sales.append(Sale(419, 874, '2008-9-15', 1, 18.49))total = 0for sale in sales:	total += sale.quantity * sale.priceprint('Total ${0:.2f}'.format(total)) #Total $42.46

第二个例子:

Aircraft = collections.namedtuple('Aircraft', 								'manufacturer model seating')Seating = collecttions.namedtuple('Seating', 'minimum maximum')aircraft = Aircraft('Airbus', 'A320-200', Seating(100, 220))aircraft.seating.maximum #220print('{0} {1}'.format(aircraft.manufacturer, aircraft.model))print('{0.manufacturer} {0.model}'.format(aircraft))#命名的元组还有几个私有方法,有一个namedtuple._asdict()的方法特别有用print('{manufacturer} {model}'.format(**aircraft._asdict()))#Airbus A320-200

3.1.3 列表 (查询有关函数点这)

列表方法:

L.append(x)

L.count(x)
L.extend(m) | L += m
L.index(x, start, end)
L.insert(i, x) #在索引i的位置上插入x

a = [1, 2, 3]a[1:1] = [4] # == a.insert(1, 4)a # [1, 4, 2, 3]

L.pop() #返回并移除list L最右边的数据项

L.pop(i) # 索引为i的
L.remove(x) #从list中移除最左边出现的数据项x,如果找不到产生ValueError

#a[2:4] = [] | del a[2:4] euqal

L.reverse()

L.sort(…) #排序 接受可选的key和reverse参数

first, *rest = [9, 2, -4, 8, 7]first, *mid, last = 'Charles Philip Arthur George Windsor.'.split()*directories, executable = '/usr/local/bin/gvim'.split('/')#(['', 'usr', 'local', 'bin'], 'gvim')

3.1.4 列表内涵

[expression for item in iterable if condition]

[y for y in range(1900, 1940) if (y % 4 == 0 and y % 100 != 0) or (y % 400 == 0)]#[1904, 1908, 1912, 1916, 1920, 1924, 1928, 1932, 1936][s + z + c for s in 'MF' for z in 'SMLX' for c in 'BGW' if not (s == 'F' and z == 'X')]

第二行代码,和一般的for循环似乎不同,条件的判断似乎必须在循环的最后关头才会进行判断,所以其实for循环的顺序发生颠倒也没有什么关系。

3.2 集合类型

只有可哈希运算的对象可以添加到集合中。

3.2.1 集合(查询有关函数点这)

集合是0个或多个对象引用的无序组合,且排他!

{
1, 1, 2, 3, 4, 5} #{1, 2, 3, 4, 5}

空集合只能用set()来创建, ‘{}’ 用来创建空dict

语法 描述
s.add(x) 将数据项x添加到集合s中——如果s中尚未包含x
s.clear() 移除集合s中的所有数据项
s.copy() 返回集合s的浅拷贝*
s.difference(t) s-t 返回一个新集合, 其中包含在s中但不在集合t中的所有数据项*
s.difference_update(t) s -= t 移除每一个在集合t但不在集合s中的项
s.discard(x) 如果数据项x存在于集合s中,就移除该数据项,参见set.remove()
s.intersection(t) s & t 返回一个新集合,其中包含所有同时包含在集合t与s中的数据项*
s.intersection(t) s &= t 使得集合s包含自身与集合t交集
s.isdisjoint(t) 如果集合s与t没有相同的项, 就返回True*
s.issubset(t) s<=t 如果集合s与集合t相同, 或者是t的子集,就返回True。 使用s<t可以测试s是否是t的真子集*
s.issuperset(t) s >= t 如果集合s与集合t相同,或者是t的超集,就返回True。使用s>t可以测试s是否是t的真子集*
s.pop() 返回并移除集合s中一个随即项,如果s为空集,就产生KeyError异常
s.remove(x) 从集合s中移除数据项x,如果s中不包含x,就产生KeyError异常,参见set.discard()
s.symmetric_difference(t) s^t 返回一个新集合,其中包含s与t中的每个数据项,但不包含同时在这俩个集合中的数据项*
s.symmetric_difference_update(t) s ^= t 使得集合s只包含其自身与集合t的对称差
s.union(t) s | t 返回一个新集合,其中包含集合s中的所有数据项,以及在t中而不在s中的数据项*
s.update(t) s|= t 将集合t中每个s中不包含的数据项添加到集合s中

* 这一方法及其操作符也可用于frozensets

3.2.2 集合内涵

{expression for item in iterable}

{expression for item in iterable if condition}

html = {x for x in files if x.lower().endswith((’.htm’, ‘.html’))}

固定集合(forzeonset)

如果讲二元运算符应用于集合于固定集合,那么产生结果的数据类型与左边操作数的数据类型一致。

3.3 映射类型

只有可哈希运算的对象才能作为字典的键。

3.3.1 字典 (查询有关函数点这)

dict() | {}

d1 = dict({
'id': 1948, 'name': 'Washer', 'size': 3})d2 = dict(id = 1948, name = 'Washer', size = 3)d3 = dict([('id', 1948), ('name', 'Washer'), ('size', 3)])d4 = dict(zip(('id', 'name', 'size'), (1948, 'Washer', 3)))d5 = {
'id': 1948, 'name': 'Washer', 'size': 3}#{'id': 1948, 'name': 'Washer', 'size': 3}del d1['id'] #删除'd1'd1.pop('id') #删除'd1'

del : del删除的不是数据,而是删除对象与数据之间的绑定,若数据没有被其他对象引用,则进入垃圾收集流程。

语法 描述
d.clear() 从dict d 中移除所有项
d.copy() 返回dict d的浅拷贝
d.fromkeys(s, v) 返回一个dict,该字典的键为序列s中的项,值为None或v
d.get(k) 返回键k相关联的值,如果k不在dict d中就返回None
d.get(k, v) 返回键k相关联的值,如果k不在dict d中就返回v
d.items() 返回dict d 中所有(key, value)对的视图
d.keys() 返回dict d 中所有键的视图
d.pop(k) 返回键k相关联的值,并移除键为k的项,如果k不包含在d中,就产生KeyError异常
d.popitem() 返回并移除dict d 中任意一个(key, value)对,如果d为空就产生KeyError异常
d.setdefault(k, v) 与dict.get()方法一样,不同之处在于,如果k没有包含在dict d中就插入一个键为k的新项,其值为None或v
d.update(a) 将a中每个尚未包含在dict d中的(key, value) 对添加到d,对同时包含在d与a中的每个键,使用a中对应的值替换d中对应的值——a可以是字典,也可以是(key,value)对的一个iterable,或关键字参数
d.values() 返回dict d中所有值的视图

视图是一个只读的iterable对象

特别的是:如果视图引用的字典发生变化,那么视图将反映该变换;键视图与项视图支持一些类似于集合的操作。
& | - ^

d1 = dict(a = 1, b = 2, c = 3)d2 = dict(x = 1, y = 2, z = 3)for item in d1.items():    print(item)d1['a'] = 7for item in d1.items():    print(item)#('a', 1)#('b', 2)#('c', 3)#('a', 7)#('b', 2)#('c', 3)d1 = dict(a = 1, b = 2, c = 3)d2 = dict(x = 1, y = 2, z = 3)v = d1.items()x = d2.items()for item in v | x:    print(item)#('b', 2)#('y', 2)#('z', 3)#('c', 3)#('x', 1)#('a', 1)
d = {
}.fromkeys('ABCD', 3) #{'A':3, 'B':3, 'C':3, 'D':4}s = set('ACX') # {'A', 'C', 'X'}matches = d.keys() & s # {'A', 'C'}

一个例子(没玩过)

import stringimport syswords = {
}strip = string.whitespace + string.punctuation + string.digits + "\"'"for filename in sys.argv[1:]: #这个是指在命令行输入的东东 for line in open(filename): for word in line.lower().split(): word = word.strip(strip) if len(word) > 2: if words[word] = words.get(word, 0) + 1 for word in sorted(words): print("'{0}' occurs {1} times".format(word, words[word]))

文件的读与写

open(filename, encoding = ‘utf8’) #for reading text

open(filename, ‘w’, encoding = ‘utf8’) #for writing text

惯用方法:

for line in open(filename, encoding = ‘utf8’):
process(line)

readlines()方法将整个文件读入字符串列表

字典内涵

{keyexpression:valueexpression for key, value in iterable}

{keyexpression:valueexpression for key, value in iterable if condtion}

file_sizes = {
name: os.path.getsize(name) for name in os.listdir(".")}file_sizes = {
name: os.path.getsize(name) for name in os.listdir(".") if os.path.isfile(name)}

inverted_d = {v: k for k, v in d.items()}#用于反转字典,但是对值有要求

3.3.3 默认字典

解释不清楚

import collectionswords = collections.defaultdict(int)

3.3.4 有序字典

d = collections.OrderedDict([('z',-4), ('e', 19), ('k', 7)])

注意,如果括号里面传入的无序的dict,或关键字参数,那么顺序将是任意的(我在没看出来任意来)。

3.4 组合数据类型的迭代与复制

3.4.1 迭代子、迭代操作与函数 (查询有关迭代子的函数点这)

语法 描述
s + t 返回一个序列,该序列是序列s与t的连接
s * n 返回一个序列,该序列是序列s的n个副本的连接
x in i 如果项x出现在iterable i 中,就返回True,not in 进行的测试则相反
all(i) 如果iterable i 中的每一项都被评估为True,就返回True
any(i) 如果iterable i中的任意项都被评估为True,就返回True
enumerate(i, start) 通常用于for … in 循环中,提供一个(index, item)元组序列,其中的索引起始值为0或start
len(x) 返回x的“长度”,如果x是组合数据类型,那么返回的是其中数据项数;如果x是一个字符串,那么返回的是其中包含的字符数
max(i,key) 返回iterable i 中的最大的项,如果给定的是key函数,就返回key值最大的项
min(i, key)
range(start, stop, step) 返回一个整数迭代子。使用一个参数(stop)时,迭代子的取值范围从0到stop-1;使用参数(start,stop)时,迭代子取值范围从start到stop-1;3个参数全部使用时,迭代范围从start到stop-1,但每俩个值之间间隔step
reversed(i) 返回一个迭代子,该迭代子以反序从迭代子i中返回项#dict 不行 有序字典倒是可以
sorted(i, key, reverse) 以排序后顺序从迭代子i返回项,key用于提供DSU(修饰、排序、反修饰)排序,如果reverse为True,则排序以反序进行
sum(i,start) 返回iterable i 中项的和,加上start(默认为0),i 可以包含字符串
zip(i1, … ,iN 返回元组的迭代子,使用迭代子i1到iN
x = [-2, 9, 7, -4, 3]all(x), any(x), len(x), min(x), max(x), sum(x)#(True, True, 5, -4, 9, 13)

iter() and next()

iter() 将返回一个用于传递给函数的对象的迭代子,如果该对象无法进行迭代,则产生一个TypeError (还有另外一种用法,关于参数和哨点值,另外再说吧(P114)).

next()会依次返回每个相继的数据项,直到没有数据项时产生StopIteration异常。

product = 1for i in [1, 2, 3, 4]:	product *= iprint(product)

与下面的是一样的:

product = 1i = iter([1, 2, 3, 4])while True:	try:		product *= next(i)	except StopIteration:		breakprint(product)

实例:程序读入一个forename文件与一个surname文件,创建俩个列表,之后创建test-names1.txt并向其中写入100个随机的名称

import randomdef get_fornames_and_surnames():	forenames = []	surnames = []	for names, filename in ((fornames, 'data/forenames.txt'),							(surnames, 'data/surnames.txt')):		for name in open(filename, encoding='utf8'):			names.append(name.rstrip()) #删除字符串末尾指定字符(默认为空格)	return forenames, surnamesforenames, surnames = get_fornames_and_surnames()fh = open('test-names.txt', 'w', encoding='utf8')for i in range(100):	line = "{0} {1}\n".format(random.choice(forenames), 							random.choice(surnames))	fh.write(line)fh.close()

zip()

zip()会返回一个迭代子,每个元素是一个元组。

for t in zip(range(4), range(0, 10, 2), range(1, 10, 2)):	print(t)#(0, 0, 1)#(1, 2, 3)#(2, 4, 5)#(3, 6, 7)#注意,即便传入的迭代子长度不一致,依然可以使用,取小。for i in zip([1, 2], [1, 2, 3]):    print(i)#(1, 1)# (2, 2)

sorted() and reversed()

list(range(6)) #[0, 1, 2, 3, 4, 5]list(reversed(range(6))) #[5, 4, 3, 2, 1, 0]
x = []for t in zip(range(-10, 0, 1), range(0, 10, 2), range(1, 10, 2)):    x += tx#[-10, 0, 1, -9, 2, 3, -8, 4, 5, -7, 6, 7, -6, 8, 9]sorted(x)#[-10, -9, -8, -7, -6, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]sorted(x, reverse = True)#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -6, -7, -8, -9, -10]sorted(x, key = abs)#[0, 1, 2, 3, 4, 5, 6, -6, -7, 7, -8, 8, -9, 9, -10]

#key关键字传入函数或方法,相当于先将x中的元素“修饰”,再对“修饰”后的元素加以排列得到一个序,最后的结果是x以这个序进行排列。

x = list(zip((1, 3, 1, 3), ('pram', 'dorie', 'kayak', 'canoe')))print(x)print(sorted(x))def swap(t):    return t[1], t[0]print(sorted(x, key=swap))#[(1, 'pram'), (3, 'dorie'), (1, 'kayak'), (3, 'canoe')]#[(1, 'kayak'), (1, 'pram'), (3, 'canoe'), (3, 'dorie')]#[(3, 'canoe'), (3, 'dorie'), (1, 'kayak'), (1, 'pram')]

注意:sorted()只适用于可以进行相互比较的组合类型

sorted([1, '1')]  #TypeError

不过,对于上面这种情况,有一个处理方法: key = int/float,当然这也只是对字符串为“数字”的特殊情形。

3.4.2 组合类型的复制

浅拷贝

a = [1, '2', 3]b = aa[1] = 'two'a, b #([1, 'two', 3], [1, 'two', 3])a = [1, ['2', 5], 3]b = a[:]a[0] = 2b[1][0] = 'two'a, b #([2, ['two', 5], 3], [1, ['two', 5], 3])

普通的 a=b,只是使用了对象引用,a, b指向了同一个内存对象

.copy()

dict()
list()
set()
a[:]
这些都会返回一个浅拷贝

深拷贝

a = [1, ['2', 5], 3]b = copy.deepcopy(a)a[0] = 2b[1][0] = 'two'a, b #([2, ['2', 5], 3], [1, ['two', 5], 3])

实例

生成用户名

import collectionsimport stringimport sys#在python中全大写的变量一般为常量,这是个约定ID = 0FORENAME = 1MIDDLENAME = 2SURNAME = 3#命名元组 User = collections.namedtuple('User', 'username forename middlename surname id')def Main():    if len(sys.argv) == 1 or sys.argv[1] in ('-h', '-help'):        print('useage: {0} file1 [file2 [... fileN]]'.format(        sys.argv[0]))                sys.exit()    usernames = set()        users = {
} for filename in sys.argv[1:]: for line in open(filename, encoding='utf8'): line = line.rstrip() if line: user = process_line(line, usernames) users[(user.username.lower(), user.forename.lower(), user.id)] = user print_users(users)def process_line(line, usernames): fields = line.split(':') username = generate_username(fields, usernames) user = User(username, fields[FORENAME], fields[MIDDLENAME], fields[SURNAME], fields[ID]) return userdef generate_username(fields, usernames): username = (fields[FORENAME][0] + fields[MIDDLENAME][:1] + fields[SURNAME]).replace('-', '').replace("'", "") username = original_name = username[:8].lower() count = 1 while username in usernames: username = "{0}{1}".format(original_name, count) count += 1 usernames.add(username) return usernamedef print_users(users): namewidth = 32 usernamewidth = 9 print("{0:<{nw}} {1:^6} {2:{uw}}".format( 'Name', 'ID', 'Username', nw = namewidth, uw = usernamewidth)) print("{0:-<{nw}} {0:-<6} {0:-<{uw}}".format( '', nw=namewidth, uw=usernamewidth)) for key in sorted(users): user = users[key] inital = '' if user.middlename: inital = ' ' + user.middlename[0] name = "{0.surname}, {0.forename}{1}".format(user, inital) print("{0:.<{nw}} {1.id:4} {1.username:{uw}}".format( name, user, nw = namewidth, uw = usernamewidth))if __name__ == '__main__': Main()

输入是这样的:

在这里插入图片描述

输出是这样的:

在这里插入图片描述

小惊喜 m[:1]来代替m[0] 防止产生IndexError

s = ''s[0] #报错s[:1]#不会报错s[:k]都不会报错,只是s[:1]在s非空的情况下满足取首项的要求

处理统计信息

import collectionsimport stringimport sysimport mathStatistics = collections.namedtuple('Statistic',    'mean mode median std_dev')def main():    if len(sys.argv) == 1 or sys.argv[1] in {
'-h', '-help'}: print('usage: {0} file1 [file2 [... fileN]'.format( sys.argv[0])) sys.exit() numbers = [] frequencies = collections.defaultdict(int) for filename in sys.argv[1:]: read_data(filename, numbers, frequencies) if numbers: statistics = calculate_statistics(numbers, frequencies) print_results(len(numbers), statistics) else: print('no numbers found')def read_data(filename, numbers, frequencies): for lino, line in enumerate(open(filename, encoding='utf8'), start = 1): for x in line.split(): try: number = float(x) numbers.append(number) frequencies[number] += 1 except ValueError as err: print('{filename}:{lino}:skipping {x}:{err}'.format( **locals()))def calculate_statistics(numbers, frequencies): mean = sum(numbers) / len(numbers) mode = calculate_mode(frequencies, 3) median = calculate_median(numbers) std_dev = calculate_std_dev(numbers, mean) return Statistics(mean, mode, median, std_dev)def calculate_mode(frequencies, maximum_modes): highest_frequency = max(frequencies.values()) mode = [number for number, frequency in frequencies.items() if frequency == highest_frequency] if not (1 <= len(mode) <= maximum_modes): mode = None else: mode.sort() return modedef calculate_median(numbers): numbers = sorted(numbers) middle = len(numbers) // 2 median = numbers[middle] if len(numbers) %2 == 0: median = (median + numbers[middle - 1]) / 2 return mediandef calculate_std_dev(numbers, mean): total = 0 for number in numbers: total += (number - mean) **2 variance = total / (len(numbers) - 1) return math.sqrt(variance)def print_results(count, statistics): real = '9.2f' if statistics.mode is None: modeline = '' elif len(statistics.mode) == 1: modeline = 'mode = {0:{fmt}}\n'.format( statistics.mode[0], fmt=real) else: modeline = ("mode = ["+ ",".join(["{0:.2f}".format(m) for m in statistics.mode]) + "]\n") print("""\ count = {0:6} mean = {mean:{fmt}} median = {median:{fmt}} {1}\ std.dev. = {std_dev:{fmt}}""".format( count, modeline, fmt=real, **statistics._asdict()))if __name__ == '__main__': main()

在这里插入图片描述

在这里插入图片描述

小惊喜 print 三引号

上面的例子中出现了三引号,三引号使得程序以我们所可理解的方式展示文本(大概就是不用加\n之类的)。

print("""aaaaaddddd""")

aaaaa

ddddd

print("""aaaaa \ddddd""")

aaaaa ddddd

注意这个时候 \ 可以起到把空行转义掉,回到原来的形状。

print("""aaaaa\n\ddddd""")

aaaaa

ddddd

转载于:https://www.cnblogs.com/MTandHJ/p/10526761.html

你可能感兴趣的文章
较快的maven的settings.xml文件
查看>>
随手练——HDU 5015 矩阵快速幂
查看>>
malloc() & free()
查看>>
Java变量类型,实例变量 与局部变量 静态变量
查看>>
mysql操作命令梳理(4)-中文乱码问题
查看>>
Python环境搭建(安装、验证与卸载)
查看>>
一个.NET通用JSON解析/构建类的实现(c#)
查看>>
关于这次软件以及pda终端的培训
查看>>
如何辨别一个程序员的水平高低?是靠发量吗?
查看>>
新手村之循环!循环!循环!
查看>>
线程安全问题
查看>>
linux的子进程调用exec( )系列函数
查看>>
MySQLdb & pymsql
查看>>
zju 2744 回文字符 hdu 1544
查看>>
【luogu P2298 Mzc和男家丁的游戏】 题解
查看>>
前端笔记-bom
查看>>
上海淮海中路上苹果旗舰店门口欲砸一台IMAC电脑维权
查看>>
Google透露Android Market恶意程序扫描服务
查看>>
给mysql数据库字段值拼接前缀或后缀。 concat()函数
查看>>
迷宫问题
查看>>