一、 顺序执行
1. 执行原则
Python代码在执行过程中,遵循下面的基本原则:
普通语句,直接执行
>>> print("hello world")hello world
碰到函数,将函数体载入内存,并不直接执行 ```python
def test(): print(“我是test”)
#不直接执行函数内代码id(test()) #遇到了函数调用,从上往下执行 我是test #先执行了函数内的print语句 506111184 #然后执行了id()语句
```
碰到类,执行类内部的普通语句,但是类的方法只载入,不执行 ```python
class Demo(): print(“我是class demo”)
def test1(self):print("我是demo test1") #碰到函数test1只载入不执行函数内语句
我是class demo #碰到了class这个类,执行类内部的普通语句,类方法只载入
d = Demo() #实例化类Demo d.test1() #调用类中的test1()方法 我是demo test1 #执行输出test1内的print语句 ```
- 碰到if、for等控制语句,按相应控制流程执行
- 碰到@,break,continue等,按规定语法执行
碰到函数、方法调用等,转而执行函数内部代码,执行完毕继续执行原有顺序代码
2. 程序主入口
我们经常在Python程序中看到这么一行语句if name == ‘main‘:
首先,name是所有模块都会有的一个内置属性,一个模块的name值取决于你如何调用模块。例如:你有一个test.py文件,如果在a.py文件中使用import导入这个模块import test.py,那么test.py模块的name属性的值就是test,不带路径或者文件扩展名。当py文件中的函数或者方法被放在main方法下面的时候,就不会被第三方导入所调用,从而起到了一种保护的作用。
#在test.py内执行如下代码:def test1():print("可公开调用的函数")def test2():print("不可公开调用的函数")test1()if __name__ == '__main__':test2()#输出结果为:可公开调用的函数不可公开调用的函数
#在imp.py中导入test.py模块,运行后的结果为import test#输出结果为:可公开调用的函数
- 其实顺序执行,简单来说就是代码按照从上到下的顺序来执行
二、 条件判断
1. 运行原理
条件判断是通过一条或多条判断语句的执行结果(True或者False)来决定怎么去执行代码块。使用if、elif和else三个关键字来进行条件判断。
点击查看【processon】
2. 使用规则
- 每个条件后面要使用冒号(:)作为判断行的结尾,表示接下来是满足条件(结果为True)后要执行的语句块。
- 除了if分支必须有,elif和else分支都可以根据情况省略。
- 使用缩进来划分语句块,相同缩进数的语句在一起组成一个语句块。
- 顺序判断每一个分支,任何一个分支首先被命中并执行,则其后面的所有分支被忽略,直接跳过!
- 在Python中没有switch – case语句。
- if/else语句可以嵌套,也就是把 if…elif…else 结构放在另外一个 if…elif…else 结构中。
练习
- 实现猜筛子点数的游戏:我们随机输入自己猜的点数(1-6)与系统随机产生的数字(1-6)进行比较。如果猜对了,输出:恭喜你猜对了;如果猜错了,输出:很遗憾,系统随机数为××。
>>> import random>>> print(f'恭喜你猜对了!' if int(input('请输入数字: ')) == random.randint(1,6) elsef'很遗憾,系统随机数为:{random.randint(1,6)}')#out测试请输入数字: 3很遗憾,系统随机数为:4
三、 循环控制
1. 运行原理
循环控制,就是让程序循环运行某一段代码直到满足退出的条件,才退出循环。Python用关键字for和while来进行循环控制,但是没有其它语言的do…while语句(在Java和PHP中都有do while)。
2. while 循环
1. while循环表达式
当程序从上至下执行时,遇到while循环语句,则会判断表达式是否成立,当成立时则会进入while循环体内,执行循环体内部执行的代码块。直到判断表达式不成立时,则终止循环。控制结构图如下:
点击查看【processon】
练习
- 使用while循环结构打印输出3次hello world
i = 1while i <=3:print('helloworld')i += 1#outhelloworldhelloworldhelloworld
- 求1-100之间的总和
方法1a = 0b = 1while b<=100:a += bb += 1print(a)#out5050#方法2a = int(input('请输入求和最大数 '))b = afor i in range(a-1,0,-1):b += iprint(b)#out请输入求和最大数 1005050
from functools import reduceprint(reduce(lambda x,y:x+y,range(1,101)))#out5050
2. while else 从句
while循环还可以增加一个else从句。当while循环正常执行完毕,会执行else语句。else与while平级的缩进方式!
number = 10i = 0# i = 11while i < number:print(i)i += 1else:print("执行完毕!")#out0123456789执行完毕!
如果被break等机制强制提前终止循环,则不会执行else语句。
number = 10i = 0while i < number:print(i)i += 1if i == 7:breakelse:print("执行完毕!")#out0123456
4. for 循环
1. 表达式
虽然与while一样都是循环的关键字,但for循环通常用来遍历可迭代的对象iterable(字符串str、列表list、),其一般格式为:for … in …:
可迭代对象内部都有一个iter()方法,for循环遍历数据之前,会调用iter()方法,将可迭代对象变为迭代器,然后调用next()方法。我们使用while循环来演练一下运行原理举例如下:
li = [1,2,3,4] #列表为可迭代对象,先将可迭代对象转为迭代器list_iter = li.__iter__()try: #报错调试while True:print(list_iter.__next__())except StopIteration: #报错调试pass#out1234
例如将列表 [1,2,3] 中的每项元素打印输出
li = [1,2,3]for i in li:print(i)#out123
2. 循环嵌套
if判断可以嵌套,while和for当然也可以嵌套。但是建议大家不要嵌套3层以上,那样的效率会很低。
练习
- 实现打印输出九九乘法表
>>> i=0>>> j=0>>> for i in range(1,10):for j in range(1,i+1):print(f'{i}*{j}=',j*i,end=' ')print()#out1*1= 12*1= 2 2*2= 43*1= 3 3*2= 6 3*3= 94*1= 4 4*2= 8 4*3= 12 4*4= 165*1= 5 5*2= 10 5*3= 15 5*4= 20 5*5= 256*1= 6 6*2= 12 6*3= 18 6*4= 24 6*5= 30 6*6= 367*1= 7 7*2= 14 7*3= 21 7*4= 28 7*5= 35 7*6= 42 7*7= 498*1= 8 8*2= 16 8*3= 24 8*4= 32 8*5= 40 8*6= 48 8*7= 56 8*8= 649*1= 9 9*2= 18 9*3= 27 9*4= 36 9*5= 45 9*6= 54 9*7= 63 9*8= 72 9*9= 81
- 实现学习调研系统:当输入为 yes 时,给出选项yes/no;当选项为正确选项时,输出显示:1.高数 2.Python 3.看电影 4.退出;选择1-3的任何一个选项,输出我对{}如初恋,{}虐我千百遍;当选择4时,输出已退出;当选择不在1-4范围内时,则提示重新选择,重新进入循环;当用户选择no,则输出好吧,再不学习就老啦;输入除了yes/no以外值时,提示输入有误,并进入重新循环。
li1 = ['1','2','3','4']li2 = ['学高数','学Python','看电影','退出']dic1 = dict(zip(li1,li2))Flag = Truewhile Flag == True:ipt1 = input('最近学习了吗?yes/no')if ipt1.lower() == 'yes':print(f'真棒哇!!!')for key,values in dic1.items():print(key+': '+values)ipt2 = input('学习了啥好玩的呢?请选择')if ipt2 in ['1','2','3']:print(f'我视{dic1[ipt2]}如初恋,{dic1[ipt2]}虐我千百遍')Flag = Falseelif ipt2 == '4':print('已退出系统')Flag = Falseelse:print('输入错误请重新输入')Flag = Trueelif ipt1.lower() == 'no':print('好吧,在不学习就老啦!')Flag = Falseelse:print('输入有误,请重新输入')Flag = True
- 遍历”12”,遍历 range(12)
for i in ('12'):print(i)for i in range(12):print(i)#out1201234567891011
[x] 计算 n 的阶乘
#1方法:a = int(input('阶乘数: '))def t1(a):if a>1:return a*t1(a-1)else:return 1res = t1(a)print(res)#out阶乘数: 103628800#2方法:from functools import reducea = int(input('阶乘数: '))print(reduce(lambda x,y:x*y,range(1,a+1)))阶乘数: 103628800#3方法:import mathn = int(input('请输入阶乘数'))a = math.factorial(n)print(a)#out请输入阶乘数103628800
[x] 计算从 1 到 n 以内所有奇数的和并输出。
from functools import reducea = int(input('奇数求和: '))print(reduce(lambda x,y:x+y,range(1,a+1,2)))#out奇数求和: 1000250000
[ ] 打印出所有的”水仙花数”,所谓”水仙花数”是指一个三位数, 其各位数字立方和等于该数本身。例如:153 是一个”水仙花数”,1^3 + 5^3+ 3^3 = 153 ```python for i in range(100,1000): a = i % 10 #个位 b = int(i/100) #百位 c = int((i-b100)/10) #十位 d = a3 + b3 +c*3 if d == i:
print(f'{d}是水仙花数')
out
153是水仙花数 370是水仙花数 371是水仙花数 407是水仙花数
方法2:延伸拓展
while True: try: x = int(input(‘请输入最大取值范围(整数): ‘)) break except: print(‘输入不正确,请重新输入:’) for i in range(100,x+1): j = str(i) k = 0 for a in j: k += int(a) ** len(j) if k == i: print(f’{i}是水仙花数’)
方法3:判定数值是否为水仙花数:
while True: #判定符合数值类型的输入 try: x = int(input(‘请输入待测试数值: ‘)) #1 例如输入153 break except: print(‘输入错误,请重新输入整数值: ‘) a = 0 #初始化变量 n = len(str(x)) #确定水仙花的幂指数 #2 n=3 test = x #3 test=153
#8 test=15 #13 test=1
while test > 0: #4 满足条件
#9 再次满足条件 #14 再次满足条件digit_x = test % 10 #取输入值的个位数 #5 digit_x = 3#10 digit_x = 5 #15 digit_x = 1a += digit_x ** n #6 a = 0 + 3**3#11 a = 3**3 + 5**3 #16 a = 3**3 + 5**3 + 1**3test //= 10 #逐渐将个位、十位、百位去掉 #7 test = 153//10 --->15 #12 test =15//10 --->1 #17 test =1//10 --->0 退出循环体#输出结果
print(f’{x}是水仙花数’ if a == x else f’{x}不是水仙花数’)
---<a name="ESKJO"></a>### 5. break 语句不论是while循环体还是for循环体执行的过程中想要退出循环体,就可以使用到break语句。举例如下:- while循环,在输出1-100个数值时,当n为8时,退出循环体```python>>> n = 1>>> while n<=100:... print(n)... n += 1... if n == 8:... break...1234567
- for 循环,遍历range(1,10)过程中,当元素为7时,退出循环体。
>>> for i in range(1,10):... if i == 7:... break... print(i)...123456
6. continue 语句
continue语句与break语句不同,continue语句用于跳过当前循环体剩余部分的代码,直接开始下一轮循环。它不会退出和终止循环。
练习
- while 循环,在输出1-100个数值时,不打印输出8。
>>> while n<=100:... # print(n) # 注:如果在这块打印输出,continue对整体打印并无影响... n+=1... if n == 8:... continue... print(n)...234567910...101
- for 循环,遍历range(1,10)过程中,不打印元素8。
for i in range(1,10):if i == 8:continueprint(i)#out12345679
7. 外层循环控制
Python中的break只能跳出当前层的循环,无法全部跳出。那如果需要退出双层循环如何做?
flag = False # 用于控制外层循环的标志for i in range(10):if flag: # 当flag被内层循环设置为True的时候,跳出外层循环breakfor j in range(10):if j==7:flag = Truebreakprint(i,j)
拓展:链表
1. 链表的定义
linked list
- 链表是一种常见的基础数据结构,是一种线性表,与顺序表不同在于它基于每一个数据存储单元里存放下一个待访问单元的地址信息,从而实现动态访问与内存管理
链表与顺序表的不同应用场景:
- 顺序表:有随机读取的优点,它需要先知道数据的大小,然后根据内置策略进行扩容存储空间并迁移数据,这在使用起来并不是很灵活
- 链表:可以通过一种方式实现灵活的动态内存管理,从而充分利用计算机内存空间,但是没有随机读取的优势
- 相应操作的时间复杂度差异:
链表主要的耗时在内部遍历查找时,而删除和插入的操作本身时间复杂度仅仅为O(1);
顺序表查找很快,主要耗时在了数据的迁移,因为除了目标元素在尾部的添加外,顺序表的插入与删除都需要对操作元素位置之后的所有元素进行移位操作,而这个只能通过拷贝和覆盖的方法进行;
| 时间复杂度对照 | 链表 | 顺序表 |
|---|---|---|
| 访问元素时 | O(n) | O(1) |
| 在头部插入/删除元素时 | O(1) | O(n) |
| 在尾部插入/删除元素时 | O(n) | O(1) |
| 在中间插入/删除元素时 | O(n) | O(n) |
2. 功能简介
循环链表是相对于单链表而言的一种特殊情况,就是将最后一个节点的next域赋值给头结点,如下图所示:
点击查看【processon】
循环链表与单链表的比较
- 循环链表的特点是无须增加存储量,仅对表的链接方式稍作改变,即可使得表处理更加方便灵活。
- 循环链表中没有None域。涉及遍历操作时,其终止条件就不再是像非循环链表那样判别p或p->next是否为None,而是判别它们是否等于某一指定指针,如头指针或尾指针等。
- 在单链表中,从一已知结点出发,只能访问到该结点及其后续结点,无法找到该结点之前的其它结点。而在循环链表中,从任一结点出发都可访问到表中所有结点,这一优点使某些运算在单循环链表上易于实现。
3. 实现代码
单链表操作:
is_empty() 链表是否为空
length() 链表长度
travel() 遍历整个链表
add(item) 链表头部添加元素
append(item) 链表尾部添加元素
insert(pos,item)指定位置添加元素
remove(item) 删除节点
searc(item) 查找节点是否存在
class SingleNode(object):"""单链表节点"""def __init__(self,item):#item是存放数据元素self.item=item#next是下一个节点的标识self.next=Noneclass SingleLinkList(object):"""单链表"""#第一个情况是空单链表、或者是非空单链表def __init__(self,node=None):self.__head=nodedef is_empty(self):"""链表是否为空"""# if self.__head==None:# return True# else:# return Falsereturn self.__head==Nonedef length(self):"""链表长度"""cur = self.__head#计数器重置为从0开始计数count=0 #如果链表本身是一个空链表的话,那么这个count=1,那么就与认知不相符while cur != None:count +=1#将游标移动至下一个位置cur = cur.nextreturn countdef travel(self):"""遍历整个列表"""cur = self.__headwhile cur != None:#打印节点中的数据print(cur.item,end=' ')cur = cur.nextprint(" ")def append(self,item):"""链表中添加元素"""#item是要具体插入的数据node = SingleNode(item)if self.is_empty():self.__head=nodeelse:cur = self.__headwhile cur.next != None :cur =cur.nextcur.next = nodedef add(self,item):"""链表添加头部元素"""#item是我们需要具体添加的数据node =SingleNode(item)#将新节点的连接区的next指向头节点node.next=self.__head#将链表头部信息指向新节点self.__head=nodedef insert(self,pos,item):"""指定位置添加"""#item是指定要插入的值,pos是要元素插入的位置if pos <= 0:self.add(item)elif pos>self.length()-1:self.append(item)else:#node =SingleNode(item)count = 0pre =self.__headwhile count<(pos - 1):count += 1pre = pre.nextnode.next=pre.nextpre.next=nodedef remove(self):"""删除节点"""#定义起点cur = self.__headpre = Nonewhile cur != None:#找到指定元素的判断if cur.item == item:#判断是否删除第一个元素if cur ==self.__head:self.__head=cur.nextelse:#删除pre.next = cur.nextbreakelse:#继续移动pre = curcur = cur.nextdef search(self,item):"""查找节点是否存在"""#定义起点cur=self.__headwhile cur != None:if cur.item==item:return Trueelse:#如果没找到的话继续往下走cur=cur.nextreturn Falses = SingleLinkList()print(s.is_empty())print(s.length())s.append(1)s.append(2)s.append(13)s.append(14)s.append(15)print(s.is_empty())s.travel()s.add(10)s.travel()s.insert(-1,666)s.insert(10,777)s.insert(3,888)s.travel()print(s.search(777))#outTrue0False1 2 13 14 1510 1 2 13 14 15666 10 1 888 2 13 14 15 777True
双向链表操作:
循环链表操作:
建立节点
class Node():"""建立节点"""def __init__(self,item):self.item=itemself.next=None
建立带有头节点的循环链表
def is_empty(self):"""判断链表是否为空"""return self.__head==None
求循环链表长度
def length(self):"""求链表的长度"""if self.is_empty():return 0else:count=1cur=self.__headwhile cur.next!=self.__head:count+=1cur=cur.nextreturn count
def travel(self):cur=self.__headif self.is_empty():print("该链表为空,无法进行遍历")else:while cur!=self.__head:print(str(cur.date),end=" ")cur=cur.nextprint(str(cur.date))#用于遍历最后一个节点
这行代码要注意最后一行,不能少,否则不能够输出最后一个节点,因为在while循环中,扫描到最后一个节点时cur==self.__head 不能够进入while循环中,所以需要单独输出
从头插入节点
def HeadInsert(self,num):"""头部插入节点"""node=Node(num)if self.is_empty():self.__head=nodenode.next=nodeelse:cur=self.__headwhile cur.next!=self.__head:cur=cur.nextnode.next=self.__headself.__head=nodecur.next=self.__head
从尾部插入节点 ```python def TailInsert(self,num):
"""尾部插入节点"""node=Node(num)if self.is_empty():self.__head=nodenode.next=self.__headelse:cur=self.__headwhile cur.next!=self.__head:cur=cur.nextnode.next=self.__headcur.next=node
6. **索引插入**```pythondef NodeInsert(self,index,num):"""在指定位置添加元素"""#指向不是头部元素,self.__head的地址# 为下一个元素,所以pre为下一个元素if index <= 0:#认为是头插法self.HeadInsert(num)elif index > (self.length()-1):self.TailInsert(num)else:pre_cur = self.__headcount = 0while count < (index-1):count+=1pre_cur = pre_cur.nextnode = Node(num)node.next = pre_cur.nextpre_cur.next = node
完整代码 ```python import random class Node(): “””
建立节点
“”” def init(self,date):
self.date=dateself.next=None
class LinkNode(): def init(self,node=None):
self.__head=nodeif node:node.next=self.__head #建立一个循环头节点
def is_empty(self):
"""判断链表是否为空"""return self.__head==None
def length(self):
"""求链表的长度"""if self.is_empty():return 0count=1cur=self.__headwhile cur.next!=self.__head:count+=1cur=cur.nextreturn count
def travel(self):
"""遍历整个链表"""if self.is_empty():return#建立游标等于起始节点cur = self.__headwhile cur.next != self.__head:print(cur.date,end=" ")cur = cur.nextprint(cur.date,end="\n")
def HeadInsert(self,num):
"""头部插入节点"""node=Node(num)if self.is_empty():self.__head=nodenode.next=nodeelse:cur=self.__headwhile cur.next!=self.__head:cur=cur.nextnode.next=self.__headself.__head=nodecur.next=self.__head
def TailInsert(self,num):
"""尾部插入节点"""node=Node(num)if self.is_empty():self.__head=nodenode.next=self.__headelse:cur=self.__headwhile cur.next!=self.__head:cur=cur.nextcur.next=nodenode.next=self.__head
def NodeInsert(self,index,num):"""在指定位置添加元素"""#指向不是头部元素,self.__head的地址# 为下一个元素,所以pre为下一个元素if index <= 0:#认为是头插法self.HeadInsert(num)elif index > (self.length()-1):self.TailInsert(num)else:pre_cur = self.__headcount = 0while count < (index-1):count+=1pre_cur = pre_cur.nextnode = Node(num)node.next = pre_cur.nextpre_cur.next = node
a=LinkNode() for i in range(6): a.TailInsert(random.randint(0,10))#随机从插入6个数字 a.travel() a.NodeInsert(5,100) a.travel() ```
