第四章:Python容器

概述

什么是容器?

容器是用于盛放元素的
由于盛有许多的元素,容器都是可以迭代遍历的
最常用的容器包括【元组】、【列表】、【字典】、【集合】等
字符串是有序字符集,本质上也是容器
我们在对比和讨论容器的特性时,最常考虑的因素有:
1、是否有序
2、是否可重复
3、如何访问其中的元素
4、是否可以编辑
5、如何遍历

第一节:字符串

字符串操作符

  • +,用于字符串连接
  • *,用于多次重复
    例如:
words = "sun"
words2 = "moon"

print(words + words2)
print(words * 3)

执行结果:
在这里插入图片描述

字符串长度

如果我们想知道一段字符串到底有多长,可以用len()进行查看,而不是一个一个数
例:

#这里有26个字母,或者更多时,使用len()
words = "abcdefghijklmnopqrstuvwxyz"
print(len(words))

#字符串的长度,包含了空格在内
words2 = "I love you"
print(len(words2))

执行结果:
在这里插入图片描述

比较字符串大小

字符串之间的比较,是按当前字符集中序号的顺序排列,前小后大

print("abc" > "def")  # False,按当前字符集中序号的顺序排列
print("中国" > "美帝")  # False,按当前字符集中序号的顺序排列

字符串截取(切片)

字符串[开始位置:结束位置:步长]
开始结束位置的原则是:含头不含尾,即结束位置的那个字符不会被截取
步长2代表每2个取第一个,3代表每三个取第一个
步长为-N时,代表从后向前截取,仍然是每N个取一个

例如:

mstr = "getsomething"

# 从0载取到总长度(最后)
print(mstr[0:len(mstr)])

#从0截取到第5位(注意含头不含尾,所以以6做结束)
print(mstr[0:6])

#从0截取到倒数第4位
print(mstr[0:-3])

#从第5位截取到最后
print(mstr[5:])

#从0截取到第4位
print(mstr[:5])

#从头截到尾
print(mstr[:])

#从0截取到最后,步长为2
print(mstr[0::2])

#从头截到尾,步长为-2
print(mstr[::-2])

执行结果:
在这里插入图片描述

判断有无子串

  • 使用 in 关键字可以判断子串是否在大串中
  • 使用 find 函数返回子串出现的位置,如子串不存在则返回-1
  • 使用 index 函数同样返回子串位置,但子串不存在就会报错
    例如:
mstr = "天下武功唯快不破"

#"武功"是否在mstr里面
print("武功" in mstr)     # True
#"武术"是否在mstr里面
print("武术" in mstr)     # False

#在mstr里寻找"不破"
print(mstr.find("不破"))    # 6
#在mstr里寻找"武术"
print(mstr.find("大破"))    # -1

#在mstr里出现""武功的下标是?
print(mstr.index("武功"))    # 2
print(mstr.index("武术"))    #此方法找不到会报错

字符串的格式化

  • capitalize(),首字母大写
  • title(),每个单词的首字母大写
  • lower(),全小写
  • upper(),全大写
    例如:
mStr = "hello world,hello python"

#字母全大写
print(mStr.upper())
#字母全小写
print(mStr.lower())
#所有单词首字母大写
print(mStr.title())
#仅开头首字母大写
print(mStr.capitalize())

执行结果:
在这里插入图片描述

编码解码

  • encode(),编码为字节
  • decode(),将字节解码为字符串,注意主语是字节而非字符串
    例如:
#例1
words = "太阳当头照,花儿对我笑"

#以gbk字符集编码将字符串编码为字节数组
wordBytes = words.encode(encoding="gbk")
print(wordBytes)

#以gbk字符集编码将字节数组解码为字符串
turnBytes = wordBytes.decode(encoding="gbk")
print(turnBytes)


print("——"*20)#此处只为分隔


例2:
words2 = "早起的鸟儿有虫吃"

#以utf-8字符集编码将字符串编码为字节数组
wordBytes2 = words2.encode(encoding="utf-8")
print(wordBytes2)

#以utf-8字符集编码将字节数组解码为字符串
turnBytes2 = wordBytes2.decode(encoding="utf-8")
print(turnBytes2)

执行结果:
在这里插入图片描述

搜索与替换

  • find(),寻找子串位置,没有返回-1
  • index(),寻找子串位置,没有报错
  • count() ,统计子串出现次数
  • replace(),替换子串为新的字符串
    例如:
mStr = "太阳当头照,花儿对我笑,太阳不见了"

#搜索“花儿”的位置
print(mStr.find("花儿"))

#搜索出现“花儿”的下标
print(mStr.index("花儿"))

#搜索“flower”的位置,-1表示子串不存在
print(mStr.find("flower"))

#搜索出现“flower”的下标位置,注意当子串不存在,将会报错,而不是返-1
# print(mStr.index("flower"))    # ValueError: substring not found

print("——————————————————————————————————")#此处只为分隔

#将“太阳”替换为Sun,替换1处
print(mStr.replace("太阳", "Sun", 1))

#将全部“太阳”替换为“Sun”
print(mStr.replace("太阳", "Sun"))  # fuck world,fuck python 全部hello替换为fuck

print("——————————————————————————————————")#此处只为分隔

#数一数子串“太阳”出现的次数
print(mStr.count("太阳"))

#在0-6位字符中,子串“太阳”出现的次数
print(mStr.count("太阳", 0, 6))  # 1 hello子串出现的次数,范围为0-6位字符

执行结果:
在这里插入图片描述

判断头尾与数字

  • isdigit(),判断是否为数字子串
  • startswith(),判断是否以子串开头
  • endswith(),判断是否以子串结尾
    例如:
words = "太阳当头照,花儿对我笑"
words2 = "3145926"

#判断words是不是数字字符串
print(words.isdigit())            # False
#判断words2是不是数字字符串
print(words2.isdigit())           # True

#判断words是不是以“太阳”子串开头
print(words.startswith("太阳"))    # True
#判断words是不是以“Sun”子串开头
print(words2.startswith("Sun"))   # False

#判断words是不是以“笑”子串结尾
print(words.endswith("笑"))      # True

拆开与重组

  • split(“,”),以逗号切分子串,形成一个列表
  • join(),用分隔符连接子串,主语为分隔符,参数为字符串
    例如:
words = "hello,world,hello,python"
#将字符串words用“,”分割成四个字符串
print(words.split(","))

words2 = "我爱你中国"
#将字符串打散为字符,并以-连接形成新字符串
print("-".join(words2))

执行结果:
在这里插入图片描述

第二节:元组

元组的特点

  • 元组是一种有序不可编辑的元素容器;
  • 可以通过下标访问元组中的元素;
  • 其它迭代器对象(如列表、字符串等)可以通过类型强转转换为元组对象;

创建元组

  • 通过( )直接赋值创建
  • 将多个值赋值给一个变量,则该变量是元组类型
    例:
#直接使用括号可创建元组
mtuple = ()
print(type(mtuple))

#元组可以通过括号直接赋值,值的类型可以多样化(整形、浮点型、字符串、复数等)
mtuple2 = (1, 1.2, True, "hello", 3 + 4j, None)
print(mtuple2)

#将多个值赋值给一个变量,则该变量是元组类型
ytuple = 1, 1.2, True, "hello", 3 + 4j, None
print(ytuple,type(ytuple))

#指定变量个数形成的元组,可直接找到指定变量
ytuple2 = width, height = 300, 400
print(ytuple2,type(ytuple2))
print(width)

执行结果:
在这里插入图片描述

下标访问元素

mtuple = ("dog", "cat", "bird", "fish", "panada", "bear")

# 元组通过使用“[]”和下标进行访问
print(mtuple[2])  # bird
print(mtuple[-1])  # bear

# 遍历元组
for i in mtuple:
    print(i)

元组不可编缉

元组不可以对里面的元素进行修改或删除,但可以删除整个元组

mtuple = ("dog", "cat", "bird", "fish", "panada", "bear")

# mtuple[1] = "apple"
print(mtuple)     # 报错,元组不可编辑

#删除元组
del mtuple
print(mtuple)     # 报错,元组已经不复存在了!NameError: name 'mtup' is not defined

元组的操作

+,连接两个元组为一个大元组
*,将元组元素重复多次
in,判断元组中是否包含某元素
例如:

#两个元组进行相加
print((1, 2, 3) + (4, 5, 6))  # (1, 2, 3, 4, 5, 6)
#元组乘以2
print((1, 2, 3) * 2)  # (1, 2, 3, 1, 2, 3)
#判断2是否在元组中
print(2 in (1, 2, 3))  # True
#判断-2是否在元组中
print(-2 in (1, 2, 3))  # False

截取元组(切片)

截取方式:元组对象[开始位置:结束位置:步长]
开始结束位置的原则是:含头不含尾,即结束位置的那个字符不会被截取
步长2代表每2个取第一个,3代表每三个取第一个
步长为-N时,代表从后向前截取,仍然是每N个取一个

mtuple = ("dog", "cat", "bird", "fish", "panada", "bear")

#截取第3-5位(含头不含尾,所以5要向后一位)
print(mtuple[3:6])   # ('fish', 'panada', 'bear')
#截取第3-倒数第2位
print(mtuple[3:-1])  # ('fish', 'panada')
#截取第3往后的所有
print(mtuple[3:])    # ('fish', 'panada', 'bear')
#截取开头-倒数第3位
print(mtuple[:-2])   # ('dog', 'cat', 'bird', 'fish')
#从头到尾的所有
print(mtuple[:])     # ('dog', 'cat', 'bird', 'fish', 'panada', 'bear')
#从头到尾的所有中,每2取1
print(mtuple[::2])   # ('dog', 'bird', 'panada')
#从头到尾的所有中,每-2取1
print(mtuple[::-2])  # ('bear', 'fish', 'cat')

相关函数

  • len(mtuple),求元组长度
  • max(mtuple),求元组中的最大值
  • min(mtuple),求元组中的最小值
  • tuple(iterable),将其它迭代器对象转换为元组
    例如:
mtuple = (0, 1, 2, 3)

#元素的长度
print(len(mtuple))  # 4
#元素的最大值 
print(max(mtuple))  # 3
#元素的最小值
print(min(mtuple))  # 0
#将列表转换为元组
print(tuple([5, 6, 7, 8]))  # (5, 6, 7, 8) 
#将字符串中的字符打散为元组
print(tuple("hello"))  # ('h', 'e', 'l', 'l', 'o') 

第三节:列表

列表的特点

  • 列表是可编辑的有序可重复的元素集
  • 列表中的元素是可以动态增删修改
  • 列表的元素通过下标进行访问

创建列表

  • 一般创建
  • 推导式创建
    例如:
#普通创建
mlist = []  # 创建了一个空列表,里面没有元素
print(mlist)
ylist = [1, 2.3, "hello", True, 5 + 6j]  # 直接赋初值创建,里面有5个元素,元素类型也是多样的
print(ylist)

# 推导式创建
alist = [c for c in "hello"]
print(alist)
blist = ["$" + c for c in "hello"]
print(blist)
clist = ["$" + c for c in "hello" if c != "e"]
print(clist)

执行结果:
在这里插入图片描述

下标访问元素

mlist =["dog", "cat", "bird", "fish", "panada", "bear"]

#列表的长度
print(len(mlist))  # 6

#通过“[]”和下标访问列表中的元素
print(mlist[1])    # cat

列表的编缉、遍历与删除

删除时注意有两种方法

  • 使用 del ——此方法直接从内存中删除列表,不复存在
  • 使用 clear ——此方法会让列表为空列表
    例如:
mlist = ["dog", "cat", "bird", "fish", "panada", "bear"]

#对列表进行遍历
for i in mlist:
    print(i)

#对列表进行编缉
mlist[1] = "apple"
del mlist[5]
print(mlist)

#删除列表
# del mlist
mlist.clear()
print(mlist)

执行结果:
在这里插入图片描述

列表的操作

列表的操作符与元组相同
+,连接两个列表为一个大列表
*,将元组元素重复多次
in,判断列表中是否包含某元素
例如:

list1 = ["cat","tiger","dog","fox","bird"]
list2 = ["老鼠","大水牛","小兔子"]

#两个列表进行相加
print(list1+list2)        # ['cat', 'tiger', 'dog', 'fox', 'bird', '老鼠', '大水牛', '小兔子'
#列表乘以2       
print(list2*2)            # ['老鼠', '大水牛', '小兔子', '老鼠', '大水牛', '小兔子']
#判断是否在列表中
print("cat" in list1)    # True
print("大蟒蛇" in list2) # False

截取列表(切片)

列表的截取与元组相同

list1 = ["cat","tiger","dog","fox","bird"]

# 截取结果含头不含尾
#截取下标从0-2
print(list1[0:3])
#截取下标从0-倒数第2
print(list1[0:-1])
#截取下标从3-最后
print(list1[3:])
#截取下标从开头-倒数第4
print(list1[:-3])
#截取下标从头到尾
print(list1[:])
#截取下标从头到尾,每2取1
print(list1[::2])
#截取下标从头到尾,每-1取1
print(list1[::-1])
#截取下标从头到尾,每-2取1
print(list1[::-2])

执行结果:
在这里插入图片描述

相关函数

  • append(),插入一个元素
  • count() ,统计元素出现的个数
  • index() ,返回元素下标
  • pop(index) ,弹出并返回指定下标的元素
  • remove(index) ,移除指定的元素
  • reverse() ,将列表逆序
  • sort() ,列表排序
  • copy() ,拷贝列表
  • clear(),清空列表
    用法:
numbs = [1,4,5,9,3,6,9]

#插入一个元素
numbs.append(7)
print(numbs)

#统计某元素出现的次数
print(numbs.count(9))

#元素找出下标
print(numbs.index(5))

#移除指定的元素
numbs.remove(5)
print(numbs)

#将列表逆序
numbs.reverse()
print(numbs)

#列表排序
numbs.sort()
print(numbs)

#拷贝列表
print(numbs.copy())

#清空列表
numbs.clear()
print(numbs)

执行结果:
在这里插入图片描述

第四节:集合

集合的特点

  • 集合是无序不重复的元素容器,用set()表示
  • 由于无序,集合无法通过下标访问
  • 集合不重复的特性,常常用于进行去重操作

创建集合

  • 普通创建
  • 推导式创建
    例如:
#普通创建
# 创建空的集合,
mset = set()
print(mset)

# 直接赋值创建集合(无序)
yset = {1, 2.3, "4", complex(5, 6), False, None}  # True==1,False==0
print(yset)            # {{False, 1, 2.3, None, (5+6j), '4'}

# 推导式创建集合
iset = {i for i in range(1, 6)}
print(iset)            #{1, 2, 3, 4, 5}

aset = {i for i in range(2, 11, 2)}  # 从2-10间每二取一
print(aset)            #{2, 4, 6, 8, 10}

# 推导式创建集合+ 条件过滤
bset = {i for i in range(2, 11) if i % 2 == 0}
print(bset)           #{2, 4, 6, 8, 10}

#注意,这结果是字符串的相加,“i”必须也是字符串
cset = {"$" + str(i) for i in range(2, 11) if i % 2 == 0}
print(cset)            #{'$6', '$8', '$4', '$10', '$2'}

# 打散字符串形成集合
eset = {i for i in "hello"}
print(eset)           #{'h', 'e', 'l', 'o'}

# 推导式创建:遍历字符串 + 条件过滤
dset = {i for i in "hello world hello python" if i != "o"}
print(dset)           #{'w', 'p', 't', 'n', 'l', 'y', ' ', 'r', 'd', 'h', 'e'}

集合的操作

  • & 求交集
  • | 求并集
  • - 求差集(B集后没有的元素)
  • ^ 求异同集
  • in 判断是否在集合中
mset1 = {1, 2, 3, 4, 5}
mset2 = {4, 5, 6, 7, 8}

# 集合操作符
print(mset1 & mset2)  # 交集
print(mset1 | mset2)  # 并集
print(mset1 - mset2)  # mset1有,而mset2没有的数
print(mset1 ^ mset2)  # mset1没有或mset2没有

#判断是否在集合中
print(1 in mset1)     # True
print(-1 in mset2)    # False

相关函数

  • set(iterable) 可迭代对象转为集合
  • sorted() 排序
  • clear() 清空
    例如:
#将可迭代对象转化为集合
mset = set([1,3,2,5,4])
print(mset)   # {1, 2, 3, 4, 5}

yset = {1,5,8,3,6,2}
#排序(排后变成列表)
print(sorted(yset))   # [1, 2, 3, 5, 6, 8]

# 以下三行等效于sorted(yset):先转化为列表再对列表排序
mlist = list(yset)
mlist.sort()
print(mlist)      # [1, 2, 3, 5, 6, 8]

#清空集合
yset.clear()
print(yset)       # set()

第五节:字典

字典的特点

  • 字典用于存储键值对数据
  • 访问时根据去访问值
  • 字典是可以编辑的,包括增删键值对,修改键对应的值
  • 字典的遍历,通常是通过字典类方法items()来进行遍历的,每个item既包含了键又包含了值

创建字典

例如:

# 创建空字典
mdict = {}
print(mdict)        # {}
ydict = dict()
print(ydict)        # {}

# 赋值创建
adict = {"牛奶": 3.5, "巧克力": "5元3盒", "购物袋": "免费"}
print(type(adict))  # <class 'dict'>
print(adict)        # {'牛奶': 3.5, '巧克力': '5元3盒', '购物袋': '免费'

键访问元素的值

字典访问通过去访问
例如:

# 访问字典
mdict = {"牛奶": 3.5, "巧克力": "5元3盒", "购物袋": "免费"}
print(mdict["牛奶"])     # 3.5
print(mdict["购物袋"])   # 免费

# 访问并不存在的键,报KeyError
# print(mdict["冰红茶"])  # KeyError: '冰红茶'

字典的编缉、遍历与删除

例:

# 字典的编缉(更新)
mdict = {"牛奶": 3.5, "巧克力": "5元3盒", "购物袋": "免费"}
# 修改元素值
mdict["牛奶"] = 5
#添加新的元素
mdict["冰红茶"] = 3
print(mdict)

print("________________________________________________________")

# 字典的遍历
for k, v in mdict.items():
    print(k, v)


print("________________________________________________________")

del mdict["购物袋"]  # 删除一个元素(键值对)
print(mdict)

# 删除整个字典
del mdict

执行结果:
在这里插入图片描述

相关函数

  • 內建函数
    len(mdict) ,获得键值对个数
    str(mdict) ,将字典转化为纯字符串(类似于json字符串)
  • 字典函数
    copy() ,拷贝字典
    formkeys() ,由一堆键快速生成字典,值先填充为默认
    items() ,得到用于遍历的所有键值对
    keys() ,得到所有键
    values() ,得到所有值
    setdefault(“key”, None) ,设置键的默认值,没有这个键就设置一个默认值,有这个键则什么都不做
    update(dict2) ,以dict2为蓝本更新数据
    pop() ,弹出一个指定的键值对
    popitem() ,弹出最后一个键值对
    clear() ,清空字典
    例如:
# 参数1("牛奶","巧克力","购物袋")=键集
# 参数2"default"=所有键的默认值
newDict = dict.fromkeys(("牛奶", "巧克力", "购物袋"), "default")
print(newDict)

print("------------------------------------------------------------")

mdict = {"牛奶": 3.5, "巧克力": "5元3盒", "购物袋": "免费"}

#字典中的键集
print(mdict.keys())
#字典中的值集
print(mdict.values())

# 为键设置缺省值(如果该键值对不存在,则创建并赋值为默认值,如果存在则不做任何改动)
mdict.setdefault("牛奶", "默认5元")
mdict.setdefault("冰红茶", "默认5元")
print(mdict["牛奶"])     #值并未变动
print(mdict["冰红茶"])   #创建了新的键值

# 以mdict2为基准更新mdict,发现mdict中count的值变为和mdict2相同了
mdict2 = {"牛奶": 7}
mdict.update(mdict2)
print(mdict)

print("------------------------------------------------------------")

adict = {"牛奶": 3.5, "巧克力": "5元3盒", "购物袋": "免费", "key1": "value1", 123: 456}
# 弹出并删除一个值,默认为"不知道的价格"
print(adict.pop("牛奶", "不知道的价格"))  #弹出了个已有的键,并获取它的值
print(adict.pop("冰红茶", "不知道的价格"))  # 弹出一个不存在的键,值就为默认值

# 从尾部逐个弹出,item呈元组的形式
print(adict.popitem())
print(adict.popitem())
print(adict.popitem())

# 清空字典
adict.clear()
print(adict)

执行结果:
在这里插入图片描述

第六节:容器的扩展

定长参数与变长参数

变长参数使用"*_"
例:

x,*_,z = 1,2,3,4,5
print(*_)       # 2 3 4

a,b,c = (5,6,7)
print(a,b,c)    # 5 6 7

字典中添加元素

  • + ——列表的相加
  • extend() ——兼并另一个可迭代对象
  • append() ——末尾追加单个元素
  • insert() ——插入某个元素

例如:

a = [1,2,3]
b = [4,5]
c = (6,7)
d = "hello"

#列表兼并另一个列表(即列表的相加)
a += b
print(a)     # [1, 2, 3, 4, 5]

#列表兼并另一个可迭代对象(可以是列表,也可以是元组等)
#注意:如果兼并的是字符串,则会把字符串视为可迭代对象
a.extend(c)
print(a)     # [1, 2, 3, 4, 5, 6, 7]

#列表末尾追加单个元素
a.append(d)
print(a)     # [1, 2, 3, 4, 5, 6, 7, 'hello'

#在指定位置插入某个元素
a.insert(0,"begin")
print(a)    # ['begin', 1, 2, 3, 4, 5, 6, 7, 'hello']

浅拷贝

  • copy()
a = [1,2,["a","b"]]
b = a
print(b)

print("------------------------------------------------------")

#浅拷贝,拷贝之后是另外的东西,c不再是a,或b,只是值相同
c = a.copy()
print(c)
#虽然整体地址不同,但元素地址还是相同
print(id(a),id(a[0]),id(a[1]),id(a[2]))
print(id(c),id(c[0]),id(c[1]),id(c[2]))

print("------------------------------------------------------")

#对a或c的元素进行编缉,不会影响对方,元素是基本类型
a.insert(0,3)
print(a,c)

#对a或c的元素内的元素进行编缉,则会影响对方,元素内的元素是对象类型
a[-1].append(4)
print(a,c)

执行结果:
在这里插入图片描述

总结:
基本类型的传参,是值拷贝
对象类型的传参,是地址引用

花式遍历列表

  • reversed() ——反向遍历
  • zip() ——组合遍历
  • enumerate() ——序号遍历
    例如:
mlist = ["牛奶","橙汁","咖啡"]
ylist = [3,6,9]

print("____________ 反向遍历 _____________")

alist = reversed(mlist)
for i in alist:
    print(i)

print("____________ 组合遍历 _____________")

for m,y in zip(mlist,ylist):
    print(m,y)

print("____________ 序号遍历 _____________")
for x,i in enumerate(mlist):
    print(x,i)

执行结果:
在这里插入图片描述

字典的键值互换

  • 普通键值互换
  • 推导式键值互换
    例如:
d = {"牛奶":3,"橙汁":5,"咖啡":12}

print("——————普通键值互换——————")

dic = {}
for k,v in d.items():
    dic[v]=k
print(dic)

print("——————推导式键值互换——————")

#方法一:推导式+元组转字典
print(dict([(v,k) for k,v in d.items()]))
#方法二:推导式+字典
print({v:k for k,v in d.items()})
#方法三:推导式+组合遍历+字典
print({v:k for k,v in zip(d.keys(),d.values())})
#方法四:推导式+组合遍历+元组转列表+列表转字典
print(dict([(v,k) for k,v in zip(d.keys(),d.values())]))

执行结果:
在这里插入图片描述

第七节:深广遍历

深度遍历(递规实现)

import os
from tkinter import filedialog


#基于递规的深度遍历
def traverseDir(dirPath):
    #列出当前路径下的所有文件
    filenames = os.listdir(dirPath)
    #遍历所有文件
    for name in filenames:
        #文件全名 = 路径 + "/" + 文件名
        name = dirPath + "/" +name

        #计算当前路径的缩进,突出层级关系
        indent = name.count("/") - 2            #这里不一定是2,具体以文件夹所在位置为准
        #打印(缩进+文件全名)
        print("\t" * indent + name)

        #如果是子文件夹,就继续递规下一个文件
        if os.path.isdir(name):
            traverseDir(name)

if __name__ == '__main__':
    traverseDir(filedialog.askdirectory())
    pass

执行结果:
在这里插入图片描述

广度遍历(列队实现)

广度遍历与深度遍历相反,深度遍历是把一个文件夹遍历干净才轮到下一个文件夹,广度遍历是按层级遍历,由浅入深,一层遍历完才能执行下一层的文件内容,队列是一种先入先出的数据结构

  • ollections.deque() ——队列,用于容纳元素,可以从头部或尾部弹出元素
import os
from tkinter import filedialog
import collections


def traverseDirVast(dirPath):
    # 定义一个队列,用于装路径,先把父路径放入(当然用列表也没问题)
    PQ = collections.deque()
    PQ.append(dirPath)

    #如果容器不为空
    while len(PQ):
        #从队列容器头中拿出一个路径
        path = PQ.popleft()

        #并罗列这一层级内容
        filenames = os.listdir(path)
        for name in filenames:
            # 计算一下下层级的缩进,并打印文件路径名
            name = path + "/" + name
            indent = name.count("/") - 2  #这里不一定是2,具体以文件夹所在位置为准
            print("\t" * indent + name)

            #对文件进行判断,如果是文件夹,继续放入队列容器,
            if os.path.isdir(name):
                PQ.append(name)


if __name__ == '__main__':
    traverseDirVast(filedialog.askdirectory())

执行结果:
在这里插入图片描述

深度遍历(栈实现)

栈,也是使用队列,但是是一种先入后出的数据结构

import os
from tkinter import filedialog
import collections


def traverseDirDeep(dirPath):
    # 定义一个栈,用于装路径,先把父路径放入
    pStack = collections.deque()
    pStack.append(dirPath)

    #如果容器不为空
    while len(pStack):
        #从队列容器尾巴中拿出一个路径
        path = pStack.pop()
        #计算一下当前路径缩进,打印
        indent = path.count("/") - 2  # 这里不一定是2,具体以文件所在位置为准
        print("\t" * indent + path)

        #判断该路径是否是文件夹,如果是,罗列它的子文件
        if os.path.isdir(path):
            filenames = os.listdir(path)

            #逆序将所子文件放入栈中
            for name in reversed(filenames):
                #子文件名
                name = path + "/" + name
                pStack.append(name)


if __name__ == '__main__':
    traverseDirDeep(filedialog.askdirectory())

执行结果:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/xiangchi7/article/details/82942197