前言:由于已经有一定的写c和cpp的经验,觉得看文字学可能更快一点,所以看菜鸟教程加上做CS61A(24Fall)的作业和看它的textbook来学。持续更新喵

Python基础知识

Python3解释器

如何在终端启动python

1
2
3
$ PATH=$PATH:/usr/local/python3/bin/python3 #设环境变量   
$ python3 --version
Python 3.4.0
1
set path=%path%;C:\python34
  • 什么叫环境变量:存储了电脑需要的常用信息,其中PATH(in Unix/Linux)或者Path(in Windows)是最常用的,储存的是文件路径(一系列),每当我们执行一些可执行文件的时候,电脑就根据这些路径来找我们的文件,可以避免我们输入文件完整路径的麻烦
  • Unix/Linux的区别:Unix是付费的,Linux是开源的,且有Ubuntu之类的发行版

脚本式编程

  • Interpreted language: 一个典型特征就是脚本式编程
  • Compiled language
  • 脚本式编程就是不需要编译,可以像一段脚本一样,写一点运行一点

交互模式

  • 终端运行python3开启
  • 在交互模式中,最后被输出的表达式结果被赋值给变量 _,这是一个只读变量

#!

  • #!/usr/bin/python3 这行代码被称为 Shebang (或者 Hashbang)。它在 Linux、macOS 等类 Unix 系统中扮演着非常重要的角色,它的作用是告诉操作系统,当这个脚本文件被直接执行时,应该使用哪个解释器来运行它。
    具体来说:
  • #! 是一个特殊的组合,它告诉系统这是一个Shebang。
  • /usr/bin/python3 是指定解释器的路径。这意味着操作系统会去 /usr/bin/ 目录下找到名为 python3 的可执行程序来运行这个脚本。

Python3运算符

Walrus Operator(海象运算符)

1
2
3
4
5
6
7
8
# 传统写法
n = 10
if n > 5:
print(n)

# 使用海象运算符
if (n := 10) > 5:
print(n)

逻辑运算符(和c不同)

  • and
    • 在 Python 中,and 运算符会从左到右评估其操作数。
    • 如果左侧操作数在布尔上下文中为 False,那么 and 运算符就会立即停止评估,并返回左侧操作数的值,而不会去评估右侧操作数。
    • 如果左侧操作数在布尔上下文中为 True,那么 and 运算符会继续评估右侧操作数,并返回右侧操作数的值
  • or
    • or 运算符从左到右评估其操作数。
    • 如果左侧操作数在布尔上下文中为 True,那么 or 运算符就会立即停止评估,并返回左侧操作数的值,而不会去评估右侧操作数。
    • 如果左侧操作数在布尔上下文中为 False,那么 or 运算符会继续评估右侧操作数,并返回右侧操作数的值
    • 这里注意如果某一测的操作数是一个expression,那么返回值是True或者False
  • not
    • True返回False
    • False返回True

成员运算符

  • in
  • not in

身份运算符

  • 判断两个标识符(变量)是不是引用自同一个对象,返回布尔值
  • is
  • is not
1
2
x is y -> id(x)==id(y)
x is not y -> id(x)!=id(y)

字符串运算符

  • r/R:原始字符串:所有的字符串都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符

Python基础语法

Pass 语句

  • Python pass是空语句,是为了保持程序结构的完整性。
  • pass 不做任何事情,一般用做占位语句

Python3转义字符

  • 续行符\
  • 响铃\a
1
2
>>> print("\a") 
# 执行之后电脑有响声
  • \000
  • 退格(Backspace)\b
1
2
>>> print("Hello \b World!")
Hello World!
  • 纵向制表符\v
1
2
3
4
>>> print("Hello \v World!")
Hello
World!
>>>
  • 横向制表符\t
1
2
3
>>> print("Hello \t World!")
Hello World!
>>>
  • 回车\r,将 \r 后面的内容移到字符串开头,并逐一替换开头部分的字符,直至将 \r 后面的内容完全替换完成。
1
2
3
4
>>> print("Hello\rWorld!")
World!
>>> print('google runoob taobao\r123456')
123456 runoob taobao
  • print() 语句中遇到 \f 这个特殊字符时,它会导致输出在 \f 所在的位置换行,并且新行会有一个缩进(模拟“新页”的效果)
  • \yyy:八进制数,y 代表 0~7 的字符,例如:\012 代表换行。
  • \xyy:十六进制数,以 \x 开头,y 代表的字符,例如:\x0a 代表换行

f-string

  • f-string用来格式化字符串,f stands for format
  • f-string 格式化字符串以 f 开头,后面跟着字符串(用引号包裹),字符串中的表达式用大括号 {} 包起来,它会将变量或表达式计算后的值替换进去
1
2
3
4
5
6
7
8
9
>>> name = 'Runoob'
>>> f'Hello {name}' # 替换变量
'Hello Runoob'
>>> f'{1+2}' # 使用表达式
'3'

>>> w = {'name': 'Runoob', 'url': 'www.runoob.com'}
>>> f'{w["name"]}: {w["url"]}'
'Runoob: www.runoob.com'
  • 用等号拼接
1
2
3
4
5
6
7
>>> x = 1
>>> print(f'{x+1}') # Python 3.6
2

>>> x = 1
>>> print(f'{x+1=}') # Python 3.8
x+1=2

数据结构

列表

  • 什么是列表
    • 列表是最常用的 Python 数据类型,它可以作为一个方括号内的逗号分隔值出现。
    • 列表的数据项不需要具有相同的类型
    • 创建一个列表,只要把逗号分隔的不同的数据项使用方括号括起来即可
    • 列表的元素是可变的
  • 索引
    • 索引可以从尾部开始,最后一个元素的索引为 -1,往前一位为 -2
    • 使用方括号 [ ] 的形式截取字符,左闭右开
  • 更新列表
    • append
    • del
    • list() 是一个内置函数,它接收一个可迭代对象(iterable)作为参数,并将其所有元素收集起来,创建一个新的**list
  • 列表可以像字符串一样用+ *等操作符进行拼接和重复
  • 列表可以嵌套
  • 列表可以比较是否相等,使用eqmethod

元组(Tuple)

  • 什么是元组
    • Python 的元组与列表类似,不同之处在于元组的元素不能修改。
    • 元组使用小括号 ( ),列表使用方括号 [ ]。
1
2
3
4
5
6
7
8
9
10
>>> tup1 = ('Google''Runoob'19972000)  
>>> tup3 = "a""b""c""d"   #  不需要括号也可以
>>> tup1 = () # 创建空tuple
>>> tup1 = (50)
>>> type(tup1) # 不加逗号,类型为整型
<class 'int'>

>>> tup1 = (50,)
>>> type(tup1) # 加上逗号,类型为元组
<class 'tuple'>
  • 更新
    • 元组中的元素值是不允许删除的,但我们可以使用del语句来删除整个元组
  • 关于元组不可变:所谓元组的不可变指的是元组所指向的内存中的内容不可变
1
2
3
4
5
6
7
8
9
10
>>> tup = ('r', 'u', 'n', 'o', 'o', 'b')
>>> tup[0] = 'g' # 不支持修改元素
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
>>> id(tup) # 查看内存地址
4440687904
>>> tup = (1,2,3)
>>> id(tup)
4441088800 # 内存地址不一样了

Dictionary

  • 什么是字典
    • 字典是一种可变容器模型,且可存储任意类型对象。
    • 字典的每个键值 key=>value 对用冒号分割,每个对之间用逗号分割,整个字典包括在花括号 {} 
    • 键必须是唯一的,但值则不必。
    • 值可以取任何数据类型,但键必须是不可变的,如字符串,数字。
  • 更新
    • 创建:
      • 使用大括号 { } 创建
      • 用`dict()
      • 不允许同一个键出现两次。创建时如果同一个键被赋值两次,后一个值会被记住
      • 键必须不可变,所以可以用数字,字符串或元组充当,而用列表就不行
    • 索引:
      • 对于特定key重新赋值,可以直接修改key对应的value
      • 用del,可以直接删除一个key和它对应的value
      • 用del,可以直接删除一个字典
      • clear()可以清空字典
  • 内置方法
    • str(dict)将字典以可以打印的字符串表示输出

Set

  • 什么是集合
    • 集合(set)是一个无序的不重复元素序列,如果定义的时候写了重复的元素,print的时候会自动去重
  • 创建
    • 可以使用大括号 { } 创建集合,元素之间用逗号 , 分隔, 或者也可以使用set()函数创建集合
    • 创建一个空集合必须用 set() 而不是 { },因为 { } 是用来创建一个空字典
  • 运算
    • 集合可以和数学里的集合一样,进行求差集-,交集&,并集|
  • 方法
    • s.add( x )
    • s.update( x )
    • s.remove( x )如果x不存在会报错
    • s.discard( x ) x不存在 也不会报错
    • s.pop()随机删除一个:对集合进行无序的排列,然后将这个无序排列集合的左面第一个元素进行删除

Python Comprehension(推导式)

  • Python支持各种数据结构的推导式
    • 列表(list)推导式
    • 字典(dict)推导式
    • 集合(set)推导式
    • 元组(tuple)推导式
  • 什么是推导式
    • Describes the elements in a container and evaluates to a new container containing those elements.

List Comprehension

  • 创建
1
2
[<expression> for <element> in <sequence>]
[<expression> for <element> in <sequence> if <conditional>]
eg
1
2
>>> [i*i for i in [1, 2, 3, 4] if i % 2 == 0] 
[4, 16]
  • 这里的sequence可以是一个已经存在的list,也可以使用range创建的数组

Dictionary Comprehension

1
2
3
>>> dic = {x: x**2 for x in (2, 4, 6)}
>>> dic
{2: 4, 4: 16, 6: 36}

Set Comprehension

1
2
3
>>> setnew = {i**2 for i in (1,2,3)}
>>> setnew
{1, 4, 9}

Tuple Comprehension

1
2
3
4
5
6
>>> a = (x for x in range(1,10))
>>> a
<generator object <genexpr> at 0x7faf6ee20a50> # 返回的是生成器对象

>>> tuple(a) # 使用 tuple() 函数,可以直接将生成器对象转换成元组
(1, 2, 3, 4, 5, 6, 7, 8, 9)

函数

嵌套函数

  • 函数可以嵌套定义,当执行外部函数的时候,内部函数只会被定义,不会被执行
  • print字符串时,不会print引号,但如果return一个字符串,会打印出引号

Higher-Order Function

在 Python(以及许多其他函数式编程语言,如 JavaScript、Scala 等)中,高阶函数是指满足以下任一两者兼备条件的函数:

  1. 接受一个或多个函数作为参数
  2. 返回一个函数作为结果
    简单来说,就是函数的参数可以是函数,或者函数的返回值可以是函数
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
def cycle(f1, f2, f3):

    """Returns a function that is itself a higher-order function.



    >>> def add1(x):

    ...     return x + 1

    >>> def times2(x):

    ...     return x * 2

    >>> def add3(x):

    ...     return x + 3

    >>> my_cycle = cycle(add1, times2, add3)

    >>> identity = my_cycle(0)

    >>> identity(5)

    5

    >>> add_one_then_double = my_cycle(2)

    >>> add_one_then_double(1)

    4

    >>> do_all_functions = my_cycle(3)

    >>> do_all_functions(2)

    9

    >>> do_more_than_a_cycle = my_cycle(4)

    >>> do_more_than_a_cycle(2)

    10

    >>> do_two_cycles = my_cycle(6)

    >>> do_two_cycles(1)

    19

    """

    "*** YOUR CODE HERE ***"

    def final(n):

        def value(x):

            result = x

            function = [f1,f2,f3]

            for i in range(n):

                result = function[i%3](result)

            return result

        return value

    return final

Pure function and Non-pure function

  • Pure functions: applying them has no effects beyond returning a value. Moreover, a pure function must always return the same value when called twice with the same arguments.
  • Non-pure functions: In addition to returning a value, applying a non-pure function can generate side effects, which make some change to the state of the interpreter or computer
    • eg: The print function returns Nonebut prints some value to the console

Lambda Expressions

  • Lambda表达式就可以不用为函数起名字
1
2
     lambda            x            :          f(g(x))
"A function that takes x and returns f(g(x))"
  • Compound Lambda expressions are illegible
  • Lambda expression returns a function

Python3数学函数

  1. (x>y)-(x<y):如果 x < y 返回 -1, 如果 x == y 返回 0, 如果 x > y 返回 1
  2. exp(x):返回e的x次幂
  3. fabs(x):以浮点数形式返回数字的绝对值,如math.fabs(-10) 返回10.0
  4. modf(x):返回x的整数部分与小数部分,两部分的数值符号与x相同,整数部分以浮点型表示。
1
2
3
4
5
6
7
8
import math
x = 3.75
# 调用 modf
fractional_part, integral_part = math.modf(x)

print(f"原始数 x: {x}")
print(f"小数部分: {fractional_part}") # 输出 0.75
print(f"整数部分: {integral_part}") # 输出 3.0 (注意,是浮点型表示)

Python3随机数函数

  1. choice(seq):从非空的序列(如列表、元组、字符串)的元素中随机挑选一个元素。
  2. randrange([start,] stop [,step]):从指定范围内,按指定步长递增的集合中获取一个随机整数。如果只提供 stop,则范围是 0stop-1。步长 step 默认值为 1
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    import random
    # 从 0 到 9 中随机选一个整数 (0, 1, ..., 9)
    num1 = random.randrange(10)
    print(f"从 0-9 中随机选择: {num1}") # 每次运行可能不同,如 4

    # 从 5 到 9 中随机选一个整数 (5, 6, ..., 9)
    num2 = random.randrange(5, 10)
    print(f"从 5-9 中随机选择: {num2}") # 每次运行可能不同,如 8

    # 从 1 到 10 之间,只选择奇数 (1, 3, 5, 7, 9)
    num3 = random.randrange(1, 11, 2)
    print(f"从 1-10 的奇数中选择: {num3}") # 每次运行可能不同,如 3
  3. random():随机生成下一个实数(浮点数),它的值在 [0.0, 1.0) 范围内,即大于等于 0.0 但小于 1.0。
  4. seed([x]):** 改变随机数生成器的种子(seed)。Python 会自动选择一个种子(通常基于系统时间)。
  5. shuffle(lst):** 将序列(通常是列表)的所有元素进行随机“洗牌”或打乱顺序,原地修改原序列。
1
2
3
4
5
6
7
8
9
10
import random

my_list = [1, 2, 3, 4, 5, 6, 7]
print(f"原始列表: {my_list}")

random.shuffle(my_list) # 原地打乱列表
print(f"打乱后的列表1: {my_list}") # 每次运行不同,如 [6, 4, 1, 7, 3, 5, 2]
# 注意:shuffle 只能用于可变序列(如列表),不能用于元组或字符串
# my_tuple = (1, 2, 3)
# random.shuffle(my_tuple) # 会报错 TypeError
  1. uniform(x, y):** 随机生成下一个实数(浮点数),它的值在 [x, y] 范围内,即大于等于 x 且小于等于 y。与 random() 不同,uniform() 允许你指定任意的上下限。

Range

  • range(start, stop) 是一个函数,它会生成一个从 start 开始,到 stop - 1 结束的整数序列
  • range() 函数返回的不是一个列表,而是一个 range 对象。
  • range 对象 是一种可迭代对象(iterable),它lazily生成数字。这意味着它不会一次性把所有的数字都存储在内存中,而是在你需要的时候(比如在 for 循环中),才一个一个地提供这些数字。这种特性使得 range 在处理非常大的数字序列时非常高效和节省内存

Recursion

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
def double_eights(n):

    """Returns whether or not n has two digits in row that

    are the number 8.



    >>> double_eights(1288)

    True

    >>> double_eights(880)

    True

    >>> double_eights(538835)

    True

    >>> double_eights(284682)

    False

    >>> double_eights(588138)

    True

    >>> double_eights(78)

    False

    >>> # ban iteration

    >>> from construct_check import check

    >>> check(LAB_SOURCE_FILE, 'double_eights', ['While', 'For'])

    True

    """

    "*** YOUR CODE HERE ***"

    if n < 10 :

        return False

    if n % 10 == 8 and (n // 10) %10 ==8:

        return True

    return double_eights(n // 10)
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
def make_onion(f, g):

    """Return a function can_reach(x, y, limit) that returns

    whether some call expression containing only f, g, and x with

    up to limit calls will give the result y.



    >>> up = lambda x: x + 1

    >>> double = lambda y: y * 2

    >>> can_reach = make_onion(up, double)

    >>> can_reach(5, 25, 4)      # 25 = up(double(double(up(5))))

    True

    >>> can_reach(5, 25, 3)      # Not possible

    False

    >>> can_reach(1, 1, 0)      # 1 = 1

    True

    >>> add_ing = lambda x: x + "ing"

    >>> add_end = lambda y: y + "end"

    >>> can_reach_string = make_onion(add_ing, add_end)

    >>> can_reach_string("cry", "crying", 1)      # "crying" = add_ing("cry")

    True

    >>> can_reach_string("un", "unending", 3)     # "unending" = add_ing(add_end("un"))

    True

    >>> can_reach_string("peach", "folding", 4)   # Not possible

    False

    """

    def can_reach(x, y, limit):

        if limit < 0:

            return False

        elif x == y:

            return True

        else:

            return can_reach(f(x), y, limit - 1) or can_reach(g(x), y, limit - 1)

    return can_reach

Iterator(迭代器)

  • iter()创建一个迭代器,可以对于string,list,tuple创建
  • next()可以指向下一个元素
    例子
1
2
3
4
5
6
7
>>> list=[1,2,3,4]
>>> it = iter(list) # 创建迭代器对象
>>> print (next(it)) # 输出迭代器的下一个元素
1
>>> print (next(it))
2
>>>

遍历方法

1
2
3
4
5
#!/usr/bin/python3
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
for x in it:
print (x, end=" ")

或者

1
2
3
4
5
6
7
8
9
#!/usr/bin/python3
import sys # 引入 sys 模块
list=[1,2,3,4]
it = iter(list) # 创建迭代器对象
while True:
try:
print (next(it))
except StopIteration:
sys.exit()
  • 自定义iterator
    • 可迭代对象(Iterable):一个对象如果可以for 循环遍历,那么它就是可迭代的,或者说如果它实现了 __iter__() method,并且该method返回一个迭代器,那这个object就是iterable
    • 迭代器(Iterator):如果一个对象同时实现了 __iter__()__next__() 方法就是迭代器,它能够实现
      • __iter__() 方法必须返回 self(即迭代器自身)。
      • __next__() 方法返回序列中的下一个元素,并在没有更多元素时抛出 StopIteration
    • 我们可以创建一个class,然后完成他的__next__()__iter__() 方法,就可以把这个类当作迭代器来用
      例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class MyNumbers:
def __iter__(self):
self.a = 1
return self

def __next__(self):
x = self.a
self.a += 1
return x

myclass = MyNumbers()
myiter = iter(myclass)

print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
print(next(myiter))
  • StopIteration
    • StopIteration 异常用于标识迭代的完成,防止出现无限循环的情况,在 next() 方法中我们可以设置在完成指定循环次数后触发 StopIteration 异常来结束迭代。

Generator(生成器)

  • 使用了 yield 的函数被称为生成器(generator),是一种特殊的函数
  • 生成器函数可以在迭代过程中逐步产生值,而不是一次性返回所有结果,它会返回一个Iterator object。生成器只有在你真正需要下一个值时,才会计算并产生它,这被称为“惰性求值”