Python学习笔记(二)之序列 控制语句 函数

Python学习笔记(二)之序列 控制语句 函数

第一章 Python 基本概念
第二章 Python 序列 控制语句 函数
第三章 Python 面向编程 异常处理 文件处理
第四章 Python 坦克大战
第五章 Python 并发编程 网络通信


文章目录


前言

主要是记录序列,控制语句,函数的学习。其中序列包含了列表、元组、字典、集合、字符串,控制语句包含选择结构和循环结构,函数主要需要掌握变量、参数传递、递归和嵌套的用法。


一、序列

序列的本质:是一种数据存储方式,用来存储一系列的数据。在内存中,序列就是一块用来存放多个值的连续的内存空间。
由于Python3中一切皆对象,在内存中实际是按照如下方式存储的:

从图示中,我们可以看出序列中存储的是整数对象的地址,而不是整数对象的值。

1.列表

1.1基本特点

  • 列表:用于存储任意数目、任意类型的数据集合。
  • 列表是内置可变序列,是包含多个元素的有序连续的内存空间。列表的标准语法格式: a = [10,20,30,40]
    其中,10,20,30,40这些称为:列表a的元素。
  • 列表中的元素可以各不相同,可以是任意类型。比如: a = [10,20,‘abc’,True]
  • Python的列表大小可变,根据需要随时增加或缩小。
  • 字符串和列表都是序列类型,一个字符串是一个字符序列,一个列表是任何元素的序列。

1.2列表的创建

基本语法[]创建

a = [10,20,'gaoqi','sxt']
b = []  #创建一个空的列表对象
print(a)

list()创建

a = list()  #创建一个空的列表对象
b = list(range(10))  #结果:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
c = list("gaoqi,sxt") #结果:['g', 'a', 'o', 'q', 'i', ',', 's', 'x', 't']

range()创建整数列表
range([start,] end [,step])

  • start参数:可选,表示起始数字。默认是0
  • end参数:必选,表示结尾数字。
  • step参数:可选,表示步长,默认为1

python3中range()返回的是一个range对象,而不是列表。需要通过list()方法将其转换成列表对象。

a = list(range(3,15,2)) #结果:[3, 5, 7, 9, 11, 13]
b = list(range(15,9,-1)) #结果:[15, 14, 13, 12, 11, 10]
c = list(range(3,-4,-1)) #结果:[3, 2, 1, 0, -1, -2, -3]
print(a,b,c)

推导式生成列表

#循环创建多个元素 [0, 2, 4, 6, 8]
a = [x*2  for  x  in range(5)]
#通过if过滤元素[0, 18, 36, 54, 72, 90, 108, 126, 144, 162, 180, 198]
b = [x*2 for x in range(100) if x%9==0]
print(a,b)

1.3元素增加

主要有append(),extend(),insert()三种方法,当列表增加和删除元素时,列表会自动进行内存管理,除非必要,一般只在列表的尾部添加元素或删除元素,提高列表的操作效率。
append()方法
原地修改列表对象,是真正的列表尾部添加新的元素,速度最快,推荐使用。

a = [20,40]
a.append(80)
print(a)    #结果:[20, 40, 80]

+运算符操作
并不是真正的尾部添加元素,而是创建新的列表对象;将原列表的元素和新列表的元素依次复制到新的列表对象中。这样,会涉及大量的复制操作,对于操作大量元素不建议使用。

a = [20,40]
print(id(a))
a = a+[50]
print(id(a))  #两次地址不一样,创建了新的对象


extend()方法
将目标列表的所有元素添加到本列表的尾部,属于原地操作,不创建新的列表对象。

a = [20,40]
print(id(a))
b = [50,60]
a.extend(b)   #原对象修改
print(id(a))
a = a+b     #产生新对象
print(id(a))

insert()插入元素
使用insert()方法可以将指定的元素插入到列表对象的任意制定位置。这样会让插入位置后面所有的元素进行移动,会影响处理速度。涉及大量元素时,尽量避免使用。类似发生这种移动的函数还有:remove()、pop()、del(),它们在删除非尾部元素时也会发生操作位置后面元素的移动。

a = [10,20,30]
a.insert(2,100)
print(a)   #结果:[10, 20, 100, 30]

乘法扩展
使用乘法扩展列表,生成一个新列表,新列表元素是原列表元素的多次重复。适用于乘法操作的,还有:字符串、元组。

a = ['sxt',100]
b = a*3
print(a) #结果:['sxt', 100]
print(b) #结果:['sxt', 100, 'sxt', 100, 'sxt', 100]

1.4列表元素删除

删除元素的本质是元素的拷贝
del 删除

a = [100,200,888,300,400]
del a[2]
print(a)   #结果:[100,200,300,400]

pop()
pop()删除并返回指定位置元素,如果未指定位置则默认操作列表最后一个元素

a = [10,20,30,40,50]
b1 = a.pop()   #结果:b1=50
print(a,b1)  #结果:[10, 20, 30, 40]  50
b2 = a.pop(1)
print(a,b2)  #结果:[10, 30, 40],20

remove()方法
删除首次出现的指定元素,若不存在该元素抛出异常。

a = [10,20,30,40,50,20,30,20,30]
a.remove(20)  #[10, 30, 40, 50, 20, 30, 20, 30]
a.remove(100)  #报错:ValueError:list.remove(x): x not in list

1.5元素访问和计数

通过索引直接访问元素
通过索引直接访问元素。索引的区间在[0, 列表长度-1]这个范围。超过这个范围则会抛出异常。

a = [10,20,30,40,50,20,30,20,30]
print(a[2]) #结果:30
print(a[10]) #报错:IndexError: list index out of range

index()获得指定元素在列表中首次出现的索引
index()可以获取指定元素首次出现的索引位置。语法是:index(value,[start,[end]])。其中,start和end指定了搜索的范围。

a = [10,20,30,40,50,20,30,20,30]
print(a.index(20))  #结果:1
print(a.index(20,3)) #结果:5   从索引位置3开始往后搜索的第一个20
print(a.index(30,5,7)) #结果:6  从索引位置5到7这个区间,第一次出现30元素的位置

count()获得指定元素在列表中出现的次数

a = [10,20,30,40,50,20,30,20,30]
a.count(20)  #结果是3

len()返回列表长度

a = [10,20,30]
len(a) # 长度是3

成员资格判断
判断列表中是否存在指定的元素,我们可以使用count()方法,返回0则表示不存在,返回大于0则表示存在。但是,一般我们会使用更加简洁的in关键字来判断,直接返回True或False

1.6切片slice()

和字符串的使用保持一致
[起始偏移量start:终止偏移量end[:步长step]]
三个量为正数的情况
三个量为负数
切片操作时,起始偏移量和终止偏移量不在[0,字符串长度-1]这个范围,也不会报错。起始偏移量小于0则会当做0,终止偏移量大于“长度-1”会被当成”长度-1”。

1.7列表遍历和排序

列表的遍历

a = [10,20,30,40]
for obj in a:       #obj是临时变量名称,随意起
  print(obj)

复制列表所有的元素到新列表对象

list1 = [30,40,50]
list2 = [] + list1  #生成了新列表对象

列表排序
-修改原列表,不建新列表的排序

建新列表的排序
-通过内置函数sorted()进行排序,这个方法返回新列表,不对原列表做修改。

reversed()返回迭代器
内置函数reversed()也支持进行逆序排列,与列表对象reverse()方法不同的是,内置函数reversed()不对原列表做任何修改,只是返回一个逆序排列的迭代器对象。
打印输出c发现提示是:list_reverseiterator。也就是一个迭代对象。同时,我们使用list©进行输出,发现只能使用一次。第一次输出了元素,第二次为空。因为迭代对象在第一次时已经遍历结束了,第二次不能再使用。

max min sum

 a = [3,10,20,15,9]
max(a) #20
min(a) #3
sum(a) @57

1.8二维列表

一维列表可以帮助我们存储一维、线性的数据。
二维列表可以帮助我们存储二维、表格的数据。

a = [
     ["高小一",18,30000,"北京"],
       ["高小二",19,20000,"上海"],
       ["高小五",20,10000,"深圳"],
   ]

嵌套循环打印二维列表所有的数据:

a = [
     ["高小一",18,30000,"北京"],
        ["高小二",19,20000,"上海"],
        ["高小一",20,10000,"深圳"],
   ]
for m in range(3):
  for n in range(4):
    print(a[m][n],end="\t")
  print() #打印完一行,换行


ps: 如果打印的时候print语句在第二个for循环下,即每个数据单行打印:

2.元组

和列表比较:

  • 列表属于可变序列,可以任意修改列表中的元素。
  • 元组属于不可变序列,不能修改元组中的元素。

    因此,元组没有增加元素、修改元素、删除元素相关的方法。
    元组支持如下操作:
    索引访问、切片操作、连接操作、成员关系操作、比较运算操作、计数:元组长度len()、最大值max()、最小值min()、求和sum()等

2.1元组的创建

1.通过()创建元组。小括号可以省略。 a = (10,20,30) 或者 a = 10,20,30。如果元组只有一个元素,则必须后面加逗号。这是因为解释器会把(1)解释为整数1,(1,)解释为元组。

2.通过tuple()创建元组

tuple()可以接收列表、字符串、其他序列类型、迭代器等生成元组。
list()可以接收元组、字符串、其他序列类型、迭代器等生成列表。

2.2元素访问

元组的元素不能修改

a = (20,10,30,9,8)
a[3]=33
"""
Traceback (most recent call last):
 File "", line 1, in <module>
  a[3]=33
TypeError: 'tuple' object does not support item assignment
"""

列表关于排序的方法list.sorted()是修改原列表对象,元组没有该方法。如果要对元组排序,只能使用内置函数sorted(tupleObj),并生成新的列表对象。

a = (20,10,30,9,8)
b = sorted(a)  #b是新对象,内容是:[8, 9, 10, 20, 30]
print(type(b)) #<class 'list'>

**zip(列表1,列表2,…)**将多个列表对应位置的元素组合成为元组,并返回这个zip对象。

a = [10,20,30]
b = [40,50,60]
c = [70,80,90,100]
d = zip(a,b,c)
print(d)  #zip object <zip object at 0x0000022D11AFC380>
e = list(d) #列表:[(10, 40, 70), (20, 50, 80), (30, 60, 90)]
print(e)

2.3生成器推导式创建元组

  • 从形式上看,生成器推导式与列表推导式类似,只是生成器推导式使用小括号
  • 列表推导式直接生成列表对象,生成器推导式生成的不是列表也不是元组,而是一个生成器对象。
  • 我们可以通过生成器对象,转化成列表或者元组。也可以使用生成器对象的__next__()方法进行遍历,或者直接作为迭代器对象来使用。不管什么方式使用,元素访问结束后,如果需要重新访问其中的元素,必须重新创建该生成器对象。
s = (x*2 for x in range(5))
print(s)  # at 0x0000021C80BE2880>
b = tuple(s)
print(b)  #(0, 2, 4, 6, 8)
c = tuple(s)
print(c)  #() 生成器只能用一次
​
s2 = (x for x in range(3))
print(s2.__next__())    #0
print(s2.__next__())    #1
print(s2.__next__())    #2
print(s2.__next__())    #报错:StopIteration

2.4总结

1.元组的核心特点是:不可变序列。
2.元组的访问和处理速度比列表快。
3.与整数和字符串一样,元组可以作为字典的键,列表则永远不能作为字典的键使用。

3.字典

3.1基本定义

字典是“键值对”的无序可变序列,字典中的每个元素都是一个“键值对”,包含:“键对象”和“值对象”。可以通过“键对象”实现快速获取、删除、更新对应的“值对象”。
a = {‘name’:‘gaoqi’, ‘age’:18, ‘job’:‘programmer’}

  • “键”是任意的不可变数据,比如:整数、浮点数、字符串、元组。
  • 但是:列表、字典、集合这些可变对象,不能作为“键”。
  • “键”不可重复。
  • “值”可以是任意的数据,并且可重复。

3.2字典创建

可以通过**{}、dict()**来创建字典对象。

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = dict(name='gaoqi',age=18,job='programmer')
a = dict([("name","gaoqi"),("age",18)])
c = {} #空的字典对象
d = dict() #空的字典对象

通过**zip()**创建字典对象

k = ['name','age','job']
v = ['gaoqi',18,'teacher']
d = dict(zip(k,v))
print(d) #{'name': 'gaoqi', 'age': 18, 'job': 'techer'}

通过fromkeys创建值为空的字典

f = dict.fromkeys(['name','age','job'])
print(f) #结果:{'name': None, 'age': None, 'job': None}

3.3元素访问

通过 [键] 获得“值”。若键不存在,则抛出异常。

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = a['name']
print(b)

通过get()方法获得“值”。优点是:指定键不存在,返回None;也可以设定指定键不存在时默认返回的对象。推荐使用get()获取“值对象”

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = a.get('name')
c = a.get('gender','不存在')
print(b)
print(c)  #不存在

列出所有的键值对

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = a.items()
print(b) #dict_items([('name', 'gaoqi'), ('age', 18), ('job', 'programmer')])

列出所有的键,列出所有的值

a = {'name':'gaoqi','age':18,'job':'programmer'}
k = a.keys()
v = a.values()
print(k) #dict_keys(['name', 'age', 'job'])
print(v) #dict_values(['gaoqi', 18, 'programmer'])

len() 键值对的个数

a = {'name':'gaoqi','age':18,'job':'programmer'}
num = len(a)
print(num) #3

检测一个“键”是否在字典中

a = {'name':'gaoqi','age':18,'job':'programmer'}
print("name" in a) #True

3.4元素增删改

给字典新增“键值对”。如果“键”已经存在,则覆盖旧的键值对;如果“键”不存在,则新增“键值对”

a = {'name':'gaoqi','age':18,'job':'programmer'}
a['address']='西三旗1号院'
a['age']=16
print(a) 
#{'name': 'gaoqi', 'age': 16, 'job': 'programmer', 'address': '西三旗1号院'}

使用update()将新字典中所有键值对全部添加到旧字典对象上。如果key有重复,则直接覆盖

a = {'name':'gaoqi','age':18,'job':'programmer'}
b = {'name':'gaoxixi','money':1000,'gender':'男的'}
a.update(b)
print(a)
#{'name': 'gaoxixi', 'age': 18, 'job': 'programmer', 'money': 1000, 'gender': '男的'}

字典中元素的删除,可以使用**del()方法;或者clear()**删除所有键值对;**pop()**删除指定键值对,并返回对应的“值对象”

a = {'name':'gaoqi','age':18,'job':'programmer'}
del(a['name'])
print(a)    #{'age': 18, 'job': 'programmer'}
age = a.pop('age')
print(age)   #18

popitem() :随机删除和返回该键值对。字典是“无序可变序列”,因此没有第一个元素、最后一个元素的概念;popitem弹出随机的项,因为字典并没有"最后的元素"或者其他有关顺序的概念。若想一个接一个地移除并处理项,这个方法就非常有效(因为不用首先获取键的列表)

a = {'name':'gaoqi','age':18,'job':'programmer'}
r1 = a.popitem()
r2 = a.popitem()
r3 = a.popitem()
print(a)  #{}

3.5序列解包用于列表元组字典

序列解包可以用于元组、列表、字典。序列解包可以让我们方便的对多个变量赋值。
序列解包用于字典时,默认是对“键”进行操作; 如果需要对键值对操作,则需要使用items();如果需要对“值”进行操作,则需要使用values()

s = {'name':'gaoqi','age':18,'job':'teacher'}
name,age,job=s          #默认对键进行操作
print(name)  #name
name,age,job=s.items()      #对键值对进行操作
print(name)  #('name', 'gaoqi')
name,age,job=s.values()     #对值进行操作
print(name)  #gaoqi

3.6复杂表格数据存储

r1 = {"name":"高小一","age":18,"salary":30000,"city":"北京"}
r2 = {"name":"高小二","age":19,"salary":20000,"city":"上海"}
r3 = {"name":"高小五","age":20,"salary":10000,"city":"深圳"}

tb = [r1,r2,r3]#获得第二行的人的薪资
print(tb[1].get("salary"))#打印表中所有的的薪资
for i in range(len(tb)):  # i -->0,1,2
  print(tb[i].get("salary"))#打印表的所有数据
for i in range(len(tb)):		   print(tb[i].get("name"),tb[i].get("age"),tb[i].get("salary"),tb[i].get("city"))

3.7核心底层原理

主要包含两步,先存再取,字典对象的核心是散列表。散列表是一个稀疏数组(总是有空白元素的数组),数组的每个单元叫做bucket。每个bucket有两部分:一个是键对象的引用,一个是值对象的引用。
由于,所有bucket结构和大小一致,我们可以通过偏移量来读取指定bucket。

**将一个键值对放进字典的底层过程,**字典a对象创建完后,数组长度为8:要把”name”=”gaoqi”这个键值对放到字典对象a中,首先第一步需要计算键”name”的散列值。Python中可以通过hash()来计算。

bin(hash("name"))
'-0b1010111101001110110101100100101'

由于数组长度为8(若长度为16,则以4为单位),可以拿计算出的散列值的最右边3位数字作为偏移量,即“101”,十进制是数字5。查看偏移量5,对应的bucket是否为空。如果为空,则将键值对放进去。如果不为空,则依次取右边3位作为偏移量,即“100”,十进制是数字4。再查看偏移量为4的bucket是否为空。直到找到为空的bucket将键值对放进去。流程图如下:

python会根据散列表的拥挤程度扩容。“扩容”指的是:创造更大的数组,将原有内容拷贝到新数组中,接近2/3时,数组就会扩容。

根据键查找“键值对”的底层过程当调用a.get(“name”),就是根据键“name”查找到“键值对”,从而找到值对象“gaoqi”。仍然要首先计算“name”对象的散列值,和存储的底层流程算法一致,也是依次取散列值的不同位置的数字
假设数组长度为8,我们可以拿计算出的散列值的最右边3位数字作为偏移量,即101,十进制是数字5。我们查看偏移量5,对应的bucket是否为空。如果为空,则返回None。如果不为空,则将这个bucket的键对象计算对应散列值,和我们的散列值进行比较,如果相等。则将对应“值对象”返回。如果不相等,则再依次取其他几位数字,重新计算偏移量。依次取完后,仍然没有找到。则返回None。流程图如下:

3.8字典总结

1.字典在内存中开销巨大,典型的空间换时间。
2.键查询速度很快
3.往字典里面添加新键值对可能导致扩容,导致散列表中键的次序变化。因此,不要在遍历字典的同时进行字典的修改
4.键必须可散列
5.数字、字符串、元组,都是可散列的
6.自定义对象需要支持下面三点:

  • 支持hash()函数
  • 支持通过__eq__()方法检测相等性
  • 若a==b为真,则hash(a)==hash(b)也为真

4.集合

4.1特点

集合是无序可变,元素不能重复。实际上,集合底层是字典实现,集合的所有元素都是字典中的“键对象”,因此是不能重复的且唯一的。

4.2创建和删除

使用{}创建集合对象,并使用add()方法添加元素

a = {3,5,7}
a.add(9)  #{9, 3, 5, 7}

使用set(),将列表、元组等可迭代对象转成集合。如果原来数据存在重复数据,则只保留一个

a = ['a','b','c','b']
b = set(a) #{'b', 'a', 'c'}

remove()删除指定元素;clear()清空整个集合

a = {10,20,30,40,50}
a.remove(20)  #{10, 50, 40,30}

4.3交集并集差集运算

>>> a = {1,3,'sxt'}
>>> b = {'he','it','sxt'}
>>> a|b                 #并集
{1, 3, 'sxt', 'he', 'it'}
>>> a&b                 #交集
{'sxt'}
>>> a-b                 #差集
{1, 3}
>>> a.union(b)              #并集
{1, 3, 'sxt', 'he', 'it'}
>>> a.intersection(b)       #交集
{'sxt'}
>>> a.difference(b)         #差集
{1, 3}

5.练习

1.集合和字典有什么关系?
集合的所有元素都是字典中的“键对象”
2.创建一个字典对象,包含如下信息:
支出金额:300.15,支出日期:2018.10.18,支出人:高小七

a = {"支出金额":"300.15","支出日期":"2018","支出人":"高小七"}
print((a))

3.元组和列表有哪些共同点?有哪些不同点?
元组是不可以增加删除修改的,只可以查询;
元组的访问和处理速度比列表快;
元组可以作为字典的键,列表则永远不能作为字典的键使用;
列表属于可变序列,可以任意修改列表中的元素;
元组属于不可变序列,不能修改元组中的元素。

二、控制语句

1.控制语句和现实逻辑表达

分为三类:顺序、选择和循环。“顺序结构”代表“先执行a,再执行b”,“条件判断结构”代表“如果…,则…”,“循环结构”代表“如果…,则重复执行…”

2.选择结构(条件判断结构)

2.1单分支


if 条件表达式:
语句/语句块

  • 条件表达式:可以是逻辑表达式、关系表达式、算术表达式等等。
  • 语句/语句块:可以是一条语句,也可以是多条语句。多条语句,缩进必须对齐一致

在选择和循环结构中,条件表达式的值为False的情况如下:
False、0、0.0、空值None、空序列对象(空列表、空元组、空集合、空字典、空字符​ 串)、空range对象、空迭代对象。
其他情况,均为True。Python所有的合法表达式都可以看做条件表达式,甚至包括函数调用的表达式。

if 3:  #整数作为条件表达式
  print("ok")
a = []  #列表作为条件表达式,由于为空列表,是False
if a:
  print("空列表,False")
  
s = "False"  #非空字符串,是True
if s:
  print("非空字符串,是True")
c = 9
if 3<c<20:
  print("3)
if 3<c and c<20:
  print("3)if True:    #布尔值
  print("True")

条件表达式中,不能有赋值操作符=
在Python中,条件表达式不能出现赋值操作符=,避免了其他语言中经常误将关系运算符==写作赋值运算符=带来的困扰。如下代码将会报语法错误:

if 3 < c and (c=20):  #直接报语法错误!
 print("赋值符不能出现在条件表达式中")

2.2双分支选择结构


if 条件表达式:
语句1/语句块1
else:
语句2/语句块2

num = input("输入一个数字:")
if int(num)<10:
  print(num)
else:
  print("数字太大")

三元条件运算符

num = input("请输入一个数字")
print( num if int(num)<10 else "数字太大")

2.3多分支选择结构


【操作】输入一个学生的成绩,将其转化成简单描述:不及格(小于60)、及格(60-79)、良好(80-89)、优秀(90-100)

score = int(input("请输入分数"))
grade = ''
if(score<60):
  grade = "不及格"
if(60<=score<80):
  grade = "及格"
if(80<=score<90):
  grade = "良好"
if(90<=score<=100):
  grade = "优秀"
print("分数是{0},等级是{1}".format(score,grade))

(利用多分支结构)
多分支结构,几个分支之间是有逻辑关系的,不能随意颠倒顺序

score = int(input("请输入分数"))
grade = ''
if score<60 :
  grade = "不及格"
elif score<80 :
  grade = "及格"
elif score<90 :
  grade = "良好"
elif score<=100:
  grade = "优秀"print("分数是{0},等级是{1}".format(score,grade))

2.4选择结构的嵌套

输入一个分数。分数在0-100之间。90以上是A,80以上是B,70以上是C,60以上是D。60以下是E

score = int(input("请输入一个在0-100之间的数字:"))
grade = ""
if score>100 or score<0:
  score = int(input("输入错误!请重新输入一个在0-100之间的数字:"))
else:
  if score>=90:
    grade = "A"
  elif score>=80:
    grade = 'B'
  elif score>=70:
    grade = 'C'
  elif score>=60:
    grade = 'D'
  else:
    grade = 'E'print("分数为{0},等级为{1}".format(score,grade))

简洁写法:

score = int(input("请输入一个在0-100之间的数字:"))
degree = "ABCDE"
num = 0
if score>100 or score<0:
  score = int(input("输入错误!请重新输入一个在0-100之间的数字:"))
else:
  num = score//10
  if num<6:num=5print("分数是{0},等级是{1}".format(score,degree[9-num]))

3.循环结构

3.1 基本含义

循环结构用来重复执行一条或多条语句。表达这样的逻辑:如果符合条件,则反复执行循环体里的语句。在每次执行完后都会判断一次条件是否为True,如果为True则重复执行循环体里的语句。图示如下:

循环体里面的语句至少应该包含改变条件表达式的语句,以使循环趋于结束;否则,就会变成一个死循环。

3.2while循环

while 条件表达式:
循环体语句

【操作】利用while循环打印从0-10的数字

num = 0
while num<=10:
  print(num)
  num += 1

利用while循环,计算1-100之间数字的累加和;计算1-100之间偶数的累加和,计算1-100之间奇数的累加和

num = 0
sum_all = 0     #1-100所有数的累加和
while num<=100:
  sum_all += num
  num += 1     #迭代,改变条件表达式,使循环趋于结束print("1-100所有数的累加和",sum_all)

5050

3.3for循环和可迭代对象遍历

for 变量 in 可迭代对象:
循环体语句

Python包含以下几种可迭代对象:

  • 序列。包含:字符串、列表、元组、字典、集合
  • 迭代器对象(iterator)
  • 生成器函数(generator)
  • 文件对象

【遍历字典】

d = {'name':'gaoqi','age':18,'address':'西三旗001号楼'}
for x in d: #遍历字典所有的key
  print(x)
for x  in d.keys():#遍历字典所有的key
  print(x)
for x  in d.values():#遍历字典所有的value
  print(x)
for x  in d.items():#遍历字典所有的"键值对"
  print(x)

range对象
range对象是一个迭代器对象,用来产生指定范围的数字序列。格式为:
range(start, end [,step])
生成的数值序列从start开始到end结束(⚠️不包含end)。若没有填写start,则默认从0开始。step是可选的步长,默认为1。如下是几种典型示例:
for i in range(10) 产生序列:0 1 2 3 4 5 6 7 8 9
for i in range(3,10) 产生序列:3 4 5 6 7 8 9
for i in range(3,10,2) 产生序列:3 5 7 9
【操作】利用for循环,计算1-100之间数字的累加和;计算1-100之间偶数的累加和,计算1-100之间奇数的累加和。

sum_all = 0     #1-100所有数的累加和
sum_even = 0    #1-100偶数的累加和
sum_odd = 0     #1-100奇数的累加和
for num in range(101):
  sum_all += num
  if num%2==0:sum_even += num
  else:sum_odd += num
 
print("1-100累加总和{0},奇数和{1},偶数和{2}".format(sum_all,sum_odd,sum_even))

3.4嵌套循环

一个循环体内可以嵌入另一个循环,一般称为“嵌套循环”,或者“多重循环”。

for x in range(5):
  for y in range(5):
    print(x,end="\t")
  print()  #仅用于换行


【打印九九乘法表】

for m in range(1,10):
  for n in range(1,m+1):
    print("{0}*{1}={2}".format(m,n,(m*n)),end="\t")
  print()


ps:若在第二层循环里for n in range(1,m),就会出错,没有1*1=1

【用列表和字典存储下表信息,并打印出表中工资高于15000的数据】

r1= dict(name="高小一",age=18,salary=30000,city="北京")
r2= dict(name="高小二",age=19,salary=20000,city="上海")
r3= dict(name="高小三",age=20,salary=10000,city="深圳")
tb = [r1,r2,r3]

for x in tb:
  if x.get("salary")>15000:
    print(x)

3.5break语句

break语句可用于while和for循环,用来结束整个循环。当有嵌套循环时,break语句只能跳出最近一层的循环。

while True:
  a = input("请输入一个字符(输入Q或q结束)")
  if a.upper()=='Q':  #a == "Q" or a == "q" 
    print("循环结束,退出")
    break
  else:
    print(a)

3.6continue语句

continue语句用于结束本次循环,继续下一次。多个循环嵌套时,continue也是应用于最近的一层循环。

【操作】要求输入员工的薪资,若薪资小于0则重新输入。最后打印出录入员工的数量和薪资明细,以及平均薪资

empNum = 0
salarySum= 0
salarys = []
while True:
  s = input("请输入员工的薪资(按Q或q结束)")if s.upper()=='Q':
    print("录入结束")
    break #若不加入则无法跳出循环
  if float(s)<0:
    print("无效!继续录入!")
    continue
  print("录入成功!")
  empNum +=1
  salarys.append(float(s))
  salarySum += float(s)print("员工数{0}".format(empNum))
print("录入薪资:",salarys)
print("总发薪资:",salarySum)
print("平均薪资{0}".format(salarySum/empNum))

3.7循环中的else子句

while、for循环可以附带一个else语句(可选)。如果for、while语句没有被break语句结束,则会执行else子句,否则不执行。语法格式如下:

while 条件表达式:
    循环体
else:
    语句块
或者:
for 变量 in 可迭代对象:
    循环体
else:
    语句块

【操作】员工一共4人。录入这4位员工的薪资。全部录入后,打印提示“您已经全部录入4名员工的薪资”。最后,打印输出录入的薪资和平均薪资

salarySum= 0
salarys = []
for i in range(4):
  s = input("请输入一共4名员工的薪资(按Q或q中途结束)")if s.upper()=='Q':
    print("录入完成,退出")
    break
  if float(s)<0:
    continue
​
  salarys.append(float(s))
  salarySum += float(s)else:
  print("您已经全部录入4名员工的薪资")print("录入薪资:",salarys)
print("平均薪资{0}".format(salarySum/4))

3.8循环代码优化

  • 尽量减少循环内部不必要的计算
  • 嵌套循环中,尽量减少内层循环的计算,尽可能向外提
  • 局部变量查询较快,尽量使用局部变量
  • 连接多个字符串,使用join()而不使用+
  • 列表进行元素插入和删除,尽量在列表尾部操作
#循环代码优化测试
import time
​
start = time.time()
for i in range(1000):
  result = []
  for m in range(10000):
    c = i * 1000      #提到外部循环
    #result = result + [m * 100] #不使用拼接,会产生大量新对象
    result.append(c+m*100)
end = time.time()
print("耗时:{0}".format((end-start)))print("简单循环优化后...")
start2 = time.time()
for i in range(1000):
  result = []
  c = i*1000
  for m in range(10000):
    result.append(c+m*100)
​
end2 = time.time()
print("耗时:{0}".format((end2-start2)))

3.9zip()并行迭代多个序列

我们可以通过zip()函数对多个序列进行并行迭代,zip()函数在最短序列“用完”时就会停止。

names = ("高淇","高老二","高老三","高老四")
ages = (18,16,20,25)
jobs = ("老师","程序员","公务员")for name,age,job in zip(names,ages,jobs):
  print("{0}--{1}--{2}".format(name,age,job))#不适用zip,也可以并行迭代多个序列
for i in range(min(len(names),len(ages),len(jobs))):
  print("{0}--{1}--{2}".format(names[i],ages[i],jobs[i]))

3.10推导式创建序列

推导式是从一个或者多个迭代器快速创建序列的一种方法。它可以将循环和条件判断结合,从而避免冗长的代码。
列表推导式

[表达式 for item in 可迭代对象 ]
[x for x in range(1,5)] #[1, 2, 3, 4]
[x*2 for x in range(1,5)] #[2, 4, 6, 8]
[x*2 for x in range(1,20) if x%5==0 ] #[10, 20, 30]
[a for a in "abcdefg"] #['a', 'b', 'c', 'd', 'e', 'f', 'g']
#可以使用两个循环,使用zip并行迭代
cells = [(row,col) for row,col in zip(range(1,10),range(101,110))]
print(cells)

a = [x for x in range(1,10) if x%2==0]
print(a)
#不适用推导式,生成列表。二者对比。体现推导式的优势
b = []
for x in range(1,10):
  if x%2==0:
    b.append(x)
print(b)

字典推导式
{key_expression: value_expression for 表达式 in 可迭代对象}
类似于列表推导式,字典推导也可以增加if条件判断、多个for循环。

values = ["北京","上海","深圳","广州"]
cities = {id*100:city for id,city in zip(range(1,5),values)}
print(cities)

生成字典对象:{100: ‘北京’, 200: ‘上海’, 300: ‘深圳’, 400: ‘广州’}

统计文本中字符出现的次数:

my_text = ' i love you, i love sxt, i love gaoqi'
char_count = {c:my_text.count(c) for c in my_text}
print(char_count)

集合推导式
{表达式 for item in 可迭代对象 }
或者:{表达式 for item in 可迭代对象 if 条件判断}

生成器推导式(不直接生成元组)

(x for x in range(1,100) if x%9==0)

<generator object at 0x0000000002BD3048>

提示的是“一个生成器对象”。显然,元组是没有推导式的。
一个生成器只能运行一次。第一次迭代可以得到数据,第二次迭代发现数据已经没有了。

gnt = (x for x in range(1,100) if x%9==0)
for x in gnt:
  print(x,end=' ,')
for x in gnt:
  print(x,end=' ')

4.综合练习

【绘制多个同心圆】

import turtle
​
p = turtle.Pen() #画笔对象
radius = [x*10 for x in range(1,11)]  #10,20,30,40...
my_colors = ("red","green","yellow","black")
p.width(4)
for r,i in zip(radius,range(len(radius))):
  p.penup()
  p.goto(0,-r)
  p.pendown()
  p.color(my_colors[i%len(my_colors)])
  p.circle(r)
​
turtle.done() #程序执行完毕,窗口在

三、函数

1.基本定义

函数是可重用的程序代码块。函数的作用,不仅可以实现代码的复用,更能实现代码的一致性。一致性指的是,只要修改函数的代码,则所有调用该函数的地方都能得到体现。
函数(function)是一个程序由一个一个的任务组成;函数就是代表一个任务或者一个功能(function),是代码复用的通用机制。
Python函数分为如下几类:
内置函数:我们前面使用的str()、list()、len()等这些都是内置函数,我们可以拿来直接使用。
标准库函数:我们可以通过import语句导入库,然后使用其中定义的函数
第三方库函数:Python社区也提供了很多高质量的库。下载安装这些库后,也是通过import语句导入,然后可以使用这些第三方库的函数
用户自定义函数:用户自己定义的函数,显然也是开发中适应用户自身需求定义的函数。

定义和调用

def 函数名 ([参数列表]) :
    '''文档字符串'''
    函数体/若干语句
def add(a,b,c):
  '''完成三个数的加法,并返回他们的和'''
  sum = a+b+c
  print("{0}、{1}、{2}三个数的和是:{3}".format(a,b,c,sum))
  return sum
add(10,20,30)
add(30,40,50)

主要要点:
1.使用def来定义函数,然后就是一个空格和函数名称;Python执行def时,会创建一个函数对象,并绑定到函数名变量上。
2.参数列表
圆括号内是形式参数列表,有多个参数则使用逗号隔开
定义时的形式参数不需要声明类型,也不需要指定函数返回值类型
调用时的实际参数必须与形参列表一一对应
3.return返回值
如果函数体中包含return语句,则结束函数执行并返回值;
如果函数体中不包含return语句,则返回None值。

https://www.ycpai.cn/wenda/RDPmnpn4.html
4.调用函数之前,必须要先定义函数,即先调用def创建函数对象
内置函数对象会自动创建
标准库和第三方库函数,通过import导入模块时,会执行模块中的def语句

2.形参和实参

  • 圆括号内是形式参数列表,有多个参数则使用逗号隔开
  • 定义时的形式参数不需要声明类型,也不需要指定函数返回值类型
  • 调用时的实际参数必须与形参列表一一对应

【操作】定义一个函数,实现两个数的比较,并返回较大的值

def printMax(a,b):
  '''实现两个数的比较,并返回较大的值'''
  if a>b:
    print(a,'较大值')
    return a
  else:
    print(b,'较大值')
    return b
printMax(10,20)
printMax(30,5)

printMax函数中,在定义时写的printMax(a,b)。a和b称为“形式参数”,简称“形参”。形式参数是在定义函数时使用的, 形式参数的命名要符合“标识符”命名规则。
在调用函数时,传递的参数称为“实际参数”,简称“实参”。上面代码中,printMax(10,20),10和20就是实际参数。

文档字符串(函数的注释)
建议在函数体开始的部分附上函数定义说明,这就是“文档字符串”,也有人成为“函数的注释”。我们通过三个单引号或者三个双引号来实现,中间可以加入多行文字进行说明。

def print_star(n):
  '''
   根据传入的n,打印多个星号
   :param n: 传入的数字
   :return:  n个星号拼接的字符串
   '''
  s = "*"*n
  print(s)
  return s

help(print_star)
print(print_star.__doc__)

3.返回值详解

  • 如果函数体中包含return语句,则结束函数执行并返回值
  • 如果函数体中不包含return语句,则返回None值
  • 要返回多个值,使用列表、元组、字典、集合将多个值“存起来”即可

【操作】定义一个打印n个星号的无返回值的函数

def print_star(n):
  print("*"*n)
​
print_star(5)

【操作】定义一个返回两个数平均值的函数

def my_avg(a,b):
  return (a+b)/2#如下是函数的调用
c = my_avg(20,30)
print(c)

【操作】返回一个列表

def printShape(n):
  s1 = "#"*n
  s2 = "$"*n
  return [s1,s2]

s = printShape(5)
print(s)

4.函数也是对象

Python中,“一切都是对象”。实际上,执行def定义函数后,系统就创建了相应的函数对象。

def print_star(n):         
  print("*"*n)print(print_star)
print(id(print_star))
​
c = print_star
c(3)

上面代码执行def时,系统中会创建函数对象,并通过print_star这个变量进行引用:

执行c=print_star后,将print_star变量的值赋给了变量c,内存图变成:
变量c和print_star都是指向了同一个函数对象。因此,执行c(3)和执行print_star(3)的效果是完全一致的。圆括号意味着调用函数。在没有圆括号的情况下,Python会把函数当做普通对象。

zhengshu = int
zhengshu("234")

将内置函数对象int()赋值给了变量zhengshu,这样zhengshu和int都是指向了同一个内置函数对象。

5.变量的作用域(全局和局部)

全局变量:

  • 在函数和类定义之外声明的变量。作用域为定义的模块,从定义位置开始直到模块结束。
  • 全局变量降低了函数的通用性和可读性。应尽量避免全局变量的使用。
  • 在函数内改变全局变量的值,使用global声明

局部变量:

  • 在函数体中(包含形式参数)声明的变量。
  • 局部变量的引用比全局变量快,优先考虑使用
  • 如果局部变量和全局变量同名,则在函数内隐藏全局变量,只使用同名的局部变量

【操作】全局变量的作用域测试

a = 100     #全局变量
def f1():
  global a  #如果要在函数内改变全局变量的值,增加global关键字声明
  print(a)  #打印全局变量a的值  
  a = 300   
f1()
f1()
print(a)


【操作】全局变量和局部变量同名测试

a=100
def f1():
  a = 3   #同名的局部变量
  print(a)
  
f1()  
print(a)  #a仍然是100,没有变化

【操作】 输出局部变量和全局变量

a = 100def f1(a,b,c):
  print(a,b,c)
  print(locals())      #打印输出的局部变量
  print("#"*20)
  print(globals())      #打印输出的全局变量
​
f1(2,3,4)

2 3 4
{‘c’: 4, ‘b’: 3, ‘a’: 2}
####################
{‘name’: ‘main’, ‘doc’: None, ‘package’: None, ‘loader’: <class ‘_frozen_importlib.BuiltinImporter’>, ‘spec’: None, ‘annotations’: {}, ‘builtins’: <module ‘builtins’ (built-in)>, ‘file’: ‘E:\PythonExec\if_test01.py’, ‘a’: 100, ‘f1’: <function f1 at 0x0000000002BB8620>}

效率测试:
局部变量的查询和访问速度比全局变量快,优先考虑使用,尤其是在循环的时候。

import time
​
a = 1000
def test01():
  start = time.time()
  global a
  for i in range(100000000):
    a += 1
  end = time.time()
  print("耗时{0}".format((end-start)))def test02():
  c = 1000
  start = time.time()
  for i in range(100000000):
    c += 1
  end = time.time()
  print("耗时{0}".format((end-start)))
​
test01()
test02()
print(globals())

6.参数的传递

函数的参数传递本质上就是:从实参到形参的赋值操作。Python中“一切皆对象”,所有的赋值操作都是“引用的赋值”。所以,Python中参数的传递都是**“引用传递”**,不是“值传递”。
具体操作时分为两类:

  • 对“可变对象”进行“写操作”,直接作用于原对象本身。
  • 对“不可变对象”进行“写操作”,会产生一个新的“对象空间”,并用新的值填充这块空间。

可变对象有:字典、列表、集合、自定义的对象
不可变对象有:数字、字符串、元组、function

传递可变对象的引用
传递参数是可变对象(例如:列表、字典、自定义的其他可变对象等),实际传递的还是对象的引用。在函数体中不创建新的对象拷贝,而是可以直接修改所传递的对象,是同一个对象
【操作】参数传递:传递可变对象的引用

b = [10,20]
def f2(m):
  print("m:",id(m))    #b和m是同一个对象
  m.append(30)  #由于m是可变对象,不创建对象拷贝,直接修改这个对象

f2(b)
print("b:",id(b))
print(b)



传递不可变对象的引用
传递参数是不可变对象(例如:int、float、字符串、元组、布尔值),实际传递的还是对象的引用。在”赋值操作”时,由于不可变对象无法修改,系统会新创建一个对象。
【操作】参数传递:传递不可变对象的引用

a = 100
def f1(n):
  print("n:",id(n))    #传递进来的是a对象的地址
  n = n+200      #由于a是不可变对象,因此创建新的对象n
  print("n:",id(n))  #n已经变成了新的对象
  print(n)
f1(a)
print("a:",id(a))

7.浅拷贝和深拷贝

浅拷贝(copy):拷贝对象,但不拷贝子对象的内容,只是拷贝子对象的引用。
深拷贝(deepcopy:拷贝对象,并且会连子对象的内存也全部(递归)拷贝一份,对子对象的修改不会影响源对象

import copy

def testCopy():
  '''测试浅拷贝'''
  a = [10, 20, [5, 6]]
  b = copy.copy(a)print("a", a)
  print("b", b)
  b.append(30)
  b[2].append(7)
  print("浅拷贝......")
  print("a", a)
  print("b", b)

testCopy()

a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
浅拷贝…
a [10, 20, [5, 6, 7]]
b [10, 20, [5, 6, 7], 30]

def testDeepCopy():
  '''测试深拷贝'''
  a = [10, 20, [5, 6]]
  b = copy.deepcopy(a)print("a", a)
  print("b", b)
  b.append(30)
  b[2].append(7)
  print("深拷贝......")
  print("a", a)
  print("b", b)
​
testDeepCopy()

a [10, 20, [5, 6]]
b [10, 20, [5, 6]]
深拷贝…
a [10, 20, [5, 6]]
b [10, 20, [5, 6, 7], 30]

8.传递不可变对象含可变子对象

#传递不可变对象时。不可变对象里面包含的子对象是可变的。则方法内修改了这个可变对象,源对象也发生了变化。
​
a = (10,20,[5,6])
print("a:",id(a))def test01(m):
  print("m:",id(m))
  m[2][0] = 888
  print(m)
  print("m:",id(m))
​
test01(a)
print(a)

a: 41611632
m: 41611632
(10, 20, [888, 6])
m: 41611632
(10, 20, [888, 6])

9.参数的类型

9.1位置参数

函数调用时,实参默认按位置顺序传递,需要个数和形参匹配。按位置传递的参数,称为:“位置参数”。

def f1(a,b,c):
  print(a,b,c)

f1(2,3,4)
f1(2,3)   #报错,位置参数不匹配

2 3 4
Traceback (most recent call last):
File “E:\PythonExec\if_test01.py”, line 5, in
f1(2,3)
TypeError: f1() missing 1 required positional argument: 'c

9.2默认值参数

可以为某些参数设置默认值,这样这些参数在传递时就是可选的。称为“默认值参数”。默认值参数放到位置参数后面

def f1(a,b,c=10,d=20):  #默认值参数必须位于普通位置参数后面
  print(a,b,c,d)
f1(8,9)
f1(8,9,19)
f1(8,9,19,29)

9.3命名参数

按照形参的名称传递参数,称为“命名参数”,也称“关键字参数”。

def f1(a,b,c):
  print(a,b,c)
f1(8,9,19)     #位置参数
f1(c=10,a=20,b=30) #命名参数

9.4可变参数

  • *param(一个星号),将多个参数收集到一个“元组”对象中。
  • **param(两个星号),将多个参数收集到一个“字典”对象中。
    【操作】测试可变参数处理(元组、字典两种方式)
def f1(a,b,*c):
  print(a,b,c)
f1(8,9,19,20)
def f2(a,b,**c):
  print(a,b,c)
f2(8,9,name='gaoqi',age=18)def f3(a,b,*c,**d):
  print(a,b,c,d)
f3(8,9,20,30,name='gaoqi',age=18)

8 9 (19, 20)
8 9 {‘name’: ‘gaoqi’, ‘age’: 18}
8 9 (20, 30) {‘name’: ‘gaoqi’, ‘age’: 18}

9.5强制命名参数

在带星号的“可变参数”后面增加新的参数,必须在调用的时候“强制命名参数”。

def f1(*a,b,c):
  print(a,b,c)
#f1(2,3,4)  #会报错。由于a是可变参数,将2,3,4全部收集。造成b和c没有赋值。
f1(2,b=3,c=4) 

(2,) 3 4

10.lambda表达式和匿名函数

lambda表达式可以用来声明匿名函数。lambda函数是一种简单的、在同一行中定义函数的方法。lambda函数实际生成了一个函数对象。
lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的计算结果就是函数的返回值。
lambda arg1,arg2,arg3… : <表达式>
arg1 arg2 arg3为函数的参数。<表达式>相当于函数体。运算结果是:表达式的运算结果。

f = lambda a,b,c:a+b+c
print(f)
print(f(2,3,4))

g = [lambda a:a*2,lambda b:b*3,lambda c:c*4]
print(g[0](6),g[1](7),g[2](8))

<function at 0x0000000002BB8620>
9
12 21 32

11.eval()函数的用法和注入安全隐患问题

将字符串str当成有效的表达式(源代码)来求值并返回计算结果。
eval(source[, globals[, locals]]) -> value

  • source:一个Python表达式或函数compile()返回的代码对象
  • globals:可选。必须是dictionary
  • locals:可选。任意映射对象
#测试eval()函数
s = "print('abcde')"
eval(s)
​
a = 10
b = 20
c = eval("a+b")
print(c)
​
dict1 = dict(a=100,b=200)
d = eval("a+b",dict1)
print(d)

abcde
30
300

一般不建议使用。

12.递归函数

12.1基本概念

自己调用自己的函数,在函数体内部直接或间接的自己调用自己。每个递归函数必须包含两个部分:

  • 终止条件:表示递归什么时候结束。一般用于返回值,不再调用自己。
  • 递归步骤:把第n步的值和第n-1步相关联。
def my_recursion(n):
  print("start:" + str(n))
  if n == 1:
    print("recursion over!")
  else:
    my_recursion(n - 1)
  print("end:" + str(n))
my_recursion(3)

start:3
start:2
start:1
recursion over!
end:1
end:2
end:3

12.2阶乘计算

def factorial(n):
  if n==1:
    return 1
  return n*factorial(n-1)print(factorial(5))

12.3嵌套函数

嵌套函数:在函数内部定义的函数

def outer():
  print('outer running...')def inner():
    print('inner running...')
  inner()
outer()

inner()就是定义在outer()函数内部的函数。inner()的定义和调用都在outer()函数内部。

一般在以下情况下使用嵌套函数:

  • 封装 - 数据隐藏
  • 外部无法访问“嵌套函数”。
  • 贯彻 DRY(Don’t Repeat Yourself) 原则
  • 嵌套函数,可以让我们在函数内部避免重复代码。
  • 闭包
def printName(isChinese,name,familyName):
  def inner_print(a,b):
    print("{0} {1}".format(a,b))if isChinese:
    inner_print(familyName,name)
  else:
    inner_print(name,familyName)

printName(True,"小七","高")
printName(False,"George","Bush")

12.4nonlocal和global


nonlocal 用来在内部函数中,声明外层的局部变量。
global 函数内声明全局变量,然后才使用全局变量。

#测试nonlocal、global关键字的用法
a = 100def outer():
  b = 10def inner():
    nonlocal b     #声明外部函数的局部变量
    print("inner b:",b)
    b = 20global a      #声明全局变量
    a = 1000
​
  inner()
  print("outer b:",b)
​
outer()
print("a:",a)

12.5LEGB规则

Local 指的就是函数或者类的方法内部
Enclosed 指的是嵌套函数(一个函数包裹另一个函数,闭包)
Global 指的是模块中的全局变量
Built in 指的是Python为自己保留的特殊名称

如果某个name映射在局部local命名空间中没有找到,接下来就会在闭包作用域enclosed进行搜索,如果闭包作用域也没有找到,Python就会到全局global命名空间中进行查找,最后会在内建built-in命名空间搜索 (如果一个名称在所有命名空间中都没有找到,就会产生一个NameError)

13.练习

13.1定义一个函数实现反响输出一个整数。比如:输入3245,输出5432

str_num = input("请输入一个整数:")
f = lambda n:print(n[::-1])
f(str_num)

13.2编写一个函数,计算下面的数列:

def sum(n):
  sum = 0
  for i in range(1,n+1):
    sum +=i/(i+1)
  print((sum))

num = int(input("请输入一个整数:"))
sum(num)

13.3输入三角形三个顶点的坐标,若有效则计算三角形的面积;如坐标无效,则给出提示

import math
def dis(a,b):
    '''计算两个点之间的距离'''
    return math.sqrt((a[0]-b[0])**2+(a[1]-b[1])**2)
def judge(a,b,c):
    '''判断前两边之和是否大于第三边'''
    if dis(a,b)+dis(a,c)>dis(b,c):
        return True
    else:
        return False


a = []
while len(a)<3:
    b = []
    point = input("请输入point{0}中x,y的值,用,分开:".format(len(a)+1))
    point_array = point.split(",")
    point_x, point_y = float(point_array[0]),float(point_array[1])
    b.append(point_x)
    b.append(point_y)
    a.append(b)
else:
    if judge(a[0],a[1],a[2]) and judge(a[0],a[2],a[1]) and judge(a[1],a[2],a[0]):
        print("三角形面积为{0}".format((a[0][0]*a[1][1]+a[1][0]*a[2][1]+a[2][0]*a[0][1]-a[0][0]*a[2][1]-a[1][0]*a[0][1]-a[2][0]*a[1][1])/2))
    else:
        print("输入的三个点({0},{1});({2},{3});({4},{5})无法构成三角形".format(a[0][0], a[0][1], a[1][0], a[1][1], a[2][0], a[2][1]))

总结

本篇笔记主要记录了序列、控制语句和函数的使用,对于函数的理解还需要加深,return语句需要再消化,不能很好地编写完成函数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值