Python-内置数据结构-list-tuple-bubble-字符串-bytes-bytesarray-切片-学习笔记

发布于:2025-07-05 ⋅ 阅读:(21) ⋅ 点赞:(0)

        欠4年前自己的一份笔记,献给今后的自己。

分类

  • 数值型
            int、float、complex、bool

  • 序列对象
            字符串 str
            列表 list
            tuple

  • 键值对
            集合set
            字典dict

  • 数值型
            int、float、complex、bool都是class,1、5.0、2+3j都是对象即实例
            int:python3的int就是长整型,且没有大小限制,受限于内存区域的大小
            float:有整数部分和小数部分组成。支持十进制和科学计数法表示。只有双精度型。
            complex:有实数和虚数部分组成,实数和虚数部分都是浮点数,3+4.2J
            bool:int的子类,仅有2个实例True、False对应1和0,可以和整数直接运算

  • 类型转换(built-in)
            int(x) 返回一个整数
            float(x) 返回一个浮点数
            complex(x)、complex(x,y) 返回一个复数
            bool(x) 返回布尔值,前面讲过False等价的对象

数字的处理函数

  • round(),四舍五入?
  • math模块、floor()地板、天花板ceil()
  • int() 、//
  • 举例:
import math

print(int(-3.6), int(-2.5), int(-1.4))

print(int(3.6), int(2.5), int(1.4))

print(7 // 2, 7 // -2, -7 // 2, -(7 // 2))

print(2 // 3, -2 // 3, -1 // 3)
print(math.floor(2.5), math.floor(-2.5))
print(round(2.5), round(2.5001), round(2.6))
print(math.ceil(2.5), math.ceil(-2.5))
print(round(3.5), round(3.5001), round(3.6), round(3.3))
print(round(-2.5), round(-2.5001), round(-2.6))
print(round(-3.5), round(-3.5001), round(-3.6), round(-3.3))


输出:

-3 -2 -1
3 2 1
3 -4 -4 -3
0 -1 -1
2 -3
2 3 3
3 -2
4 4 4 3
-2 -3 -3
-4 -4 -4 -3


  • round(),四舍六入五取偶
  • floor()向下取整、ceil()向上取整
  • int() 取整数部分
  • // 整除且向下取整
  • min()
  • max()
  • pow(x,y) 等于 x**y
  • math.sqrt()
  • 进制函数,返回值是字符串
            bin()
            oct()
            hex()
  • math.pi π
  • math.e 自如常数

类型判断

  • type(obj) ,返回类型,而不是字符串
  • isinstance(obj, class_or_tuple),返回布尔值
    举例:
            type(a)
            type(‘abc’)
            type(123)
            isinstance(6, str)
            isinstance(6, (str, bool, int))
            type(1+True)
            type(1+True+2.0) # 是什么?隐式转换

列表list

  • 一个队列,一个排列整齐的队伍
  • 列表内的个体称作元素,由若干元素组成列表
  • 元素可以是任意对象(数字、字符串、对象、列表等)
  • 列表内元素有顺序,可以使用索引
  • 线性的数据结构
  • 使用 [ ] 表示
  • 列表是可变的
  • 列表list、链表、queue、stack的差异

列表list定义 初始化

  • list() -> new empty list
  • list(iterable) -> new list initialized from iterable’s items
  • 列表不能一开始就定义大小
    lst = list()
    lst = []
    lst = [2, 6, 9, ‘ab’]
    lst = list(range(5))

列表索引访问

  • 索引,也叫下标
  • 正索引:从左至右,从0开始,为列表中每一个元素编号
  • 负索引:从右至左,从-1开始
  • 正负索引不可以超界,否则引发异常IndexError
  • 为了理解方便,可以认为列表是从左至右排列的,左边是头部,右边是尾部,左边是下界,右边是上界
  • 列表通过索引访问
            list[index] ,index就是索引,使用中括号访问

列表查询

  • index(value,[start,[stop]])
    通过值value,从指定区间查找列表内的元素是否匹配
    匹配第一个就立即返回索引
    匹配不到,抛出异常ValueError
  • count(value)
    返回列表中匹配value的次数
  • 时间复杂度
    index和count方法都是O(n)
    随着列表数据规模的增大,而效率下降
  • 如何返回列表元素的个数?如何遍历?如何设计高效?
    len()

如何查帮助

在这里插入图片描述

列表元素修改

  • 索引访问修改
    list[index] = value
    索引不要超界

列表增加、插入元素

  • append(object) -> None
    列表尾部追加元素,返回None
    返回None就意味着没有新的列表产生,就地修改
    时间复杂度是O(1)
  • insert(index, object) -> None
    在指定的索引index处插入元素object
    返回None就意味着没有新的列表产生,就地修改
    时间复杂度是O(n)
    索引能超上下界吗?
            超越上界,尾部追加
            超越下界,头部追加
  • extend(iteratable) -> None
            将可迭代对象的元素追加进来,返回None
            就地修改
    + -> list
            连接操作,将两个列表连接起来
            产生新的列表,原列表不变
            本质上调用的是__add__()方法
  • -> list
            重复操作,将本列表元素重复n次,返回新的列表

    Python中用[]表示空的list,我们也可以直接在其中填充元素进行初始化:

# Lists store sequences
li = []
# You can start with a prefilled list
other_li = [4, 5, 6]

print(li)

print(other_li)

    使用append和pop可以在list的末尾插入或者删除元素:

# Lists store sequences
li = []

# Add stuff to the end of a list with append
li.append(1)  # li is now [1]
print(li)

li.append(2)  # li is now [1, 2]
print(li)
li.append(4)  # li is now [1, 2, 4]
print(li)
li.append(3)  # li is now [1, 2, 4, 3]
print(li)
# Remove from the end with pop
li.pop()  # => 3 and li is now [1, 2, 4]
# Let's put it back
li.append(3)  # li is now [1, 2, 4, 3] again.

print(li)

    list可以通过[]加上下标访问指定位置的元素,如果是负数,则表示倒序访问。-1表示最后一个元素,-2表示倒数第二个,以此类推。如果访问的元素超过数组长度,则会出发IndexError的错误。

# Lists store sequences
li = [1,2,3,4,5]


# Access a list like you would any array
print(li[0]) # => 1
# Look at the last element
print(li[-1]) # => 5
# Looking out of bounds is an IndexError
print(li[10]) # Raises an IndexError


输出 : 
1
5
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test1.py", line 10, in <module>
    print(li[10]) # Raises an IndexError
          ~~^^^^
IndexError: list index out of range

    list支持切片操作,所谓的切片则是从原list当中拷贝出指定的一段。我们用start:end的格式来获取切片,注意,这是一个左闭右开区间。如果留空表示全部获取,我们也可以额外再加入一个参数表示步长,比如[1:5:2]表示从1号位置开始,步长为2获取元素。得到的结果为[1, 3]。如果步长设置成-1则代表反向遍历。

# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li = [1, 2, 4, 3]
print(li[1:3])  # Return list from index 1 to 3 => [2, 4]
print(li[2:])  # Return list starting from index 2 => [4, 3]
print(li[:3])  # Return list from beginning until index 3 => [1, 2, 4]
print(li[::2])  # Return list selecting every second entry => [1, 4]
print(li[::-1])  # Return list in reverse order => [3, 4, 2, 1]
# Use any combination of these to make advanced slices
# li[start:end:step]

    如果我们要指定一段区间倒序,则前面的start和end也需要反过来,例如我想要获取[3: 6]区间的倒序,应该写成[6:3:-1]。
只写一个:,表示全部拷贝,如果用is判断拷贝前后的list会得到False。可以使用del删除指定位置的元素,或者可以使用remove方法。

# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li = [1, 2, 4, 3]



# Make a one layer deep copy using slices
li2 = li[:] # => li2 = [1, 2, 4, 3] but (li2 is li) will result in false.
print(li2)
# Remove arbitrary elements from a list with "del"
del li[2] # li is now [1, 2, 3]
print(li)
# Remove first occurrence of a value
li.remove(2) # li is now [1, 3]
print(li)
li.remove(2) # Raises a ValueError as 2 is not in the list
print(li)


输出:
[1, 2, 4, 3]
[1, 2, 3]
[1, 3]

Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test1.py", line 17, in <module>
    li.remove(2) # Raises a ValueError as 2 is not in the list
    ~~~~~~~~~^^^
ValueError: list.remove(x): x not in list


    insert方法可以指定位置插入元素,index方法可以查询某个元素第一次出现的下标。

# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li = [1, 2, 4, 3]

# Insert an element at a specific index
li.insert(1, 2)  # li is now [1, 2, 3] again
print(li)

# Get the index of the first item found matching the argument

print(li.index(2))  # => 1
li = [1, 2, 4, 3]
print(li.index(5))  # Raises a ValueError as 4 is not in the list

输出 : 
[1, 2, 2, 4, 3]
1
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test1.py", line 14, in <module>
    print(li.index(5))  # Raises a ValueError as 4 is not in the list
          ~~~~~~~~^^^
ValueError: 5 is not in list

    list可以进行加法运算,两个list相加表示list当中的元素合并。等价于使用extend方法:

# You can look at ranges with slice syntax.
# The start index is included, the end index is not
# (It's a closed/open range for you mathy types.)
li = [1, 2, 4, 3]

other_li = [4, 5, 6]

# You can add lists
# Note: values for li and for other_li are not modified.


print(li + other_li)  # => [1, 2, 3, 4, 5, 6]

# Concatenate lists with "extend()"
li.extend(other_li)  # Now li is [1, 2, 3, 4, 5, 6]

    我们想要判断元素是否在list中出现,可以使用in关键字,通过使用len计算list的长度:

li = [1, 2, 4, 3]

other_li = [4, 5, 6]

# Check for existence in a list with "in"
print(1 in li) # => True
# Examine the length with "len()"
print(len(li)) # => 6

列表 *重复的坑

  • * -> list
    重复操作,将本列表元素重复n次,返回新的列表
x = [[1,2,3]]*3
print(x)
x[0][1] = 20
print(x)
y = [1]*5
y[0] = 6
y[1] = 7
print(y)

输出:
[[1, 2, 3], [1, 2, 3], [1, 2, 3]]
[[1, 20, 3], [1, 20, 3], [1, 20, 3]]
[6, 7, 1, 1, 1]

上面代码运行结果是什么?为什么?

列表删除元素

  • remove(value) -> None
            从左至右查找第一个匹配value的值,移除该元素,返回None
            就地修改
            效率?
    8 pop([index]) -> item
            不指定索引index,就从列表尾部弹出一个元素
            指定索引index,就从索引处弹出一个元素,索引超界抛出IndexError错误
            效率?指定索引的的时间复杂度?不指定索引呢?
  • clear() -> None
            清除列表所有元素,剩下一个空列表

列表其它操作

  • reverse() -> None
            n将列表元素反转,返回None
            就地修改
  • sort(key=None, reverse=False) -> None
            对列表元素进行排序,就地修改,默认升序
            reverse为True,反转,降序
            key一个函数,指定key如何排序
            lst.sort(key=functionname)
  • in
             [3,4] in [1, 2, [3,4]]
             for x in [1,2,3,4]

列表复制

lst0 = list(range(4))
lst2 = list(range(4))
print(lst0==lst2)
lst1 = lst0
lst1[2] = 10
print(lst0)
lst0==lst2相等吗?为什么?lst0里面存的是什么?
请问lst0的索引为2的元素的值是什么?
请问lst1 = lst0这个过程中有没有复制过程?

输出:
True
[0, 1, 10, 3]


  • copy() -> List shadow copy返回一个新的列表
lst0 = list(range(4))
lst5 = lst0.copy()
print(lst5 == lst0)
lst5[2] = 10
print(lst5 == lst0)
lst0和lst5一样吗?
对比左右程序的差别


lst0 = [1, [2, 3, 4], 5]
lst5 = lst0.copy()
lst5 == lst0
lst5[2] = 10
lst5 == lst0
lst5[2] = 5
lst5[1][1] = 20
lst5 == lst0

输出:
True
False

  • shadow copy
            影子拷贝,也叫浅拷贝,遇到引用类型,只是复制了一个引用而已
  • 深拷贝
            copy模块提供了deepcopy
import copy
lst0 = [1, [2, 3, 4], 5]
lst5 = copy.deepcopy(lst0)
lst5[1][1] = 20
lst5 == lst0

在这里插入图片描述

随机数

  • random模块
  • randint(a, b) 返回[a, b]之间的整数
  • choice(seq) 从非空序列的元素中随机挑选一个元素,比如random.choice(range(10)),从0到9中随机挑选一个整数。random.choice([1,3,5,7])
  • randrange ([start,] stop [,step]) 从指定范围内,按指定基数递增的集合中获取一个随机数,基数
            缺省值为1。 random.randrange(1,7,2)
  • random.shuffle(list) ->None 就地打乱列表元素
  • sample(population, k) 从样本空间或总体(序列或者集合类型)中随机取出k个不同的元素,返回
    一个新的列表
            random.sample([‘a’, ‘b’, ‘c’, ‘d’], 2)
            random.sample([‘a’, ‘a’], 2) 会返回什么结果

    关于list的判断,我们常用的判断有两种,一种是刚才介绍的==,还有一种是is。我们有时候也会简单实用is来判断,那么这两者有什么区别呢?我们来看下面的例子:

a = [1, 2, 3, 4]  # Point a at a new list, [1, 2, 3, 4]
print(a)
b = a  # Point b at what a is pointing to
print(b is a)  # => True, a and b refer to the same object
print(b == a)  # => True, a's and b's objects are equal
b = [1, 2, 3, 4]  # Point b at a new list, [1, 2, 3, 4]
print(b is a)  # => False, a and b do not refer to the same object
print(b == a)  # => True, a's and b's objects are equal

    Python是全引用的语言,其中的对象都使用引用来表示。is判断的就是两个引用是否指向同一个对象,而==则是判断两个引用指向的具体内容是否相等。举个例子,如果我们把引用比喻成地址的话,is就是判断两个变量的是否指向同一个地址,比如说都是沿河东路XX号。而==则是判断这两个地址的收件人是否都叫张三。
显然,住在同一个地址的人一定都叫张三,但是住在不同地址的两个人也可以都叫张三,也可以叫不同的名字。所以如果a is b,那么a == b一定成立,反之则不然。

求100内的素数

import math
import datetime

start = datetime.datetime.now()

primenumber = []

flag = False

count = 1

for x in range(3, 100000, 2) :
    for i in primenumber:
        if x % i == 0:
            flag = True
            break

        if i >= math.ceil(math.sqrt(x)) :
            flag = False
            break

    if not flag:
        #print(x)

        count += 1

        primenumber .append (x)

delta = (datetime.datetime.now() - start).total_seconds()

print(delta)

print(count)

print ("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

杨辉三角

在这里插入图片描述


triangle = [[1], [1, 1]]


for i in range(2,6):
    cur = [1]
    pre = triangle[i-1]
    for j in range(len(pre)-1):

        cur.append(pre[j] + pre[j+1])
    cur.append (1)
    triangle.append (cur)

print(triangle)

变体一 :

triangle = []

n = 6

for i in range(n):

    cur = [1]

    triangle.append(cur)

    if i == 0:
        continue

    pre = triangle[i - 1]

    for j in range(len(pre) - 1):
        cur.append(pre[j] + pre[+1])

    cur.append(1)

print(triangle)

补零(方法2)
除了第一行以外,每一行每一个元素(包括两头的1)都是由上一行的元素相加得到。如何得到两头的1呢?目标是打印指定的行,所以算出一行就打印一行,不需要用一个大空间存储所有已经算出的行。

while循环实现

n = 6

newline =[1] # 相当于计算好的第一行

print(newline)

for i in range(1,n):
    oldline = newline.copy() # 浅拷贝并补0

    oldline.append(0)  # 尾部补0相当于两端补0

    newline.clear() # 使用append,所以要清除

    offset = 0

    while offset <= i:
        newline.append(oldline[offset-1] + oldline[offset])

        offset += 1

print(newline)

for循环实现

n = 6

newline =[1]  # 相当于计算好的第一行

print(newline)

for i in range(1,n):

    oldline = newline.copy()    # 浅拷贝并补0

    oldline.append(0) # 尾部补0相当于两端补0

    newline.clear() # 使用append,所以要清除

    for j in range(i+1):
        newline.append(oldline[j - 1] + oldline[j])

    print(newline)

        上面的代码看似不错,但行初始化的代码明显繁琐了,进一步简化

triangle = []

n = 6

for i in range(n):

    row = [1] * (i + 1)  # 一次性开辟

    triangle.append(row)

    for j in range(1, i // 2 + 1):  # i=2第三行才能进来

        # print(i, j)

        val = triangle[i - 1][j - 1] + triangle[i - 1][j]
        row[j] = val

        if i != 2 * j:  # 奇数个数的中点跳过

            row[-j - 1] = val

print(triangle)

        首先我们明确的知道所求最大行的元素个数,例如前6行的最大行元素个数为6个。下一行等于首元素不变,覆盖中间元素。

n = 6

row = [1] * n  # 一次性开辟足够的空间

for i in range(n):

    offset = n - i

    z = 1  # 因为会有覆盖影响计算,所以引入一个临时变量学院

    for j in range(1, i // 2 + 1):  # 对称性

        val = z + row[j]

        row[j], z = val, row[j]

        if i != 2 * j:
            row[-j - offset] = val

    print(row[:i + 1])

求杨辉三角第n行第k列的值

计算到m行,打印出k项

# 求m行k个元素

# m行元素有m个,所以k不能大于m

# 这个需求需要保存m行的数据,那么可以使用一个嵌套机构[L],[],[]]

m = 5

k = 4

triangle = []

for i in range(m):

    # 所有行都需要1开头

    row = [1]

    triangle.append(row)
    if i == 0:
        continue
    for j in range(1, i):
        row.append(triangle[i - 1][j - 1] + triangle[i - 1][j])
    row.append(1)

print(triangle)

print("---------" * 2)

print(triangle[m - 1][k - 1])

print("*" * 20)


输出:
[[1], [1, 1], [1, 2, 1], [1, 3, 3, 1], [1, 4, 6, 4, 1]]
------------------
4
********************
算法2

在这里插入图片描述

# m行k列的值,C(m-1,k-1)组合数

m = 9

k = 5

# m最大

n = m - 1

r = k - 1

# c(n,r) = c(m-1, k-1) = (m-1) !/((k-1)! (m-r) !)

d = n - r

targets = []  # r,n-r, n

factorial = 1

# 可以加入k为1或者m的判断,返回1
for i in range(1, n + 1):

    factorial *= i

    if i == r:
        targets.append(factorial)
    if i == d:
        targets.append(factorial)
    if i == n:
        targets.append(factorial)

        # print(targets)

print(targets[2] // (targets[0] * targets[1]))

输出:
70

在这里插入图片描述

元组tuple

  • 一个有序的元素组成的集合
  • 使用小括号()表示
  • 口元组是不可变对象

    tuple和list非常接近,tuple通过()初始化。和list不同,tuple是不可变对象。也就是说tuple一旦生成不可以改变。如果我们修改tuple,会引发TypeError异常。

# Tuples are like lists but are immutable.
tup = (1, 2, 3)
print(tup[0]) # => 1
tup[0] = 3 # Raises a TypeError



输出 : 
1
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test1.py", line 4, in <module>
    tup[0] = 3 # Raises a TypeError
    ~~~^^^
TypeError: 'tuple' object does not support item assignment


    由于小括号是有改变优先级的含义,所以我们定义单个元素的tuple,末尾必须加上逗号,否则会被当成是单个元素:

# Note that a tuple of length one has to have a comma after the last element but
# tuples of other lengths, even zero, do not.
print(type((1))) # => <class 'int'>
print(type((1,))) # => <class 'tuple'>
print(type(())) # => <class 'tuple'>

    tuple支持list当中绝大部分操作:

# You can do most of the list operations on tuples too
tup = (1, 2, 3)
print(len(tup))  # => 3
print(tup + (4, 5, 6))  # => (1, 2, 3, 4, 5, 6)
print(tup[:2])  # => (1, 2)
print(2 in tup ) # => True



输出 : 
3
(1, 2, 3, 4, 5, 6)
(1, 2)
True


    我们可以用多个变量来解压一个tuple:

# You can unpack tuples (or lists) into variables
a, b, c = (1, 2, 3) # a is now 1, b is now 2 and c is now 3
print(a, b, c)
# You can also do extended unpacking
a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4
print(a, b, c)
# Tuples are created by default if you leave out the parentheses
d, e, f = 4, 5, 6 # tuple 4, 5, 6 is unpacked into variables d, eand f
print(d, e, f)
# respectively such that d = 4, e = 5 and f = 6
# Now look how easy it is to swap two values
e, d = d, e # d is now 5 and e is now 4
print(d, e)

输出:
1 2 3
1 [2, 3] 4
4 5 6
5 4

解释一下这行代码:

a, *b, c = (1, 2, 3, 4) # a is now 1, b is now [2, 3] and c is now 4

    我们在b的前面加上了星号,表示这是一个list。所以Python会在将其他变量对应上值的情况下,将剩下的元素都赋值给b。补充一点,tuple本身虽然是不可变的,但是tuple当中的可变元素是可以改变的。比如我们有这样一个tuple:



a = (3, [4])
print(a)

a[1].append(0) # 这是合法的
print(a)

输出:
(3, [4])
(3, [4, 0])

    我们虽然不能往a当中添加或者删除元素,但是a当中含有一个list,我们可以改变这个list类型的元素,这并不会触发tuple的异常:

转置矩阵

有一个方阵,左边方阵,求其转置矩阵
在这里插入图片描述

规律:对角线不动,alillil <=> alili,而且到了对角线,就停止,去做下一行,对角线上的元素不动

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
print(matrix)

count = 0

for i, row in enumerate(matrix):

    for j, col in enumerate(row):

        if i < j:
            temp = matrix[i][j]

            matrix[i][j] = matrix[j][i]
            matrix[j][i] = temp

            count += 1

print(matrix)

print(count)


输出:

[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
3

方法二:

#

matrix = [[1,2,3,10],
          [4,5,6,11],
          [7,8,9,12],
          [1,2,3,4]]

length = len(matrix)

count = 0

for i in range(length):

    for j in range(i): # j<i


        matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]

count += 1

print(matrix)

print(count)

输出:

[[1, 4, 7, 1], [2, 5, 8, 2], [3, 6, 9, 3], [10, 11, 12, 4]]
1


有一个任意矩阵,求其转置矩阵

在这里插入图片描述

算法1

过程就是,扫描matrx第一行,在tm的第一列从上至下附加,然后再第二列附加举例,扫描第一行1.2,3,加入到tm的第一列,然后扫描第二行4,5,6,追加到tm的第二列

# 定义一个矩阵,不考虑稀疏矩阵

# 1 2 3     1 4

# 4 5 6 =>> 2 5

#           3 6

import datetime

matrix = [[1, 2, 3], [4, 5, 6]]

# matrix = [[1,4],[2,5],[3,6]]

tm = []

count = 0

for row in matrix:

    for i, col in enumerate(row):

        if len(tm) < i + 1:  # matrix有i列就要为tm创建i行

            tm.append([])

        tm[i].append(col)

        count += 1

print(matrix)

print(tm)

print(count)


输出:

[[1, 2, 3], [4, 5, 6]]
[[1, 4], [2, 5], [3, 6]]
6

算法2

思考:

能否一次性开辟目标矩阵的内存空间?

如果一次性开辟好目标矩阵内存空间,那么原矩阵的元素直接移动到转置矩阵的对称坐标就行了

# 定义一个矩阵,不考虑稀疏矩阵

# 1 2 3     1 4

# 4 5 6 =>> 2 5

#           3 6

import datetime

matrix = [[1, 2, 3], [4, 5, 6]]

# matrix = [[1,4],[2,5],[3,6]]
tm = [[0 for col in range(len(matrix))] for row in range(len(matrix[0]))]

count = 0

for i, row in enumerate(tm):

    for j, col in enumerate(row):
        tm[i][j] = matrix[j][i]  # 将matrix的所有元素搬到tm中

        count += 1

print(matrix)

print(tm)

print(count)


输出:

[[1, 2, 3], [4, 5, 6]]
[[1, 4], [2, 5], [3, 6]]
6
效率测试
import datetime

matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

matrix = [[1, 4], [2, 5], [3, 6]]

print('\nMethod 1')

start = datetime.datetime.now()
for c in range(100000):
    tm = []  # 目标矩阵

    for row in matrix:

        for i, item in enumerate(row):

            if len(tm) < i + 1:
                tm.append([])

            tm[i].append(item)

delta = (datetime.datetime.now() - start).total_seconds()
print(delta)

print(matrix)

print(tm)

print('\nMethod 2')

start = datetime.datetime.now()
for c in range(100000):

    tm = [0] * len(matrix[0])
    for i in range(len(tm)):
        tm[i] = [0] * len(matrix)

    # print(tm)

    for i, row in enumerate(tm):

        for j, col in enumerate(row):
            tm[i][j] = matrix[j][i]

delta = (datetime.datetime.now() - start).total_seconds()
print(delta)

print(matrix)

print(tm)


输出:

Method 1
0.094851
[[1, 4], [2, 5], [3, 6]]
[[1, 2, 3], [4, 5, 6]]

Method 2
0.100858
[[1, 4], [2, 5], [3, 6]]
[[1, 2, 3], [4, 5, 6]]

说明:

上面两个方法在ipython中,使用%%timeit测试下来方法一效率高。

但是真的是方法一效率高吗?

给一个大矩阵,测试一下

matrix = [[1, 2, 3], [4,5, 6], [1, 2, 3], [4,5, 6], [1,2, 3], [4,5, 6], [1, 2,3], [4,5, 6], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3], [4,5, 6], [1, 2, 3],
[4,5,6]]

测试发现,其实只要增加到4*4开始,方法二优势就开始了。

矩阵规模越大,先开辟空间比后append效率高。

元组的定义 初始化

  • 定义

        tuple() -> empty tuple

        tuple(iterable) -> tuple initialized from iterable’s items

t = tuple() # 工厂方法
t = ()
t = tuple(range(1,7,2)) # iteratable
t = (2,4,6,3,4,2)
t = (1,) # 一个元素元组的定义,注意有个逗号
t = (1,)*5
t = (1,2,3) * 6

元组元素的访问

  • 支持索引(下标)

  • 正索引:从左至右,从0开始,为列表中每一个元素编号口

  • 负索引:从右至左,从-1开始

  • 正负索引不可以超界,否则引发异常IndexError

  • 元组通过索引访问

        tuple[index],index就是索引,使用中括号访问

t[1]
t[-2]
t[1] = 5

元组查询

  • index(value,[start,[stop]])
    通过值value,从指定区间查找列表内的元素是否匹配
    匹配第一个就立即返回索引
    匹配不到,抛出异常ValueError
  • count(value)
    返回列表中匹配value的次数
  • 时间复杂度
    index和count方法都是O(n)
    随着列表数据规模的增大,而效率下降
  • len(tuple)
    返回元素的个数

元组其它操作

  • 元组是只读的,所以增、改、删方法都没有

命名元组namedtuple

  • 帮助文档中,查阅namedtuple,有使用例程
  • namedtuple(typename, field_names, verbose=False, rename=False)
             命名元组,返回一个元组的子类,并定义了字段
             field_names可以是空白符或逗号分割的字段的字符串,可以是字段的列表
from collections import namedtuple
Point = namedtuple('_Point',['x','y']) # Point为返回的类
p = Point(11, 22)
Student = namedtuple('Student', 'name age')
tom = Student('tom', 20)
jerry = Student('jerry', 18)
tom.name

练习

  • 依次接收用户输入的3个数,排序后打印
  1. 转换int后,判断大小排序。使用分支结构完成
  2. 使用max函数
  3. 使用列表的sort方法
  4. 冒泡法

冒泡法

  • 冒泡法
    属于交换排序
    两两比较大小,交换位置。如同水泡咕嘟咕嘟往上冒
    结果分为升序和降序排列
  • 升序
            n个数从左至右,编号从0开始到n-1,索引0和1的值比较,如果索引0大,则交换两者位置,如果索引1大,则不交换。继续比较索引1和2的值,将大值放在右侧。直至n-2和n-1比较完,第一轮比较完成。第二轮从索引0比较到n-2,因为最右侧n-1位置上已经是最大值了。依次类推,每一轮都会减少最右侧的不参与比较,直至剩下最后2个数比较。
  • 降序
    和升序相反

在这里插入图片描述

冒泡法代码实现(一)

from sortTest.Maopao1 import num_list

num_list = [
    [1, 9, 8, 5, 5, 6, 7, 4, 3, 2],

    [1, 2, 3, 4, 5, 6, 7, 8, 9]]

nums = num_list[1]

print(nums)

length = len(nums)

count_swap = 0

count = 0

# bubble sort

for i in range(length):

    for j in range(length - i - 1):

        count += 1

        if nums[j] > nums[j + 1]:
            tmp = nums[j]

            nums[j] = nums[j + 1]

            nums[j + 1] = tmp

            count_swap += 1


print(nums, count_swap, count)

冒泡法代码实现(二)

num_list = [
    [1, 9, 8, 5, 6, 7, 4, 3, 2],
    [1, 2, 3, 4, 5, 6, 7, 8, 9],
    [1, 2, 3, 4, 5, 6, 7, 8, 9]]

nums = num_list[2]
print(nums)
length = len(nums)
count_Swap = 0
count = 0

# bubble sort

for i in range(length):
    flag = False

    for j in range(length - i - 1):
        count += 1

        if nums[j] > nums[j + 1]:
            tmp = nums[j]
            nums[j] = nums[j + 1]
            nums[j + 1] = tmp
            flag = True  # swapped
            count_Swap += 1

    if not flag:
        break

print(nums, count_Swap, count)

例一:

from collections import namedtuple

Point = namedtuple('P', ['x', 'y'])
print(Point)

p1 = Point(10, 20)
print(p1)

print(p1.x, p1.y)

print(p1[0], p1[1])


Student = namedtuple('stu','name age')
s1 = Student('tom',20)
s2 = Student('jerry',30)
print(s1.name)
print(s2.age)


结果输出:
<class '__main__.P'>
P(x=10, y=20)
10 20
10 20
tom
30

例二:



def sum(a,b):
    return a ,b

a,b = sum(1,2)
print(a,b)

输出:
1 2

例三:



a = tuple([1,2])
print(a )

输出:

(1, 2)

冒泡法总结

  • 冒泡法需要数据一轮轮比较
  • 可以设定一个标记判断此轮是否有数据交换发生,如果没有发生交换,可以结束排序,如果发生交换,继续下一轮排序
  • 最差的排序情况是,初始顺序与目标顺序完全相反,遍历次数1,…,n-1之和n(n-1)/2
  • 最好的排序情况是,初始顺序与目标顺序完全相同,遍历次数n-1
  • 时间复杂度O(n^2)

字符串

    Python当中对字符串的限制比较松,双引号和单引号都可以表示字符串,看个人喜好使用单引号或者是双引号。我个人比较喜欢单引号,因为写起来方便。字符串也支持+操作,表示两个字符串相连。除此之外,我们把两个字符串写在一起,即使没有+,Python也会为我们拼接:

# Strings are created with " or '
print("This is a string.")
print('This is also a string.')
# Strings can be added too! But try not to do this.
print( "Hello " + "world!") # => "Hello world!"
# String literals (but not variables) can be concatenated without using '+'
print("Hello " "world!" )# => "Hello world!"

    我们可以使用[]来查找字符串当中某个位置的字符,用len来计算字符串的长度。

# A string can be treated like a list of characters
print("This is a string"[0])  # => 'T'
# You can find the length of a string
print(len("This is a string"))  # => 16

    我们可以在字符串前面加上f表示格式操作,并且在格式操作当中也支持运算,比如可以嵌套上len函数等。不过要注意,只有Python3.6以上的版本支持f操作。

# You can also format using f-strings or formatted string literals (in Python 3.6+)
name = "Reiko"
print(f"She said her name is {name}.")  # => "She said her name is Reiko"
# You can basically put any Python statement inside the braces and it will be output in the string.
print(f"{name} is {len(name)} characters long.")  # => "Reiko is 5 characters long."

    最后是None的判断,在Python当中None也是一个对象,所有为None的变量都会指向这个对象。根据我们前面所说的,既然所有的None都指向同一个地址,我们需要判断一个变量是否是None的时候,可以使用is来进行判断,当然用==也是可以的,不过我们通常使用is。

# None is an object
print(None)  # => None
# Don't use the equality "==" symbol to compare objects to None
# Use "is" instead. This checks for equality of object identity.
print("etc" is None)  # => False
print(None is None)  # => True

    理解了None之后,我们再回到之前介绍过的bool()函数,它的用途其实就是判断值是否是空。所有类型的默认空值会被返回False,否则都是True。比如0,“”,[], {}, ()等。

# None, 0, and empty strings/lists/dicts/tuples all evaluate toFalse.
# All other values are True
print(bool(None))  # => False
print(bool(0))  # => False
print(bool(""))  # => False
print(bool([]))  # => False
print(bool({}))  # => False
print(bool(()))  # => False

    除了上面这些值以外的所有值传入都会得到True。

几种字符串的表示

    在Python中,字符串是一种基本的数据类型,可以使用多种方式进行表示:

    普通字符串:使用单引号(’或双引号(”)括起米的字符串,例如:

 print('323232')
 输出:323232

    原始字符串:使用反斜杠(\)转义特殊字符的字符串,例如:

    在Python中,r表示原始字符串(raw string)。原始宇符串是一种特类型的字符串,在字符串中不会将反斜杠(\)视为转义字符,而是作为普通字符原样输出。

print(r'hello\nworld!')
输出:hello\nworld!

    三引号字符串:使用三个引号(单引号或双引号)括起来的字符串,可以包含多行文本,例如:

    三引号字符串可以用来表示包含多行文本的字符串

    当字符串中包含引号时,为了避免将引号视为转义字符,

    可以使用三引号字符串。

    三引号字符串也可以用来表示文档字符串

在这里插入图片描述
    f-string: 使用f-string表示格式化的字符串,主要作用是简化了字符串格式化的过程,使得代码更加简洁和易读。

    f-string使用大写的F‘或者作为字符串的前缀,然后在字符串中用花括号日来标记需要插入或替换的表达式。

for i in range(5):
    print(f'第{i + 1} 个数字是{i}')

在这里插入图片描述

Unicode字符串和字节串

    Unicode字符串通常用于表示包含非ASCII拿符的字符串,比如包含中文字符或特殊符号的文本。

    在Python中,Unicode字符串通常以u或U“作为前缀, Unicode字符串表示的是字符本身,而不是它们的编码形式。

# codecs是Python的一个标准库,它提供了对各种字符编码的读取和写入操作的支持。

import codecs

# 定义一个包含中文字符的Unicode字符串

text = u'hello, Python! '

#  打印该字符串

print(text)

# 將该字符串写入文件

with codecs.open('output.txt', 'w', 'utf-8') as f:
    f.write(text)

在这里插入图片描述

    字节串 (Byte String)是一种特的数据类型,用于表示二进制数据。字节串以b或bytes作前缀, 并且包含了一串字符的ASCI码表示。每个字符都是一个字节,因此字节串可以包含多个字节。


	# 创建一个字符串
	
	byte_string = b'Hello,World!'

	# 打印字符串
	print(byte_string)

	# 将字节串转换成字符串(需要解码 ) 

	strint = byte_string.decode('utf-8')

	print(strint)


	# 将字符串转换成字节串 (需要编码 )
	byte_string = strint.encode('utf-8')

	print(byte_string)

输出 :
在这里插入图片描述

  • 一个个字符组成的有序的序列,是字符的集合
    使用单引号、双引号、三引号引住的字符序列
    字符串是不可变对象
    Python3起,字符串就是Unicode类型

字符串定义 初始化

s1 = 'string'
s2 = "string2"
s3 = '''this's a "String" '''
s4 = 'hello \n magedu.com'
s5 = r"hello \n magedu.com"
s6 = 'c:\windows\nt'
s7 = R"c:\windows\nt"
s8 = 'c:\windows\\nt'
sql = """select * from user where name='tom' """

字符串元素访问——下标

  • 字符串支持使用索引访问

sql = "select * from user where name='tom'"
print(sql)
print(sql[4]) # 字符串'c'
sql[4] = 'o'
## print(sql)


输出:

select * from user where name='tom'
c

Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test2.py", line 4, in <module>
    sql[4] = 'o'
    ~~~^^^
TypeError: 'str' object does not support item assignment

  • 有序的字符集合,字符序列

sql = "select * from user where name='tom'"
for c in sql:
    print(c)
    print(type(c)) # 什么类型?

输出:
s
<class 'str'>
e
<class 'str'>
l
<class 'str'>
e
<class 'str'>
c
<class 'str'>
t
<class 'str'>
 
<class 'str'>
*
<class 'str'>
 
<class 'str'>
f
<class 'str'>
r
<class 'str'>
o
<class 'str'>
m
<class 'str'>
 
<class 'str'>
u
<class 'str'>
s
<class 'str'>
e
<class 'str'>
r
<class 'str'>
 
<class 'str'>
w
<class 'str'>
h
<class 'str'>
e
<class 'str'>
r
<class 'str'>
e
<class 'str'>
 
<class 'str'>
n
<class 'str'>
a
<class 'str'>
m
<class 'str'>
e
<class 'str'>
=
<class 'str'>
'
<class 'str'>
t
<class 'str'>
o
<class 'str'>
m
<class 'str'>
'
<class 'str'>
  • 可迭代

sql = "select * from user where name='tom'"
lst = list(sql)
print(lst)

输出:
['s', 'e', 'l', 'e', 'c', 't', ' ', '*', ' ', 'f', 'r', 'o', 'm', ' ', 'u', 's', 'e', 'r', ' ', 'w', 'h', 'e', 'r', 'e', ' ', 'n', 'a', 'm', 'e', '=', "'", 't', 'o', 'm', "'"]

字符串join连接*

  • “string”.join(iterable) -> str
    将可迭代对象连接起来,使用string作为分隔符
    可迭代对象本身元素都是字符串
    返回一个新字符串
lst = ['1','2','3']
print("\"".join(lst)) # 分隔符是双引号
print(" ".join(lst))
print("\n".join(lst))
lst = ['1',['a','b'],'3']
print(" ".join(lst))

输出:
1"2"3
1 2 3
1
2
3
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test2.py", line 6, in <module>
    print(" ".join(lst))
          ~~~~~~~~^^^^^
TypeError: sequence item 1: expected str instance, list found

字符串+连接

  • + -> str
    将2个字符串连接在一起
    返回一个新字符串

a = "1" + "2";

print(a)

输出:
12

字符串分割

  • 分割字符串的方法分为2类
            split系
                    partition系
            将字符串按照分隔符分割成若干字符串,并返回列表
                    将字符串按照分隔符分割成2段,返回这2段和分隔符的元组

  • split(sep=None, maxsplit=-1) -> list of strings
    从左至右
    sep 指定分割字符串,缺省的情况下空白字符串作为分隔符
    maxsplit 指定分割的次数,-1 表示遍历整个字符串

s1 = "I'm \ta super student."
print(s1.split())
print(s1.split('s'))
print(s1.split('super'))
print(s1.split('super '))
print(s1.split(' '))
print(s1.split(' ',maxsplit=2))
print(s1.split('\t',maxsplit=2))


输出:
["I'm", 'a', 'super', 'student.']
["I'm \ta ", 'uper ', 'tudent.']
["I'm \ta ", ' student.']
["I'm \ta ", 'student.']
["I'm", '\ta', 'super', 'student.']
["I'm", '\ta', 'super student.']
["I'm ", 'a super student.']


  • rsplit(sep=None, maxsplit=-1) -> list of strings
    从右向左
    sep 指定分割字符串,缺省的情况下空白字符串作为分隔符
    maxsplit 指定分割的次数,-1 表示遍历整个字符串
s1 = "I'm \ta super student."
print(s1.rsplit())
print(s1.rsplit('s'))
print(s1.rsplit('super'))
print(s1.rsplit('super '))
print(s1.rsplit(' '))
print(s1.rsplit(' ',maxsplit=2))
print(s1.rsplit('\t',maxsplit=2))


输出:
["I'm", 'a', 'super', 'student.']
["I'm \ta ", 'uper ', 'tudent.']
["I'm \ta ", ' student.']
["I'm \ta ", 'student.']
["I'm", '\ta', 'super', 'student.']
["I'm \ta", 'super', 'student.']
["I'm ", 'a super student.']

  • splitlines([keepends]) -> list of strings
    按照行来切分字符串
    keepends 指的是是否保留行分隔符
    行分隔符包括\n、\r\n、\r等
'ab c\n\nde fg\rkl\r\n'.splitlines()
'ab c\n\nde fg\rkl\r\n'.splitlines(True)
s1 = '''I'm a super student.
You're a super teacher.'''
print(s1)
print(s1.splitlines())
print(s1.splitlines(True))


输出:
I'm a super student.
You're a super teacher.
["I'm a super student.", "You're a super teacher."]
["I'm a super student.\n", "You're a super teacher."]
  • partition(sep) -> (head, sep, tail)
    从左至右,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组;如果没有找到分隔符,就返回头、2个空元素的三元组
    sep 分割字符串,必须指定
s1 = "I'm a super student."
print(s1.partition('s'))
print("==============")
print(s1.partition('stu'))
print("*********************")
print(s1.partition(''))
print("------------------------")
print(s1.partition('abc'))


输出:


("I'm a ", 's', 'uper student.')
==============
("I'm a super ", 'stu', 'dent.')
*********************
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test2.py", line 6, in <module>
    print(s1.partition(''))
          ~~~~~~~~~~~~^^^^
ValueError: empty separator
  • rpartition(sep) -> (head, sep, tail)
    从右至左,遇到分隔符就把字符串分割成两部分,返回头、分隔符、尾三部分的三元组;如果没有找到分隔符,就返回2个空元素和尾的三元组

字符串大小写

  • upper()
    全大写
  • lower()
  • 全小写
  • 大小写,做判断的时候用
  • swapcase()
    交互大小写

字符串排版

  • title() -> str
    标题的每个单词都大写
  • capitalize() -> str
             首个单词大写
  • center(width[, fillchar]) -> str
             width 打印宽度
             fillchar 填充的字符
  • zfill(width) -> str
             width 打印宽度,居右,左边用0填充
  • ljust(width[, fillchar]) -> str 左对齐
  • rjust(width[, fillchar]) -> str 右对齐
  • 中文用的少,了解一下

字符串修改

  • replace(old, new[, count]) -> str
    字符串中找到匹配替换为新子串,返回新字符串
    count表示替换几次,不指定就是全部替换
print('www.magedu.com'.replace('w','p'))
print('www.magedu.com'.replace('w','p',2))
print('www.magedu.com'.replace('w','p',3))
print('www.magedu.com'.replace('ww','p',2))
print('www.magedu.com'.replace('www','python',2))

输出:
ppp.magedu.com
ppw.magedu.com
ppp.magedu.com
pw.magedu.com
python.magedu.com

字符串修改

  • strip([chars]) -> str
    从字符串两端去除指定的字符集chars中的所有字符
    如果chars没有指定,去除两端的空白字符
s = "\r \n \t Hello Python \n \t"
print(s.strip())
s = " I am very very very sorry "
print(s.strip('Iy'))
print(s.strip('Iy '))


输出:
Hello Python
 I am very very very sorry 
am very very very sorr
  • lstrip([chars]) -> str
    从左开始
  • rstrip([chars]) -> str
    从右开始

字符串查找

  • find(sub[, start[, end]]) -> int
            在指定的区间[start, end),从左至右,查找子串sub。找到返回索引,没找到返回-1
  • rfind(sub[, start[, end]]) -> int
            在指定的区间[start, end),从右至左,查找子串sub。找到返回索引,没找到返回-1
s = "I am very very very sorry"
print(s.find('very'))
print(s.find('very', 5))
print(s.find('very', 6, 13))
print(s.rfind('very', 10))
print(s.rfind('very', 10, 15))
print(s.rfind('very',-10,-1))


输出:


5
5
-1
15
10
15

  • index(sub[, start[, end]]) -> int
            在指定的区间[start, end),从左至右,查找子串sub。找到返回索引,没找到抛出异常ValueError
  • rindex(sub[, start[, end]]) -> int
            在指定的区间[start, end),从左至右,查找子串sub。找到返回索引,没找到抛出异常ValueError
s = "I am very very very sorry"
print(s.index('very'))
print("="*60)
print(s.index('very', 5))
print("*"*60)
print(s.index('very', 6, 13))
print("-"*60)
print(s.rindex('very', 10))
print("|"*60)
print(s.rindex('very', 10, 15))
print("/")
print(s.rindex('very',-10,-1))


输出:
5
============================================================
5
************************************************************
Traceback (most recent call last):
  File "/Users/quyixiao/pp/python_lesson/jk/zhushi/test2.py", line 6, in <module>
    print(s.index('very', 6, 13))
          ~~~~~~~^^^^^^^^^^^^^^^
ValueError: substring not found

  • 时间复杂度
    index和count方法都是O(n)
    随着列表数据规模的增大,而效率下降

  • len(string)
    返回字符串的长度,即字符的个数

  • count(sub[, start[, end]]) -> int
    在指定的区间[start, end),从左至右,统计子串sub出现的次数

s = "I am very very very sorry"
print(s.count('very'))
print(s.count('very', 5))
print(s.count('very', 10, 14))

输出:
3
3
1

字符串判断

  • endswith(suffix[, start[, end]]) -> bool
            在指定的区间[start, end),字符串是否是suffix结尾
  • startswith(prefix[, start[, end]]) -> bool
            在指定的区间[start, end),字符串是否是prefix开头
s = "I am very very very sorry"
print(s.startswith('very'))
print(s.startswith('very', 5))
print(s.startswith('very', 5, 9))
print(s.endswith('very', 5, 9))
print(s.endswith('sorry', 5))
print(s.endswith('sorry', 5, -1))
print(s.endswith('sorry', 5, 100))

输出:
False
True
True
True
True
False
True

字符串判断 is系列

  • isalnum() -> bool 是否是字母和数字组成
  • isalpha() 是否是字母
  • isdecimal() 是否只包含十进制数字
  • isdigit() 是否全部数字(0~9)
  • isidentifier() 是不是字母和下划线开头,其他都是字母、数字、下划线
  • islower() 是否都是小写
  • isupper() 是否全部大写
  • isspace() 是否只包含空白字符

字符串格式化

  • 字符串的格式化是一种拼接字符串输出样式的手段,更灵活方便
            join拼接只能使用分隔符,且要求被拼接的是可迭代对象
            + 拼接字符串还算方便,但是非字符串需要先转换为字符串才能拼接

  • 在2.5版本之前,只能使用printf style风格的print输出
            printf-style formatting,来自于C语言的printf函数
            格式要求
            占位符:使用%和格式字符组成,例如%s、%d等
            s调用str(),r会调用repr()。所有对象都可以被这两个转换。
            占位符中还可以插入修饰字符,例如%03d表示打印3个位置,不够前面补零
            format % values,格式字符串和被格式的值之间使用%分隔
            values只能是一个对象,或是一个和格式字符串占位符数目相等的元组,或一个字典

  • printf-style formatting 举例

print("I am %03d" % (20,))
print('I like %s.' % 'Python')
print('%3.2f%% , 0x%x, 0X%02X' % (89.7654, 10, 15))
print("I am %-5d" % (20,))

输出:

I am 020
I like Python.
89.77% , 0xa, 0X0F
I am 20 
  • format函数格式字符串语法——Python鼓励使用
    “{} {xxx}”.format(*args, **kwargs) -> str
    args是位置参数,是一个元组
    kwargs是关键字参数,是一个字典
    花括号表示占位符
    {}表示按照顺序匹配位置参数,{n}表示取位置参数索引为n的值
    {xxx}表示在关键字参数中搜索名称一致的
    {{}} 表示打印花括号

  • 位置参数
    “{}:{}”.format(‘192.168.1.100’,8888),这就是按照位置顺序用位置参数替换前面的格式字符串的占位符中

  • 关键字参数或命名参数
    “{server} {1}:{0}”.format(8888, ‘192.168.1.100’, server='Web Server Info : ') ,位置参数按照序号匹配,
    关键字参数按照名词匹配

  • 访问元素
    “{0[0]}.{0[1]}”.format((‘magedu’,‘com’))

  • 对象属性访问

from collections import namedtuple
Point = namedtuple('Point','x y')
p = Point(4,5)
print("{{{0.x},{0.y}}}".format(p))

输出:
{4,5}

  • 对齐
print('{0}*{1}={2:<2}'.format(3,2,2*3))
print('{0}*{1}={2:<02}'.format(3,2,2*3))
print('{0}*{1}={2:>02}'.format(3,2,2*3))
print('{:^30}'.format('centered'))
print('{:*^30}'.format('centered'))

输出:

3*2=6 
3*2=60
3*2=06
           centered           
***********centered***********
  • 进制
print("int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}".format(42))
print("int: {0:d}; hex: {0:#x}; oct: {0:#o}; bin: {0:#b}".format(42))
octets = [192, 168, 0, 1]
print('{:02X}{:02X}{:02X}{:02X}'.format(*octets))
输出:
int: 42; hex: 2a; oct: 52; bin: 101010
int: 42; hex: 0x2a; oct: 0o52; bin: 0b101010
C0A80001

bytes、bytearray

  • Python3引入两个新类型
             bytes
                     不可变字节序列
             bytearray
                     字节数组
                     可变

  • 字符串与bytes
    字符串是字符组成的有序序列,字符可以使用编码来理解
    bytes是字节组成的有序的不可变序列
    bytearray是字节组成的有序的可变序列

  • 编码与解码
    字符串按照不同的字符集编码encode返回字节序列bytes
             encode(encoding=‘utf-8’, errors=‘strict’) -> bytes
    字节序列按照不同的字符集解码decode返回字符串
             bytes.decode(encoding=“utf-8”, errors=“strict”) -> str
             bytearray.decode(encoding=“utf-8”, errors=“strict”) -> str

ASCII

        ASCIl ( American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套单字节编码系统

在这里插入图片描述

bytes定义

  • 定义
    bytes() 空bytes
    bytes(int) 指定字节的bytes,被0填充
    bytes(iterable_of_ints) -> bytes [0,255]的int组成的可迭代对象
    bytes(string, encoding[, errors]) -> bytes 等价于string.encode()
    bytes(bytes_or_buffer) -> immutable copy of bytes_or_buffer 从一个字节序列或者buffer复制出
            一个新的不可变的bytes对象
    使用b前缀定义
            只允许基本ASCII使用字符形式b’abc9’
            使用16进制表示b"\x41\x61"

bytes操作

  • 和str类型类似,都是不可变类型,所以方法很多都一样。只不过bytes的方法,输入是bytes,输出是
    bytes
    b’abcdef’.replace(b’f’,b’k’)
    b’abc’.find(b’b’)
  • 类方法 bytes.fromhex(string)
    string必须是2个字符的16进制的形式,‘6162 6a 6b’,空格将被忽略
    bytes.fromhex(‘6162 09 6a 6b00’)
  • hex()
    返回16进制表示的字符串
    ‘abc’.encode().hex()
  • 索引
    b’abcdef’[2] 返回该字节对应的数,int类型

bytearray定义

  • 定义
    bytearray() 空bytearray
    bytearray(int) 指定字节的bytearray,被0填充
    bytearray(iterable_of_ints) -> bytearray [0,255]的int组成的可迭代对象
    bytearray(string, encoding[, errors]) -> bytearray 近似string.encode(),不过返回可变对象
    bytearray(bytes_or_buffer) 从一个字节序列或者buffer复制出一个新的可变的bytearray对象
    注意,b前缀定义的类型是bytes类型

bytearray操作

  • 和bytes类型的方法相同
    bytearray(b’abcdef’).replace(b’f’,b’k’)
    bytearray(b’abc’).find(b’b’)

  • 类方法 bytearray.fromhex(string)
    string必须是2个字符的16进制的形式,‘6162 6a 6b’,空格将被忽略
    bytearray.fromhex(‘6162 09 6a 6b00’)

  • hex()
    返回16进制表示的字符串
    bytearray(‘abc’.encode()).hex()

  • 索引
    bytearray(b’abcdef’)[2] 返回该字节对应的数,int类型

  • append(int) 尾部追加一个元素

  • insert(index, int) 在指定索引位置插入元素

  • extend(iterable_of_ints)将一个可迭代的整数集合追加到当前bytearray

  • pop(index=-1) 从指定索引上移除元素,默认从尾部移除口 remove(value) 找到第一个value移除,找不到抛 ValueError异常

  • 注意:上述方法若需要使用int类型,值在[0,255]

  • clear() 清空bytearray

  • reverse()翻转bytearray,就地修改

b = bytearray()
b.append (97)
print('append_97:',b)

b.append(99)
print('append_99:',b)

b.insert (1,98)
print('insert:',b)

b.extend ([65,66,67])
print('extend:',b)
b.remove(66)
print('remove_66:',b)

print(b.pop())

b.reverse()
print('reverse:',b)


b.clear()
print(b)


输出:

append_97: bytearray(b'a')
append_99: bytearray(b'ac')
insert: bytearray(b'abc')
extend: bytearray(b'abcABC')
remove_66: bytearray(b'abcAC')
67
reverse: bytearray(b'Acba')
bytearray(b'')

切片

线性结构

  • 线性结构
    可迭代 for … in
    len()可以获取长度
    通过下标可以访问
    可以切片
  • 学过的线性结构
    列表、元组、字符串、bytes、bytearray

切片

  • 通过索引区间访问线性结构的一段数据
  • sequence[start:stop] 表示返回[start, stop)区间的子序列
  • 支持负索引
  • start为0,可以省略
  • stop为末尾,可以省略
  • 超过上界(右边界),就取到末尾;超过下界(左边界),取到开头
  • start一定要在stop的左边
  • [:] 表示从头至尾,全部元素被取出,等效于copy()方法

切片举例

print('www.magedu.com'[4:10])                      # magedu
print('www.magedu.com'[:10])                      # www.magedu
print('www.magedu.com'[4:])                      # magedu.com
print('www.magedu.com'[:])                      # www.magedu.com
print('www.magedu.com'[:-1])                      # www.magedu.co
print('www.magedu.com'[4:-4])                      # magedu
print('www.magedu.com'[4:50])                      # magedu.com
print(b'www.magedu.com'[-40:10])                      # b'www.magedu'
print(bytearray(b'www.magedu.com')[-4:10])                      # bytearray(b'')
print(tuple('www.magedu.com')[-10:10])                      # ('m', 'a', 'g', 'e', 'd', 'u')
print(list('www.magedu.com')[-10:-4])                      # ['m', 'a', 'g', 'e', 'd', 'u']
  • 步长切片
    [start:stop:step]
    step为步长,可以正、负整数,默认是1
    step要和start:stop同向,否则返回空序列
print('www.magedu.com'[4:10:2])    # mgd
print(list('www.magedu.com')[4:10:-2])    # []
print(tuple('www.magedu.com')[-10:-4:2])    # ('m', 'g', 'd')
print(b'www.magedu.com'[-4:-10:2])    # b''
print(bytearray(b'www.magedu.com')[-4:-10:-2])    # bytearray(b'.dg')

数字统计

随机产生10个数字要求:
每个数字取值范围[1,20]
统计重复的数字有几个?分别是什么?
统计不重复的数字有几个?分别是什么?
举例:11,7.5,11,6, 7.4,其中2个数字7和11重复了,3个数字4、5、6没有重复过

思路:
对于一个排序的序列,相等的数字会挨在一起。但是如果先排序,还是要花时间,能否不排序解决?
例如11,7,5,11,6,7,4,先拿出11,依次从第二个数字开始比较,发现11就把对应索引标记,这样
一趟比较就知道11是否重复,哪些地方重复。第二趟使用7和其后数字依次比较,发现7就标记, 当遇到以前比较过的11的位置的时候,其索引已经被标记为1,直接跳过。

import random

nums = []

for _ in range(10):
    nums.append(random.randrange(21))

# nums = [1,22,33, 56, 56,22,4,56, 9,56,2,1]

print("Origin numbers = {}".format(nums))
print()

length = len(nums)

samenums = []  # 记录相同的数字

diffnums = []  # 记录不同的数字

states = [0] * length  # 记录不同的索引异同状态

for i in range(length):

    flag = False  # 假定没有重复
    if states[i] == 1:
        continue

    for j in range(i + 1, length):

        if states[j] == 1:
            continue

        if nums[i] == nums[j]:
            flag = True

            states[j] = 1

    if flag:  # 有重复

        samenums.append(nums[i])

        states[i] = 1


    else:

        diffnums.append(nums[i])

print("Same numbers = {1}, Counter = {0}".format(len(samenums), samenums))
print("Different numbers = {1}, Counter = {0}".format(len(diffnums), diffnums))
print(list(zip(states, nums)))