9.对象和值
下面的a和b有两种可能的状态
一种可能是,a 和b 引用着不同的对象,它们的值相同。另一种情况下,它们指向同
一个对象。
a = 'stan'
b = 'stan'
# 判断a和b是否指向同一个字符串
print(a is b)
# 很明显是指向的同一个地址
print(id(a),id(b))
对一个列表进行修改
t4 = [1,2 ,4]
def bad(t):
t = t[1:]
return t
# 这个函数不会改变外面的t4,
print(bad(t4))
print(t4)
🚩在bad的开头,t 和t4 指向同一个列表。在函数最后,t 指向了一个
新的列表,但t4 仍然指向原先的那个没有改变的列表。
这个函数不会修改原始列表。
t4 = [1,2 ,4]
def tail(t):
return t[1:]
t = tail(t4)
print(t)
range的使用
数range()让你能够轻松地生成一系列的数字
举个栗子
li = list(range(1, 10))
print(li)
步长
range(起始位置:结束位置:步长)
默认步长是1
起始位置 < 结束位置,步长是正数
起始位置 > 结束位置,步长是负数
步长为负数实现倒序排列
li = list(range(1, 10, 2))
print(li)
li = list(range(10, 0, -1))
print(li)
li = list(range(10, 0, -1))
print(li)
11.元组
目标
- 展示列表、字典和元组三者如何一起工作。
- 很有用的可变长参数列表功能:收集操作符和分散操作符。
(1)不可变
元组是值的一个序列。其中的值可以是任何类型,并且按照整数下标索引,所以从这 方面看,元组和列表很像。元组和列表之间的重要区别是,元组是不可变的。
语法:
# 元组就是用(逗号)分隔的一列值(有的话需要仔细的琢磨哦~)
t = '1', '3', 5, 9
print(t)
# 虽然不是必需的,但是我们常常用括号括起来
t = ('1', '3', 5, 9)
print(t)
如果你想输出一个元素的元组
t1 = ('1')
t2 = '1',
print(t1)
print(type(t1))
print(type(t2))
t3 = tuple(t1)
print(t3)
运行上面的代码,找不同。
🚩小结:
元组就是用(逗号)分隔的一列值,上面的代码可以看出,使用tuple方法后,t1
输出的值是 ('1',)
如果参数是一个序列(字符串、列表或者元组),结果就是一个包含序列的元素的元 组:
st = tuple('lupins')
print(st)
❌因为tuple 是内置函数的名称,所以应当避免用它作为变量名称。
运算符使用
关系运算符适用于元组和其他序列。
print( (0, 1, 2) < (0, 3, 4))
Python从比较每个序列的第一个元素开始。如果 它们相等,它就继续比较下一个元素,依次类推,直到它找到不同元素为止。
(2)元组赋值
在做算法题时,时常会用到交换两个变量的值,传统的赋值方式,需要使用一个临时变量。
a = 2
b = 3
# 交换值
temp = a
a = b
b = temp
这种解决方案很笨拙,而元组赋值 则更优雅:
a = 2
b = 3
a, b = b, a
print(a, b)
🚩 第三行,左边是一个变量的元组,右边是表达式的元组,。每个值会被赋值给相应的变量。右边 所有的表达式,都会在任何赋值操作进行之前完成求值。类似得用法很多,需要自己在实践中摸索,大胆实践。
⚠但是左右两边的值的个数必须得相同
❌a, b = 1,2,3
(3)作为返回值的元组
严格的讲,函数只能返回一个值,但如果返回值是元组的话,效果和返回多个值差不 多。例如,如果将两个整数相除,得到商和余数,那么先计算x/y 再计算x%y 并不高效。 更好的方法是同时计算它们。
python内置函数:
divmod
接收两个参数,并返回两个值的元组,即商和余数。可以将结果存 为一个元组:
builtins.py
内置函数:
def divmod(x, y): # known case of builtins.divmod
""" Return the tuple (x//y, x%y). Invariant: div*y + mod == x. """
return (0, 0)
使用:
t = divmod(7,3)
print(t)
结果:
或者可以使用元组赋值来分别存储结果中的元素
val, mod = divmod(7,3)
print(mod)
来演示一个冗余的操作,主要是利于理解
def mod_val(a,b):
val, mod = divmod(a,b)
return val,mod
print(mod_val(7,3))
#最后得到的结果和上面元组赋值一样的,但是这里想展示的是返回一个元组的函数
(4)可变长参数元组
函数可以接收不定个数的参数。以* 开头的参数名会收集 (gather)所有的参数到一 个元组上。
来写一个接收任意个数的参数并打印它们:
def print_all(*args):
print(args)
print_all("231adadsdad",2312)
#回得到一个元组
还是以divmod
这个函数为例:
收集的反面是分散 (scatter)。如果有一个序列的值而想将它们作为可变长参数传入 到函数中,可以使用* 操作符。
因为divmod
只允许传入两个值,所以我们不能传入元组,不信可以试试。但是我们可以将元组分散:
t = (7 , 3)
tt = divmod(*t)
print(tt)
结果:
🚩python很多内置函数都是提供可变长参数元组,比如max,查看方法:在pycharm
里面按住CTRL
再鼠标左点。
(5)列表和元组
zip 是一个内置函数,接收两个或多个序列,并返回一个元组列表。每个元组包含来 自每个序列中的一个元素。这个函数的名字取自拉链(zipper),它可以将两行链牙交替 连接起来。
(6)序列的序列
列表比元组更加通用,主要因为它是可变的。但也有一些情况下你可能会优先选择元 组。
- 在有些环境中,如返回语句中,创建元组比创建列表从语法上说更容易。
- 如果需要用序列作为字典的键,则必须使用不可变类型,如元组或字符串。
- 如果你要向函数传入一个序列作为参数,使用元组可能会减少潜在的由假名导致 的不可预知行为。
🚩因为元组是不可变的,它们不提供类似sort 和reverse 之类的方法,这些方法修改 现有的序列。但Python也提供了内置函数sorted ,可以接收任何序列作为参数,并按排 好的顺序返回带有同样元素的新列表。
1.字典
主要介绍三种存储方式
存储字典的列表、存储列表的字典和存储字典的字典。
字典是没有索引的
(1)去重
字典自动去掉相同键的键值对
alien_0 = {'color': 'green', 'points': 5, 'points': 5}
print(alien_0)
(2)访问字典的值和修改
没什么好说的这些
alien_0 = {'color': 'green', 'points': 5, 'points': 5}
alien_0['name'] = 'stan'
alien_0['character'] = 'outgoing'
alien_0['family'] = ['1', '2']
print(alien_0['family'])
(3)删除键值对
对于字典中不再需要的信息,可使用del语句将相应的键—值对彻底删除。使用del语句时,
必须指定字典名和要删除的键。
(4)字典做计数器
统计字符串中字母的个数
def hub(x):
d =dict()
for i in x :
if i in d :
d[i] += 1
else:
d[i] = 1
return d
print(hub("aacde"))
(5)反向查找
给定一个字典d 和键k ,找到对应的值v = d[k] 非常容易。这个操作称为查找
(lookup)。
但是如果有v ,而想找到k 时怎么办?这里有两个问题:首先,可能存在多个键映射
到同一个值v 上。随不同的应用场景,也许可以挑其中一个,或者也许需要建立一个列表
来保存所有的键。其次,并没有可以进行反向查找 的简单语法,你需要使用搜索(如果你学过二分查找,
那么就可以找到你需要的值了)
alien_0 = {'color': 'green', 'points': 5, 'singer':'drake','age':5}
# 找到的第一个符合条件的数
def reverse (d, v):
for k in d:
if d[k] == v:
return k
raise LookupError()
print(reverse(alien_0, 5))
🚩raise 语句 会生成一个异常;在这个例子里它生成一个LookupError
,这是一个内置异常,通常用来表示查找操作失败。(不懂先不用管,或者百度)
(6)字典与列表
来做一个小栗子:
例如,如果你遇到一个将字母映射到频率的字
典,可能会想要反转它;也就是说,建立一个字典,将频率映射到字母上。因为可能出现
多个字母频率相同的情况,在反转的字典中,每项的值应当是字母的列表。
# 统计每个字母出现的次数
def hub(x):
d =dict()
for i in x :
if i in d :
d[i] += 1
else:
d[i] = 1
return d
print(hub("aacde"))
st = 'stanabcc'
s = hub(st)
def inver_dict(d):
save = dict()
for key in d:
val = d[key]
if val not in save:
# 将key作为列表添加进去
save[val] = [key]
else:
save[val].append(key)
return save
print(inver_dict(s))
❌列表可以用作字典的值,但它们不能用作键。
🚩小结:
字典是通过散列表的方式实现的,这意味着键必须是可散列
(hashable)的。散列 是一个函数,接收(任意类型)的值并返回一个整数。字典使用这些被称为散列值的整数来保存和查找键值对。
因此键必须是可散列的,而类似列表这样的可变类型是不可散列的。绕过这种限制的 最简单办法是使用元组。
因为字典是可变的,它也不能用作键,但它可以 用作字典的值。
(7)备忘
在3_函数-(4)执行流程中,我们写了求斐波那契数的代码
从图中可以看出fib(1)和fib(0)被计算了很多次,而且当参数变大时,事情会变得更糟,一个解决办法是记录已经计算过的值,并将它们保存在一个字典中
。将之前计算的值 保存起来以便后面使用的方法称为备忘 (memo)
known = {0:0, 1:1}
def fibonacci(n):
if n in known:
return known[n]
res = fibonacci(n-1) + fibonacci(n-2)
known[n] = res
return res
先解释下代码:
每当fibonacci 被调用时,它会先检查known 。如果结果已经存在,则可以立即返 回。如果不存在,它需要计算这个新值,将其添加进字典,并返回。
我们将0和1保存下来, 提高了计算的效率,(当然这个不是最优的,别杠,这里只是为了用来展示字典的用法)
2.遍历字典⚠
alien_0 = {'color': 'green', 'points': 5}
# 添加值
alien_0['name'] = 'stan'
alien_0['character'] = 'outgoing'
alien_0['family'] = ['1', '2']
# 删除值
del alien_0['points']
# 输出字典
print(alien_0)
print(alien_0['family'])
for i, j in alien_0.items():
print("key:",i,"value:",j)
print("*"*11)
# 得到的是键,可以通过键得到对应的值
for i in alien_0:
print(alien_0[i])
a = alien_0.keys()
print(type(a))
alien_0 = {'color': 'green', 'points': 5}
# 添加值
alien_0['name'] = 'stan'
alien_0['character'] = 'outgoing'
alien_0['family'] = ['1', '2']
# 删除值
del alien_0['points']
# 输出字典
print(alien_0)
print(alien_0['family'])
for i, j in alien_0.items():
print("key:",i,"value:",j)
print("*"*11)
# 得到的是键,可以通过键得到对应的值
for i in alien_0:
print(alien_0[i])
a = alien_0.keys()
print(type(a))
(1)排序
按照键的大小排序
alien_2 = {'color': 'blue', 'points': 11,'a':1}
for c in alien_2:
print(c,alien_2[c])
# 排序
for c in sorted(alien_2):
print(c,alien_2[c])
列表嵌套
alien_0 = {'color': 'green', 'points': 5}
alien_1 = {'color': 'red', 'points': 6}
alien_2 = {'color': 'blue', 'points': 11}
# 将字典放入列表
li = [alien_0, alien_1, alien_2]
print(li[1])
# 用循环来放入列表,取出前五个
lis = []
for i in range(10):
lis.append(alien_1)
print(lis[:5])
# 将列表放入字典
pziza = {
'cust':'thick',
'topping':['mushroom', 'extra cheese']
}
# 取值
for i in pziza["topping"]:
print(i)
3.全局变量
main 之中的变量有时被称为全局 变量,因为它们可以在任意函数中访问。和局 部变量在函数结束时就消失不同,全局变量可以在不同函数的调用之间持久存在
全局变量常常用作标志 (flag);它是一种布尔变量,可以标志一个条件是否为真。
比如我们想要通过函数改变一个全局变量时:
been_called = False
def example2():
# 如果不先声明这个全局变量,则不能修改为True
global been_called
been_called = True
example2()
print(been_called)
❌举个错误例子,更新全局变量
count = 0
def example3():
count = count + 1
就会报错:
UnboundLocalError: local variable 'count' referenced before assignment
解决方法:
在函数中声明全局变量
count = 0
def example3():
global count
count = count + 1
print(count)
🚩小结:如果想要给全局变量 重新赋值,则需要声明它
未完待续…
本文章对于初学者也十分友好,也可以用来查漏补缺,是博主自己结合一些书籍和自己的经验写的教程。如果想要完整的md文件和代码(全是我自己总结的哦~)后续还会更新,值得收藏
可以加我qq:2024810652, 当然也可以加我的qq群:785318982,人很多,大佬也多,闲者勿扰。