Python数据结构与算法分析 第一章-Python 基础

第一章   Python 基础

1.1数据

1.1.1原子数据类型

Python 有两大內建数据类实现了整数类型和浮点数类型,相应的 Python 类就是 int 和 float。标准的数学运算符,即+、-、×、/、以及(幂)可以能够改变运算优先级的括号一起使用。其他非常有用的运算符包括取余(取模)运算符%,以及整除整除运算符//。当两个整数相除时,其结果是一个浮点数,而整除运算符截去小数部分,只返回商的整数部分。

1661310880146.png

Python 通过 bool 类实现对表达真值非常有用的布尔数据类型。布尔对象可能的状态值是True 或者 False,布尔运算符有 and、or 以及 not。

标识符在编程语言中被用作名字。当一个名字第一次出现在赋值语句的左边部分时,会创建对应的 Python 变量。赋值语句将名字与值关联起来。变量存的是指向数据的引用,而不是数据本身。赋值语句改变了变量的引用,这体现了 Python 的动态特性。同样的变量可以指向许多不同类型的数据。

1661311099613.png

1.1.2内建集合数据类型

除了数值类和布尔类,Python 还有众多强大的內建集合类。列表、字符串以及元组是概念上非常相似的有序集合,但是只有理解它们的差别,才能正确运用。

1661311207964.png

列表和序列的下标从 0 开始。myList[1:3]会返回一个包含下标从 1 到 2的元素列表(并没有包含下标为 3 的元素)

1661311438645.png

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

1661311525023.png

你会发现,像 pop 这样的方法在返回值的同时也会修改列表的内容,reverse 等方法则仅修改列表而不返回任何值。pop 默认返回并删除列表的最后一个元素,但是也可以用来返回并删除特定的元素。这些方法默认下标从 0 开始。你也会注意到那个熟悉的句点符号,它被用来调用某个对象的方法。

1661311981185.png

1661312199477.png

range是一个常见的 Python 函数,我们常把它与列表放在一起讨论。range 会生成一个代表值序列的范围对象。使用 list 函数,能够以列表形式看到范围对象的值。

1661312421034.png

字符串是零个或多个字母、数字和其他符号的有序集合。这些字母、数字和其他符号被称为字符。

1661312765689.png

列表字符串的主要区别在于,列表能够被修改,字符串则不能。列表的这一特性被称为可修改性。列表具有可修改性,字符串则不具有。

由于都是异构数据序列,因此元组与列表非常相似。它们的区别在于,元组和字符串一样是不可修改的。元组通常写成由括号包含并且以逗号分隔的一系列值。与序列一样,元组允许之前描述的任一操作。

1. 列表[ ]

2. 元组( )

3. 字符串 ’ ’

最后要介绍的 Python 集合是字典。字典是无序结构,由相关的元素对构成,其中每对元素都由一个键和一个值组成。这种键–值对通常写成键:值的形式。字典由花括号包含的一系列以逗号分隔的键–值对表达,可以通过键访问其对应的值,也可以向字典添加新的键–值对。访问字典的语法与访问序列的语法十分相似,只不过是使用键来访问,而不是下标。

1661317873209.png

1661318871353.png

1.1.3输入与输出

input 函数接受一个字符串作为参数。由于该字符串包含有用的文本来提示用户输入,因此它经常被称为提示字符串。 不论用户在提示字符串后面输入什么内容,都会被存储在 aName 变量中。使用 input 函数,可以非常简便地写出程序,让用户输入数据,然后再对这些数据进行进一步处理。

需要注意的是,input 函数返回的值是一个字符串,它包含用户在提示字符串后面输入的所有字符。如果需要将这个字符串转换成其他类型,必须明确地提供类型转换。

print 函数为输出 Python 程序的值提供了一种非常简便的方法。它接受零个或者多个参数,并且将单个空格作为默认分隔符来显示结果。

1661485158734.png

1.1.4控制结构

算法需要两个重要的控制结构:迭代分支

1.1.4.1迭代

对于迭代,Python 提供了标准的 while 语句以及非常强大的 for 语句。Python 会在每次重复执行前计算 while 语句中的条件表达式。由于 Python 本身要求强制缩进,因此可以非常容易地看清楚 while 语句的结构。

1661740285811.png

for 语句将列表[1,3,6,2,5]中的每一个值依次赋给变量 item。然后,迭代语句就会被执行。这种做法对任意的序列集合(列表、元组以及字符串)都有效。

1661740392917.png

for 语句的一个常见用法是在一定的值范围内进行有限次数的迭代。下面的语句会执行print 函数 5 次。range 函数会返回一个包含序列 0、1、2、3、4 的范围对象,然后每个值都会被赋给变量 item。

1661740609572.png

for 语句的另一个非常有用的使用场景是处理字符串中的每一个字符。下面的代码段遍历一个字符串列表,并且将每一个字符串中的每一个字符都添加到结果列表中。最终的结果就是一个包含所有字符串的所有字符的列表。

1661740792269.png

1.1.4.2分支

分支语句允许程序员进行询问,然后根据结果,采取不同的行动。绝大多数的编程语言都提供两种有用的分支结构:if-elseif

和其他所有控制结构一样,分支结构支持嵌套,一个问题的结果能帮助决定是否需要继续问下一个问题。例如,假设 score 是指向计算机科学考试分数的变量。

image.png

另一种表达嵌套分支的语法是使用 elif 关键字。将 else 和下一个 if 结合起来,可以减少额外的嵌套层次。注意,最后的 else 仍然是必需的,它用来在所有分支条件都不满足的情况下提供默认分支。

1661741886589.png

Python 也有单路分支结构,即 if 语句。如果条件为真,就会执行相应的代码。如果条件为假,程序会跳过 if 语句,执行下面的语句。

1661742047666.png

列表可以通过使用迭代结构和分支结构来创建。这种方式被称为列表解析式。通过列表解析式,可以根据一些处理和分支标准轻松创建列表。举例来说,如果想创建一个包含前 10 个完全平方数的列表,可以使用以下的 for 语句。

1661742538730.png

使用列表解析式,只需一行代码即可创建完成。

1661742353744.png

变量 x 会依次取由 for 语句指定的 1 到 10 为值。之后,计算 x * x 的值并将结果添加到正在构建的列表中。列表解析式也允许添加一个分支语句来控制添加到列表中的元素。例如添加1~10 中不能被2整数的数。

1661742736631.png

这一列表解析式构建的列表只包含 1 到 10 中奇数的平方数。任意支持迭代的序列都可用于列表解析式

1661742824899.png

1.1.5异常处理

在编写程序时通常会遇到两种错误。第一种是语法错误,也就是说,程序员在编写语句或者表达式时出错。例如,在写 for 语句时忘记加冒号。这不就说的本废琪吗,总是忘记。

image.png

第二种是逻辑错误,即程序能执行完成但返回了错误的结果。这可能是由于算法本身有错,或者程序员没有正确地实现算法。有时,逻辑错误会导致诸如除以 0、越界访问列表等非常严重的情况。这些逻辑错误会导致运行时错误,进而导致程序终止运行。通常,这些运行时错误被称为异常

当异常发生时,我们称程序“抛出”异常。可以用 try 语句来“处理”被抛出的异常。例如,以下代码段要求用户输入一个整数,然后从数学库中调用平方根函数。如果用户输入了一个大于或等于 0 的值,那么其平方根就会被打印出来。但是,如果用户输入了一个负数,平方根函数就会报告 ValueError 异常。except 会捕捉到 sqrt 抛出的异常并打印提示消息,然后会使用对应数字的绝对值来保证sqrt 的参数非负。这意味着程序并不会终止,而是继续执行后续语句。

1661743426769.png

1.1.6定义函数

函数的定义需要一个函数名、一系列参数以及一个函数体。函数也可以显式地返回一个值。例如,下面定义的简单函数会返回传入值的2倍。

1661743714540.png

1.1.7定义类

每当需要实现抽象数据类型时,就可以创建新类。

  1. Fraction 类

3/5这样的分数由两部分组成。上面的值称作分子,可以是任意整数。下面的值称作分母,可以是任意大于 0 的整数(负的分数带有负的分子)。尽管可以用浮点数来近似表示分数,但我们在此希望能精确表示分数的值。

Fraction 对象的表现应与其他数值类型一样。我们可以针对分数进行加、减、乘、除等运算,也能够使用标准的斜线形式来显示分数,比如 3/5。

Fraction 类及其构造方法

1661744401140.png

1661744327585.png

Fraction 对象 myfraction 并不知道如何响应打印请求。print 函数要求对象将自己转换成一个可以被写到输出端的字符串。myf 唯一能做的就是显示存储在变量中的实际引用(地址本身)。这不是我们想要的结果。有两种办法可以解决这个问题。

1661744565386.png

(1)show 方法,使得 Fraction 对象能够将自己作为字符串来打印。

image.png

(2)str 方法,将对象转换成字符串的方法__str__。

1661744876838.png

两个分数需要有相同的分母才能相加。确保分母相同最简单的方法是使用两个分母的乘积作为分母

1661825237081.png

1661825262535.png

(1/4+1/2 的确等于 6/8,但它并不是最简分数。最好的表达应该是 3/4。为了保证结果总是最简分数,需要一个知道如何化简分数的辅助方法。该方法需要寻找分子和分母的最大公因数(greatest commondivisor,GCD),然后将分子和分母分别除以最大公因数,最后的结果就是最简分数。

欧几里得算法指出,对于整数 m 和 n,如果 m 能被 n 整除,那么它们的最大公因数就是 n。然而,如果 m 不能被 n 整除,那么结果是 n 与 m 除以 n 的余数的最大公因数。

1661825724585.png

在 Fraction 类中,可以通过统一两个分数的分母并比较分子来实现__eq__方法。

1661827651877.png

完整Fraction类

import math

class Fraction:
    def __init__(self,top,bottom):
        self.num = top
        self.den = bottom

    def __str__(self):
       return  str(self.num)+"/"+str(self.den)

    def show(self):
        print(self.num,"/",self.den)

    def __add__(self, other):  # 1/4+1/2 = 1*2+1*4/4*2

        newnum = self.num * other.den + self.den * other.num

        newden = self.den * other.den

        common = math.gcd(newnum,newden)

        return Fraction(newnum // common, newden // common)


    def __eq__(self, other):
         firstnum = self.num *other.den
         secondnum = other.num*self.den

         return firstnum == secondnum


f1 = Fraction(1,4)
f2 = Fraction(1,2)

f1.__str__()
f2.__str__()


f3=f1+f2
print(f3)

  1. 继承:逻辑门与电路

继承使一个类与另一个类相关联,就像人们相互联系一样。孩子从父母那里继承了特征。与之类似,Python 中的子类可以从父类继承特征数据和行为。父类也称为超类。

列表是有序集合的子。因此,我们将列表称为子,有序集合称为父(或者分别称为子类列表和超类序列)。这种关系通常被称为 IS-A 关系(IS-A意即列表是一个有序集合)。这意味着,列表从有序集合继承了重要的特征,也就是内部数据的顺序以及诸如拼接、重复和索引等方法。

1661828172954.png

逻辑门

我们来构建一个模拟程序,用于模拟数字电路。逻辑门是这个模拟程序的基本构造单元,它们代表其输入和输出之间的布尔代数关系。一般来说,逻辑门都有单一的输出。输出值取决于提供的输入值。

1661829098422.png

1661829204994.png

顶部的 LogicGate 类代表逻辑门的通用特性:逻辑门的标签和一个输出。下面一层子类将逻辑门分成两种:有一个输入的逻辑门和有两个输入的逻辑门。

1661829323733.png

① 超类 LogicGate

1661829454570.png

② BinaryGate 类 和 UnaryGate 类

与门和或门有两个输入,非门只有一个输入。BinaryGate 是 LogicGate 的一个子类,并且有两个输入。UnaryGate 同样是 LogicGate 的子类,但是仅有一个输入。

1661829958158.png

③ AndGate 类

AndGate 类唯一需要添加的是布尔运算行为。这就是提供 performGateLogic 的地方。对于与门来说,performGateLogic 首先需要获取两个输入值,然后只有在它们都为 1 时返回 1。

1661830456651.png

③ Connector 类

Connector 类并不在逻辑门的继承层次结构中。但是,它会使用该结构,从而使每一个连接器的两端都有一个逻辑门。这被称为 HAS-A 关系(HAS-A 意即“有一个”),它在面向对象编程中非常重要。

1661830621577.png

Connector 与 LogicGate 是 HAS-A关系。这意味着连接器内部包含 LogicGate 类的实例,但是不在继承层次结构中。对 setNextPin 的调用对于建立连接来说非常重要。需要将这个方法添加到逻辑门类中,以使每一个 togate 能够选择适当的输入。

在 BinaryGate 类中,逻辑门有两个输入,但连接器必须只连接其中一个。如果两个都能连接,那么默认选择 pinA。如果 pinA 已经有了连接,就选择 pinB。如果两个输入都已有连接,则无法连接逻辑门。非门的输出就是整个电路的输出。

1661831247978.png

完整代码如下:

‘’‘logicgate 逻辑门
binarygate 两个输入
andgate与门 orgate或门
与非门 或非门
异或门 同或门
unarygate 一个输入
notgate 非门’‘’

class LogicGate :

def init(self,n):
self.label = n
self.output = None

def getLabel(self):
return self.label

def getOutput(self):
self.output = self.performGateLogic()
return self.output

与门和或门有两个输入,非门只有一个输入

   """与门和或门:两个输入"""

class BinaryGate(LogicGate):

def __init__(self,n):
    super().__init__(n)

    self.pinA = None
    self.pinB = None

def getPinA(self):

    if self.pinA == None:
       return int(input("Enter Pin A input for gate "+ self.getLabel() + "-->"))
    else:
        return self.pinA.getForm().getOutput()

def getPinB(self):
    return int(input("Enter Pin B input for gate " + self.getLabel() + "-->"))

def setNextPin(self, source):  # 该方法用于连结器连结两个逻辑门的时候
        if self.pinA == None:
            self.pinA = source
        else:
            if self.pinB == None:
                self.pinB = source
            else:
                raise RuntimeError('ERROR:No empry pin')

class AndGate(BinaryGate):
“”“与门 1 1为1
0 1为0 “””
def init(self,n):
super().init(n)

def performGateLogic(self):

    '''重写基类的方法,实现逻辑门的输出'''

    a = self.getPinA()
    b = self.getPinB()

    if a==1 and b==1:
        return 1
    else:
        return 0

class NotAndGate(BinaryGate):
“”“与非门 1 1为0
0 0为1
0 1为1
1 0为1"”"

def __init__(self,n):
    super.__init__(n)

def performGateLogic(self):

        '''重写基类的方法,实现逻辑门的输出'''

        a = self.getPinA()
        b = self.getPinB()

        if a == 1 and b == 1:
            return 0
        else:
            return 1

class OrGate(BinaryGate):
“”“或门 0 1为1
1 0为1
1 1为1
0 0为0
“””
def init(self,n):
super().init(n)
def performGateLogic(self):

        '''重写基类的方法,实现逻辑门的输出'''

        a = self.getPinA()
        b = self.getPinB()

        if a == 1 and b == 1:
            return 1
        else:
            return 0

class NotOrGate(BinaryGate):
‘’‘或非门 0 1为0
1 0为0
1 1为0
0 0为1
‘’’
def init(self,n):
super().init(n)

def performGateLogic(self):

        '''重写基类的方法,实现逻辑门的输出'''

        a = self.getPinA()
        b = self.getPinB()

        if a == 1 and b == 1:
            return 0
        else:
            return 1

class XORGate(BinaryGate):
‘’‘异或门 :若两个输入的电平相同,则输出为低电平0。即如果两个输入不同,则异或门输出高电平1
0 1为1
1 0为1
1 1为0
0 0为0’‘’
def init(self,n):
super().init(n)

def performGateLogic(self):

        '''重写基类的方法,实现逻辑门的输出'''

        a = self.getPinA()
        b = self.getPinB()

        if a == b:
            return 0
        else:
            return 1

class XNOGate(BinaryGate):
‘’'同或门 若两个输入的电平相同,则输出为低电平1。即如果两个输入不同,则异或门输出高电平0
0 1为0
1 0为0
1 1为1
0 0为1

'''
def __init__(self,n):
    super().__init__(n)

def performGateLogic(self):

        '''重写基类的方法,实现逻辑门的输出'''

        a = self.getPinA()
        b = self.getPinB()

        if a == b:
            return 1
        else:
            return 0

“”“非门:一个输入”“”

class UnaryGate(LogicGate):
def init(self,n):
super().init(n)

    self.pin = None

def getPin(self):
    return int(input("Enter Pin  input for gate " + self.getLabel() + "-->"))

def setNextPin(self, source):  # 该方法用于连结器连结两个逻辑门的时候
 if self.pin  == None:
    self.pin = source

 else:
        raise RuntimeError('ERROR:No empry pin')

class NotGate(UnaryGate):
“”“非门”“”

def __init__(self, n):
    super().__init__(n)

def performGateLogic(self):
    x = self.getPin()
    if x == 1:
        return 0
    else:
        return 1

class Connector:

'''连接器类,用于连接两个逻辑门:默认选择PinA,如果 pinA 已经有了连接,就选择 pinB。如果两个输入都已有连接,则无法连接逻辑门。'''
def __init__(self,fgate,tgate):
    self.fromgate = fgate
    self.togate = tgate

    tgate.setNextPin(self)

def getFrom(self):
    return  self.fromgate

def getTo(self):
    return  self.togate

if name == ‘main’:
# g1 = AndGate(‘g1’)
# print(g1.getOutput())
# n1 = NotGate(‘n1’)
# print(n1.getOutput())
#
# o1 = OrGate(‘o1’)
# print(o1.getOutput())

g1 = AndGate('g1')
g2 = AndGate('g2')
g3 = OrGate('g3')
g4 = NotGate('g4')
c1 = Connector(g1,g3)
c2 = Connector(g2,g3)
c3 = Connector(g3,g4)
print(g4.getOutput())
# g5 = XORGate('g5')
# print(g5.getOutput())

1.2 小结

  • 计算机科学是研究如何解决问题的学科。
  • 计算机科学利用抽象这一工具来表示过程和数据。
  • 抽象数据类型通过隐藏数据的细节来使程序员能够管理问题的复杂度。
  • 列表、元组以及字符串是 Python 的內建有序集合。
  • 字典和集是无序集合。
  • 类使得程序员能够实现抽象数据类型,以通过继承层次结构来组织,其构造方法总是先调用其父类的构造方法,然后才处理自己的数据和行为。
  • 程序员既可以重写标准方法,也可以构建新的方法。

如果你对Python感兴趣,想要学习python,这里给大家分享一份Python全套学习资料,都是我自己学习时整理的,希望可以帮到你,一起加油!

😝有需要的小伙伴,可以V扫描下方二维码免费领取🆓

1️⃣零基础入门

① 学习路线

对于从来没有接触过Python的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。
在这里插入图片描述

② 路线对应学习视频

还有很多适合0基础入门的学习视频,有了这些视频,轻轻松松上手Python~
在这里插入图片描述

③练习题

每节视频课后,都有对应的练习题哦,可以检验学习成果哈哈!
在这里插入图片描述

2️⃣国内外Python书籍、文档

① 文档和书籍资料

在这里插入图片描述

3️⃣Python工具包+项目源码合集

①Python工具包

学习Python常用的开发软件都在这里了!每个都有详细的安装教程,保证你可以安装成功哦!
在这里插入图片描述

②Python实战案例

光学理论是没用的,要学会跟着一起敲代码,动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。100+实战案例源码等你来拿!
在这里插入图片描述

③Python小游戏源码

如果觉得上面的实战案例有点枯燥,可以试试自己用Python编写小游戏,让你的学习过程中增添一点趣味!
在这里插入图片描述

4️⃣Python面试题

我们学会了Python之后,有了技能就可以出去找工作啦!下面这些面试题是都来自阿里、腾讯、字节等一线互联网大厂,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
在这里插入图片描述
在这里插入图片描述

  • 20
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值