Loading

【啃书】Python数据结构与算法分析(第二版)---导论

前言

算法

  • 计算机科学的研究对象是问题、解决问题的过程,以及通过该过程得到的解决方案。给定一个问题,计算机科学家的目标是开发一个能够解决该问题的算法。算法是具有有限步骤的过程,依照这个过程便能解决问题。因此算法就是解决方案

计算机科学

  • 定义一:研究问题及解决方案,以及研究目前无解的问题的学科。
  • 定义二:在描述问题及解决方案时,经常会用“可计算”一次。因此计算机科学也可以定义为:研究可计算以及不可计算的问题,即研究算法的存在性以及不存在性。

抽象

  • 所谓抽象,就是将具体的问题,使用逻辑思维,将之提炼出来。举个例子,下面这个计算开平方的函数,别人已经实现了解决方案,我们只需要调用被人写好的接口:函数名,所需参数,了解返回值就可以用了。所有的计算细节都被隐藏起来了。

编程

  • 编程是指通过编程语言将算法编码以使其能被计算机执行的过程。

为何学习算法

  • 虽然解决问题的方案有很多,但总有一个较其他在内存上、效率上更好的策略,学习算法的意义就在于比较这些算法,学会分析技巧。

Python基础

  • 面向对象的编程语言、解释型语言。动态语言。

数据类型

  • 内建原子数据类型(int、float、bool)

    • 整数类型int、浮点型数据float

      标准数学运算符:+、-、*、/、以及**(幂运算)、%(取余)、//(整除)

    • 布尔数据bool

      布尔对象可能的状态值是True、False。布尔运算符:and、or、not。
      布尔运算也被用于等于(==)、大于(>)....

    • 标识符

      即变量名:数字、字符型、下划线。命名时不以数字开头,做到见名知意。

    • 命名、定义

      变量名在赋值的时候,存的是数据的引用,而不是数据本身。Python又是一个动态语言,当引用发生改变的时候,数据随之改变。

  • 内建集合数据类型(有序:list、str、tuple;无序:set、dict)

    • 列表

      列表是异构的,意味着其内部元素的指向的数据对象不需要都是同一个类,并且这个集合可以赋值给一个变量。

      • my_list = [1, 1.5, True, my_dict]

      列表有序的,所以支持一系列的Python序列运算

      • 索引(my_list[0])、连接(+)、重复(*)、成员(in)、长度(len)、切片([:])

        注意点:切片运算:顾头不顾尾,重复运算:返回的结果是序列中指向数据对象的引用的重复。

        my_list = [1, 2, 4, 6]
        print(my_list[1:3])  # [2, 4]
        
        A = my_list * 3
        print(A)  # [1, 2, 4, 6, 1, 2, 4, 6, 1, 2, 4, 6]
        B = [my_list] * 3
        print(B)  # [[1, 2, 4, 6], [1, 2, 4, 6], [1, 2, 4, 6]]
        my_list[0] = 5
        print(B)  # [[5, 2, 4, 6], [5, 2, 4, 6], [5, 2, 4, 6]],当my_list改变时,B随之改变
        

      列表支持一些用于构建的数据类型的方法

      • 末尾追加 mylist.append(item)
      • 索引i处插入 mylist.insert(i, item)
      • 删除并返回 删除末尾:my_list.pop()删除某索引i的元素:my_list.pop(i)
      • 按大小排序 my_list.sort()
      • 列表前后颠倒 my_list.reverse()
      • 删除不返回 del my_list[i]
      • 返回元素第一次出现的下标 my_list.index(item)
      • 返回元素在列表出现的次数 my_list.count(item)
      • 移除某元素第一次在列表出现 my_list.remove(item)
        my_list = [1, 2, 4, 6]
        my_list.reverse()
        print(my_list)  # [6, 4, 2, 1]
        
        print(my_list.pop())  # 1
        

      范围对象

      • range函数会生成一个代表值序列的范围对象。使用lsit可以看到其值。
        my_range = range(10)
        print(my_range)  # range(0, 10)
        print(list(my_range))  # [0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 顾头不顾尾
        print(list(range(5, 10, 2)))  # 5开始,到9结束,步长为2
        
    • 字符串

      常量字符串通过引号引起来,与标识符(变量区别开来)。字符串是不可变的,my_str[0] = "a"会报错。

      • 由于字符串是序列,因此前面提到的序列运算符(索引(my_list[0])、连接(+)、重复(*)、成员(in)、长度(len)、切片([:]))都能用
      • 除此之外,字符串还有一些特殊地方法。
        • 居中 my_str.center(w),返回一个新的字符串,使用空格填充,使其长度为w,并居中
        • 统计次数 my_str.count(item),返回items出现的次数
        • 向左靠齐 my_str.ljust(w),返回一个新的字符串,使用空格填充,使其长度为w,并使原字符靠右放置
        • 向右靠齐 my_str.rjust(w)
        • 转小写并返回 my_str.lower()
        • 转大写并返回 my_str.upper()
        • 查找item第一次出现的下标 my_str.find(item)
        • 分割 my_str.split(schar),按schar将字符串切割,返回一个列表,schar为空时,默认使用制表符、换行符、空格等空白字符切割
        • 去除首尾空格 my_str.strip()
    • 元组

      元组与列表非常相似,都是异构数据序列。主要区别在于,元组和字符串一样不可修改。

      • 同前面列表与字符串,可以使用序列运算符(索引(my_list[0])、连接(+)、重复(*)、成员(in)、长度(len)、切片([:]))
    • 集合(set)

      集合是由零个或多个不可修改的Python数据对象组成的无序集合。集合内不允许出现重复元素,集合也是异构的。

      • 支持的运算:成员(in)、长度(len())、并集(|)、交集(&)、差集(-)、子集(<=)
      • 内置方法:
        • 并集 a_set.union(other_set),返回两者的交集
        • 交集 a_set.intersection(other_set),返回两者的交集
        • 差集 a_set.difference(other_set),返回a_set特有的元素
        • 子集 a_set.issubset(other_set),判断a_set是否为other_set的子集
        • 添加元素 a_set.add(item)
        • 移除item元素 a_set.remove(item)
        • 随机移除一个元素 a_set.pop()
        • 清空集合 a_set.clear()
    • 字典

      无序结构,key:value键值对组成。访问字典的语法与访问序列的语法十分相似,只是由之前的索引访问改成了key来访问。

      • 注意:字典并不是通过key来进行有序维护的,键的位置是由散列来决定的。
      • 支持的运算:key取值(my_dict[key]、成员运算(针对的是key)、删除(del my_dict[key])
      • 内置方法:
        • 取出所有的key my_dict.keys()
        • 取出所有的values my_dict.values()
        • 键值对以元组的形式返回 my_dict.items()
        • get取值 my_dict.get(k),没有返回None,也可以设置默认返回值:my_dict.get(k, alt)
          my_dict = {"name": "alan", "age": 18, "power": True}
          print(my_dict.keys())  # dict_keys(['name', 'age', 'power']) 返回的是对象
          print(list(my_dict.keys()))  # ['name', 'age', 'power']
          print(my_dict.values())  # dict_values(['alan', 18, True]) 返回的是对象
          print(my_dict.items())  # dict_items([('name', 'alan'), ('age', 18), ('power', True)]) 返回的是对象
          

输入与输出

Pytho提供input函数用来接受用户输入的内容,返回的是一个字符串,print函数用于输出需要返回的内容。

  • 格式化字符串
    1. 使用print函数 print(xxxx, seq="", end=""),seq控制分隔符,默认空格;end控制结尾,默认是换行符
    2. 占位符 "%s"
      name = "alan"
      old = 18
      price = 18.2
      print("%s is %d years old!" % (name, old))  # alan is 18 years old!
      print("the book's price is %08.2f" % price)  # the book's price is 00018.20
      
    3. format格式化
      name = "alan"
      old = 18
      print(f"{name} is {old} years old!")  # alan is 18 years old!
      print("{} is {} years old!".format(name, old))  # alan is 18 years old!
      

控制结构(循环与分支)

while语句是非常普遍的循环结构。

while counter <= 10 and not done:
    print("只有两者条件都为True的时候才会执行,但当counter<=10条件不满足的时候,后者条件就无需判断了。")

for循环语句一个应用场景是遍历一个有序集合(list、str、tuple)。另一个应用场景是进行有限次的迭代for item in range(5)

分支:if-elif-else

异常处理

两种报错:语法错误(杜绝发生)、逻辑错误(避免发生),下面介绍的是针对逻辑错误(异常)的处理方法。

  • try:

    try下面将可能发生异常的代码块保护起来,用except取捕获异常。

  • raise:

    主动抛出异常,主动抛出的异常也会导致程序的终止,只是这个异常是我们手动创的。

函数

函数名、参数、函数体、返回值四者构成完整的函数。

def func(num):
    root = num / 2
    for item in range(20):
        root = 1 / 2 * (root + (num / root))
    return root


print(func(9))  # 3.0
print(func(81))  # 9.0



# 装饰器
from functools import wraps


def outfunc(func):
    @warps(func)  # 装饰器修复技术,用来隐瞒help函数查询的结果
    def infunc(*args, **kwargs):
        """代码体,可以效验之类"""
        get_return = func(*args, **kwargs)
        """代码体,可以对返回值进一步处理"""
        return get_return
    return infunc

posted @ 2023-03-04 15:05  爱learn  阅读(40)  评论(0编辑  收藏  举报