Haste makes waste

Python-Liao-01-变量/控制/数据结构(list-tuple-set)

Posted on By lijun

[Python-Liao-XX…]系列,系列根据廖雪峰的python3初级教程学习整理。

notebook

1. Python解释器

使用标准的Cython,即官方的C语言编写的解释器。

2. 第一个Python程序

略!

3. 使用文本编辑器

Sublime是个好用的编辑器,小巧,功能齐全。之前用VIM,但有时要写Markdown文档,还是Sublime功能齐全。

  • 直接运行py文件

在windows下,无法像exe文件那样直接运行,但是在Mac和Linux是可以的,方法是在.py文件第一行加上一行特殊注释:#!/usr/bin/env python3,然后通过命令给hello.py以执行权限:$ chmod a+x hello.py,然后就可以直接执行文件了 $./hello.py

4. Python代码运行助手

略!

5. 输入和输出

name = input("please input your name:")
print(name,"hello")
输出:please input your name:lju
     lju hello

6. Python基础

按照python约定俗成的规则,缩进都采用4个空格,防止不同系统中对tab的定义不同。 最好在代码编辑器中将Tab键设置为4个空格。

采用空格作为缩进,能培养出写短小代码的习惯,如果代码太长的话,就会使得缩进太多,代码难读。

7. 数据类型和变量

  • 整数和浮点数在计算机内部的存储是不同的,整数永远是精确的,浮点数则会存在四舍五入的误差。

  • 转义字符\可以转义很多字符,比如\n 表示换行,\t 表示制表符,字符
    本身也要转义,所以\表示的字符就是.-

print("I\'m learning \n python \n java!")
输出:	 I'm learning 
	     python 
	     java!

Python 还允许用 r’‘表示’‘内部的字符串默认不转义,如下所示:

print(r"I\'m learning \n python \n java!")
输出:	 I\'m learning \n python \n java!

用 ‘’’ 能表示多行内容。

print('''123
456
789
123''')
输出:   123
	    456
	    789
	    123
  • Bool值 ,True和False

  • 空值是Python中的一个特殊值,用None表示,不能理解为0,0有意义,而None是一个特殊的空值。

  • 变量:

  1. python是一种动态语言,俗称脚本语言,在运行的时候直接执行。进行变量定义时,不需要指定变量类型。与之对应的静态语言,变量定义时必须指定类型,否则编译的时候就出错。
  2. 理解变量在计算机内存中的表示,当我们写a = "ABC"时,python解释器干了两件事情,先在内存中创建一个ABC的字符串,然后创建一个名为a的变量,并将该变量指向上面的ABC字符串。
  • 常量 python中没有通常的常量,只有一个中约定的命名方法,即用大写表示常量,如PI = 3.14159,但仍然是但仍然是变量,可以修改。
a = 10/3 # 精确除法
b = 10//3 # 地板除法
c = 10%3 # 除法之后取余数
print("a:{}, b:{}, c:{}".format(a,b,c))
输出:	 a:3.3333333333333335, b:3, c:1

8. 字符串和编码

关于字符串和编码,总结过一篇,参考: https://utanesuke0612.github.io/2017/09/09/Python3-Liao_02/

9. 使用list和tuple

List和tuple是python内置的有序集合,一个可变,一个不可变,要根据需要选择使用。

9.1 List

  • 创建list
listA = ["lj","wl","utane","utasuke"] # 创建list
listA
输出:	 ['lj', 'wl', 'utane', 'utasuke']
  • 取元素
listA[1] # 获取元素
输出:	 'wl'
listA[:2] # 切片
输出:	 ['lj', 'wl']
listA[-2] # 反向获取
输出:	 'utane'
listA[-3:-1] # 反向切片
输出:	 ['wl', 'utane']
  • list是一个有序的可变列表,可以将元素进行增加删除和修改。
listA.append("baba") # 末尾追加元素
listA
输出:	 ['lj', 'wl', 'utane', 'utasuke', 'baba']
listA.insert(2,"mama") # 指定位置增加元素
listA
输出:	 ['lj', 'wl', 'mama', 'utane', 'utasuke', 'baba']
listA.pop() #弹出最末尾的元素
listA
输出:	 ['lj', 'wl', 'mama', 'utane', 'utasuke']
listA.pop(2) #弹出指定位置的元素
listA
输出:	 ['lj', 'wl', 'utane', 'utasuke']
listA[0] = "lijun" # 修改值
listA
输出:	 ['lijun', 'wl', 'utane', 'utasuke']
# list中能保持不同类型的值
listA.append(4)
listA.append(True)
listA.append([33,30,4,2])
listA
输出:	 ['lijun', 'wl', 'utane', 'utasuke', 4, True, [33, 30, 4, 2]]

9.2 Tuple

Tuple元祖与列表list非常类似,但是Tuple是不可变的,一旦初始化就不能修改了,没有list的append,insert方法,也不能修改元素的值。

familyTuple = ("lj","wl","uta","utasuke")
familyTuple
输出:	 ('lj', 'wl', 'uta', 'utasuke')
familyTuple[:4] # 能正常的取得元素,但是不能再赋值
输出:	 ('lj', 'wl', 'uta', 'utasuke')
tupleA = () # 定义一个空的元祖
tupleA
输出:	 ()
tupleB = (1) # 这里实际将()看成是数学符号,不是元素的括号
tupleB
输出:	 1
type(tupleB) # 见上,是定义了一个int
输出:	 int
tupleC = (1,) # 要定义单个元素的元祖,后面要加逗号
tupleC
输出:	 (1,)
  • “可变”的Tuple

为什么会这样参考 https://utanesuke0612.github.io/2017/09/09/Python3-Liao_01/#81-tuple的可变性

tupleD = (1,2,[3,4])
tupleD[2][0] = 5
tupleD[2][1] = 6
tupleD
输出:	 (1, 2, [5, 6])

实际上tupleD中的元素,分别是三个指向1,2,[3,4]的变量,变量的值没有变化,变量指向的list的值发生了变化。

所以要保持tuple的不变型,tuple元组中的元素只能是不可变的。

10. 条件判断

def judge_age(age):
    if age > 30:
        print("baba")
    elif age > 25:
        print("mama")
    elif age > 3:
        print("uta")
    elif age > 1:
        print("utasuke")
    else:
        print("I dont know")
judge_age(3)
输出:	 utasuke

11. 循环

for 循环和while 循环。

sum = 0
for i in range(100):
    sum += i

sum
输出:	 4950
n = 0
sum = 0
while n < 100:
    sum += n
    n += 1
sum
输出:	 4950

12. 使用Dict和Set

12.1 使用Dict

Dict是key和value的键值对。

dictA = {"wl":30}
dictA["lj"] = 33
dictA["lj"] = 18
dictA #无序
输出:	 {'lj': 18, 'wl': 30}
dictA.pop("lj")
输出:	 18
dictA
输出:	 {'wl': 30}
  • key是否存在的判断
"wl" in dictA
输出:	 True
dictA.get("wl")
输出:	 30
dictA.get("haha",-1)
输出:	 -1
  • list与dict
  1. dict查找和插入速度快,不会随着key的增加而增加
  2. dict占用大量内存

  3. list查找和插入速度,随着元素增多而增加
  4. list占用空间小,浪费内存少
  • dict的key只能不可变

12.2 Set集合

与上面的list与tuple关系类似,set集合也是一类特殊的dict,dict是key和value的键值对,set可以看成只有key的集合,所以set中是没有重复记录的。

setA = set([1,2,2,3,4,4,3]) # set通过list创建
setA
输出:	 {1, 2, 3, 4}
setA.add(5) 
setA.add(3) # 通过add追加,重复的不被追加
setA
输出:	 {1, 2, 3, 4, 5}
setA.remove(3)
setA
输出:	 {1, 2, 4, 5}
# set可以看成数学意义上的无序和无重复元素的集合,因为两个set可以做数学意义的交集并集操作
setB = set([2,3,5,6])
setA & setB
输出:	 {2, 5}
setA | setB
输出:	 {1, 2, 3, 4, 5, 6}

set与dict的唯一区别在于,set没有存储对应的value,但是原理是一样的,同样不能放入可变对象,比如通过add添加[1,2]会出错,虽说操作上是添加list[1,2],但实际是添加了一个指向list的变量,这个变量的值不会变,但是它指向的list可能变化,而set是存储key的集合,如果key发生了变化,通过hash算法,就无法计算出准确的value(与dict一样)。

总结一下:

  • list [],有序,可重复,可增删改,查找慢,占用内存少。
  • tuple (),类似list,但是不能增删改,不可变。
  • dict {key:value,key:value},无序,key不重复,可增删改,查找快,内存占用多。
  • set set(),{key,key,key},类似dict,无序,只有key,与dict一样,key不能为list等可变对象。

12.3 关于不可变对象

python中,对象分为可变(mutable)和不可变(immutable)两种类型,

  1. 元组(tuple)、数值型(number)、字符串(string)均为不可变对象。
  2. 而字典型(dictionary)和列表型(list)的对象是可变对象。
a = 1 #将名字a与内存中值为1的内存绑定在一起
#将名字a与内存中值为2的内存绑定在一起,而不是修改原来a绑定的内存中的值,
# 这时,内存中值为1的内存地址引用计数-1,当引用计数为0时,内存地址被回收
a = 2 
b = a #变量b执行与a绑定的内存
b = 3 #创建一个内存值为3的内存地址与变量名字b进行绑定。这是a还是指向值为2的内存地址。
a,b
输出:	 (2, 3)
a = [1] #
b = [2]
b = a
b[0] = 3 # 因为b已经指向了a的对象,通过对b的修改,也能修改a
a,b
输出:	 ([3], [3])

上面的变量与内存关系,参考 ★★

x = 25
y = 25
x is y
输出:	 True
x = 2500
y = 2500
x is y
输出:	 False

因为整数为不可变,x,y在内存中均指向一个值为1的内存地址,也就是说,x,y均指向的是同一个地址,值得注意的是,整形来说,目前仅支持(-1,100)。 java中类似,取值范围好像是(-127,128)。

  • (-1,100)这些数因为时常用到,所以以对象的形式常驻内存,有变量被赋值到了这些数字,则直接将变量指向它。

  • 超过这个范围,就需要新建一个内存去存储指定数据,然后将变量指向这个内存,所以x和y就不会指向同一个内存了。

总结一下,不可变对象的优缺点。

  • 优点是,这样可以减少重复的值对内存空间的占用。

  • 缺点呢,要修改这个变量绑定的值,如果内存中没用存在该值的内存块,那么必须重新开辟一块内存,把新地址与变量名绑定。 而不是修改变量原来指向的内存块的值,这回给执行效率带来一定的降低。