python的基本对象类型
在python中,万物皆对象,或许你现在还不理解这句话的含义,但是从现在开始,我们即将接触的就是python的对象,对象有类型,python默认了一些对象类型
- int整数
- 浮点数(不用深究的情况下,把他直接理解为小数即可)
- bool值
- 内置数据结构
- 列表
- 元祖
- 字符串
- 字典
- 集合
整数
a = input("please insert a num:")
print(a,type(a))
运行结果:
please insert a num:23
23 <class 'str'>
str 是string(字符串)的简写,怎么把a 转换成数字类型a呢?
a = int(input("please insert a num"))
print(a,type(a))
运行结果:
please insert a num23
23 <class 'int'>
在python2里分为整型和长整型(long),但在python3里就是int
[root@hadoop-namenode002 /]# python
Python 2.7.5 (default, Nov 6 2016, 00:28:07)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 999999999999999999999999999999999999999
>>> print(type(a))
<type 'long'>
>>> b = 333
>>> print(type(b))
<type 'int'>
[root@hadoop-namenode002 opt]# python
Python 3.5.3 (default, Jul 27 2017, 22:41:34)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>>
>>>
>>> a = 99999999999999999999999999999999999999999999999999999
>>> print(type(a))
<class 'int'>
>>> b = 333
>>> print(type(b))
<class 'int'>
浮点数
a = 23.0
print(a,type(a))
运行结果:
23.0 <class 'float'>
python 内置数据结构
五种内置数据结构:
- list 列表
- tuple 元组
- str 字符串
- set 集合
- dic 字典
其中 列表、元组、字符串是线性结构(线性结构是一个有序数据元素的集合),线性结构可以做切片操作,解包和封包 ,而成员运算符,遍历操作
只要是可迭代对象都可以,比如集合虽不是线性结构,但也是可迭代对象,也可以用 for 循环遍历
解析式:
- 列表解析式
- 生成器解析式 (py3 特有)
- 集合解析式 (py3 特有)
- 字典解析式 (py3 特有)
列表
创建列表
初始化一个空列表,列表用list表示,创建空列表有两种方式:
创建空列表
方式一:
a = []
print(a,type(a))
运行结果:
[] <class 'list'>
方式二:
a = list()
print(a,type(a))
运行结果:
[] <class 'list'>
创建一个非空列表
b = [1,2,3,4,5]
print(b,type(b))
运行结果:
[1, 2, 3, 4, 5] <class 'list'>
列表的索引和下标操作
python中 列表的索引是从0开始的,索引0代表第一个元素,索引1代表第二个元素,索引-1代表最后一个元素
也有人把索引叫做下标,都是一样的
x = ["a","b","c","d","e","f","g"]
x[0]
运行结果:
'a'
x[1]
运行结果:
'b'
x[-1]
运行结果:
'g'
x[-2]
运行结果:
'f'
如果索引超出范围,将会引发我们的index_error
x[7]
运行结果:
IndexError: list index out of range
x[-9]
运行结果:
IndexError: list index out of range
上面我们通过索引取出了列表中元素的值,现在我们希望通过值找到他的下标
x = ["a","b","c","d","e","f","g"]
x.index("d") #index 可以通过type补齐,因为.index 是列表的内置方法
运行结果:
3
help(list) 可以看到list有很多内置方法,但是终究还是增删改查,带下划线的方法可以忽略
列表的增删改查
增方法之append
yunwei = ["dailiang","network","hardware","software","DBA"]
yunwei.append("security")
print(yunwei)
运行结果:
['dailiang', 'network', 'hardware', 'software', 'DBA', 'security']
你发现新的元素追加到最后了
help(list.append)
运行结果:
Help on method_descriptor:
append(...)
L.append(object) -> None -- append object to end
增方法之insert
help(list.insert)
运行结果:
Help on method_descriptor:
insert(...)
L.insert(index, object) -- insert object before index
yunwei = ["dailiang","network","hardware","software","DBA"]
yunwei.insert(2,"python")
print(yunwei)
运行结果:
['dailiang', 'network', 'python', 'hardware', 'software', 'DBA']
yunwei = ["dailiang","network","hardware","software","DBA"]
yunwei.insert(3,"python")
print(yunwei)
运行结果:
['dailiang', 'network', 'hardware', 'python', 'software', 'DBA']
yunwei = ["dailiang","network","hardware","software","DBA"]
yunwei.insert(100,"python")
yunwei.insert(-100,"linux")
print(yunwei)
运行结果:
['linux', 'dailiang', 'network', 'hardware', 'software', 'DBA', 'python']
总结:insert方式操作的索引超出范围的化,如果为正索引,那么效果为append,如果是负索引,等同于insert(0,”元素”)
增方法之extend
help(list.extend)
运行结果:
Help on method_descriptor:
extend(...)
L.extend(iterable) -> None -- extend list by appending elements from the iterable
iterable 可迭代的
a = [1,2,3]
b = [4 ,5,6]
a.extend(b)
print(a)
运行结果:
[1, 2, 3, 4, 5, 6]
a = [1,2,3]
b = range(10)
a.extend(b)
print(a)
运行结果:
[1, 2, 3, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
我们发现列表里面可以有重复元素的
删方法之pop
help(list.pop)
运行结果:
Help on method_descriptor:
pop(...)
L.pop([index]) -> item -- remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
pop 根据下标删除元素,默认为 -1 ,如果index超出索引或者列表为空,会抛出IndexError 异常
a = [1,2,3,4,5]
a.pop()
print(a)
运行结果:
[1, 2, 3, 4]
a = [1,2,3,4,5]
a.pop(0)
print(a)
运行结果:
[2, 3, 4, 5]
a = [1,2,3,4,5] #索引超出限制
a.pop(100) # pop index out of range
运行结果:
a.pop(100) # pop index out of range
IndexError: pop index out of range
a = [1,2,3] #列表为空的情况
a.pop()
a.pop()
a.pop()
print(a)
a.pop()
运行结果:
[]
IndexError: pop from empty list
删方法之remove
help(list.remove)
运行结果:
Help on method_descriptor:
remove(...)
L.remove(value) -> None -- remove first occurrence of value.
Raises ValueError if the value is not present.
x = ["a","b","c","d","b"]
x.remove("a")
print(x)
运行结果:
['b', 'c', 'd', 'b']
x = ["a","b","c","d","b"]
x.remove("b")
print(x)
运行结果:
["a","c","d","b"]
可以看出是按照顺序删除的,remove删除第一个对应该value的元素
pop是根据索引删除元素,而remove方法是直接删除元素
删方法之clear
help(list.clear)
运行结果:
Help on method_descriptor:
clear(...)
L.clear() -> None -- remove all items from L
x = ["a","b","c","d","b"]
x.clear()
print(x)
运行结果:
[]
删方法之del
前面的删除方式: pop、remove、clear都是列表的内置方法。而del并非列表的内置方法,可以用在元组、字典等多种数据结构
x = ["a","b","c","d","b"]
del x[0]
print(x)
运行结果:
['b', 'c', 'd', 'b']
改方法之reverse
help(list.reverse)
运行结果:
Help on method_descriptor:
reverse(...)
L.reverse() -- reverse *IN PLACE*
x = ["a","b","c","d"]
x.reverse()
print(x)
运行结果:
['d', 'c', 'b', 'a']
改方法之sort
help(list.sort) #排序
运行结果:
Help on method_descriptor:
sort(...)
L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*
x = ["a","c","b","d","b"]
x.sort()
print(x)
运行结果:
['a', 'b', 'b', 'c', 'd']
x = [3,5,4,2,1]
x.sort()
print(x)
运行结果:
[1, 2, 3, 4, 5]
x = [3,5,4,2,1]
x.sort(reverse=False)
print(x)
x.sort(reverse=True)
print(x)
运行结果:
[1, 2, 3, 4, 5]
[5, 4, 3, 2, 1]
查找统计方式之index
x = ["a","b","c","d","e"]
x.index("b")
运行结果:
1
x[0]
运行结果:
'a'
查找统计方式之count
help(list.count)
运行结果:
Help on method_descriptor:
count(...)
L.count(value) -> integer -- return number of occurrences of value
x = ["a","b","b","c","d","e"]
x.count("b")
运行结果:
2
查找统计方式之len
len 不是list的内置方法,而是一个函数
a = [1,2,3,4,5,6]
len(a)
运行结果:
6
列表的深浅copy
赋值
x = ["a","b","c","d","e"]
y = x
print("--1--",y)
y.remove("a")
print("--2--",y)
print("--3--",x)
运行结果:
--1-- ['a', 'b', 'c', 'd', 'e']
--2-- ['b', 'c', 'd', 'e']
--3-- ['b', 'c', 'd', 'e']
你发现你删除了y 里面的值,x的值也顺便删除了,这种是不能接受的 原理是这样的,y = x 只是把x对应的内存指针给指过来了
print(id(x))
print(id(y))
运行结果:
139674624008840
139674624008840
发现都是指向同一块内存地址,举例:一间房子两个门牌号而已,这种情况我们是不能接受的,所以我们又有了copy函数
浅copy (shallow copy)
help(list.copy) #shallow copy 也叫做浅copy
运行结果:
Help on method_descriptor:
copy(...)
L.copy() -> list -- a shallow copy of L
x = ["a","b","c","d","e"]
y = x.copy()
print("--1--",y)
y.remove("a")
print("--2--",y)
print("--3--",x)
print(id(x),id(y))
运行结果:
--1-- ['a', 'b', 'c', 'd', 'e']
--2-- ['b', 'c', 'd', 'e']
--3-- ['a', 'b', 'c', 'd', 'e']
139674623262472 139674623032584
现在你可能发现一切都完美了,但是看下面一个例子
x = ["a","b",["c","d","e"] ]
print(x,type(x))
运行结果:
['a', 'b', ['c', 'd', 'e']] <class 'list'>
x = ["a","b",["c","d","e"] ]
y = x.copy()
y[2][1] = "k"
print("---",x)
print("---",y)
运行结果:
--- ['a', 'b', ['c', 'k', 'e']]
--- ['a', 'b', ['c', 'k', 'e']]
浅copy只能改变一层内存地址,如果列表嵌套列表,那么是不行的,于是我们有了深copy的方法
deepcopy
import copy
s = [[1,2],3,4]
s2 = copy.deepcopy(s)
s2[0][1] = 'abc'
print('列表s:',s)
print('列表s2:',s2)
运行结果:
列表s: [[1, 2], 3, 4]
列表s2: [[1, 'abc'], 3, 4]
导入模块的例子:
>>> a = [1,2,3]
>>> b = copy.deepcopy(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'copy' is not defined
>>> import copy
>>> b = copy.deepcopy(a)
>>> print(b)
[1, 2, 3]
元组
元组(tuple)其实跟列表差不多,也是存一组数,只不是它一旦创建,便不能再修改,所以又叫只读列表
创建空元组
a = ()
print(a,type(a))
b = tuple()
print(b,type(b))
运行结果:
() <class 'tuple'>
() <class 'tuple'>
因为元组一旦被创建,就不能够被修改,所以创建空元组基本没有意义的
元组的方法
x = (1,2,3)
print(x,type(x))
运行结果:
(1, 2, 3) <class 'tuple'>
输入tuple. tab补全,发现tuple只有 count 和index
x = ("a","b","b","c","d")
print(x.count("b"))
print(x.index("b")) #找到第一个就不往下查找了
len(x)
运行结果:
2
1
5
x[1]
运行结果:
'b'
x[1] = "z"
运行结果:
TypeError: 'tuple' object does not support item assignment
列表与元组的区别
- 列表与元组最大的区别,就是元组不可变
- 元组是可hash的
a = [1,2,3,4]
b = (1,2,3,4)
hash(a)
运行结果:
TypeError: unhashable type: 'list'
hash(b)
运行结果:
485696759010151909
这个功能我们在讲字典的时候会讲,就先记住这个知识点即可
在讲字典时我们会讲到,字典的key要求是必须可hash的,所以元组可以作为字典的key,而list不行
线性结构
列表、元组、字符串是线性结构(线性结构是一个有序数据元素的集合),线性结构可以做切片操作
之所以说它有序,因为它可以使用下标的方式把元素取出来
线性结构可以做切片操作,解包和封包 ,而成员运算符,遍历操作 只要是可迭代对象都可以,比如集合虽不是线性结构,但也是可迭代对象,也可以用 for 循环遍历,我们先来说一下什么叫做切片操作
线性结构的切片操作
列表的切片
a = ["a","b","c","d","e","f","g","h","i","j"]
b = a[0:2]
print(b)
运行结果:
['a', 'b']
你会发现上面的是半开区间的,这就叫做切片的“顾头不顾尾”原则
a = ["a","b","c","d","e","f","g","h","i","j"]
b = a[0:10000]
print(b)
运行结果:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
a = ["a","b","c","d","e","f","g","h","i","j"]
b = a[0:-1]
print(b)
运行结果:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
切片操作最后一个值不写,那么代表取全部的值
a = ["a","b","c","d","e","f","g","h","i","j"]
b = a[0:]
print(b)
运行结果:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
切片操作也可以前面的值不写,那么这个值默认为0,不常用
a = ["a","b","c","d","e","f","g","h","i","j"]
b = a[:-1]
print(b)
运行结果:
['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
元组的切片操作
x = ("a","b","c","d","e","f","g","h","i","j")
x[0:4]
运行结果:
('a', 'b', 'c', 'd')
切片的步长
x = ("a","b","c","d","e","f","g","h","i","j")
x[0:4:2]
运行结果:
('a', 'c')
切片步长默认是1,那么步长为负数呢??
x = list(range(10)) #如果用list() 方式来创建列表,list() 内的值必须为一个可迭代对象
print(x)
运行结果:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
x = list(range(10))
y = x[0:8:-1]
print(y)
运行结果:
[]
步长为负,为何是空列表呢? 步长为负时,要求切片的起始值大于结束值
x = list(range(10))
y = x[8:0:-1]
print(y)
运行结果:
[8, 7, 6, 5, 4, 3, 2, 1]
x = list(range(10))
y = x[8:0:-2]
print(y)
运行结果:
[8, 6, 4, 2]
x = list(range(10))
y = x[:0:-1]
print(y)
运行结果:
[9, 8, 7, 6, 5, 4, 3, 2, 1]
x = list(range(10))
y = x[9::-1]
print(y)
运行结果:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
我们之前说过反转列表使用reverse
x = list(range(10))
x.reverse()
print(x)
运行结果:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
我们现在有了第二个方式来反转列表
x = list(range(10))
y = x[::-1]
print(y)
运行结果:
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
线性结构的解包和封包
线性结构之pack & unpack(封包,解包)
封包
什么叫做封包?把一组变量打包为一个元组叫做pack,也叫封包
* 封包出来的一定是元组 *
x = 1,3
print(x,type(x))
运行结果:
(1, 3) <class 'tuple'>
x = 1,[1,2,3],(4,5,6)
print(x,type(x))
运行结果:
(1, [1, 2, 3], (4, 5, 6)) <class 'tuple'>
解包
x,y = (1,3)
print(x)
print(y)
运行结果:
1
3
x,y = [1,3]
print(x)
print(y)
运行结果:
1
3
x,y = (1,2,3) #数量必须一致
运行结果:
ValueError: too many values to unpack (expected 2)
我们来举一个封包、解包的例子:
z = (1,3) #封包为元组
a,b = z
print(a,b)
运行结果:
1 3
我们可以把封包的过程省略:
a,b = 1,3
print(a,b)
运行结果:
1 3
解包与封包的初级作用
我们通过一个例子来了解:解包与封包的实际作用
比如 a = 1 , b =2 ,我们定义了两个变量,现在我想把他们两个的值调换以下,应该怎么办?
def change(a,b):
i = b
b = a
a = i
return (a,b)
change(1,3)
运行结果:
(3, 1)
但是我们可以通过解包封包的思想来看以下这个问题:
先把 a,b 封包成一个元组c
a = 1
b = 3
#封包
c = a,b
#print(c)
#解包
b,a =c
print(a)
print(b)
运行结果:
3
1
再把封包过程省略
a = 1
b = 3
b,a = a,b
print(a,b)
运行结果:
3 1
解包的高级应用:
head,*tail = list(range(10))
print(head)
print(tail)
运行结果:
0
[1, 2, 3, 4, 5, 6, 7, 8, 9]
head , *mid ,tail = list(range(0,10))
print(head)
print(mid)
print(tail)
运行结果:
0
[1, 2, 3, 4, 5, 6, 7, 8]
9
ok,前面我们一直在对列表 做解包操作,现在我们对元组做一下解包操作
head , *mid ,tail = tuple(range(0,10))
print(head)
print(mid)
print(tail)
运行结果:
0
[1, 2, 3, 4, 5, 6, 7, 8]
9
你会发现mid也是返回列表的形式,所以结论是:无论是unpack任意值,*asg 永远返回的是列表
封包永远是封成元组,解包如果有*asg,那么*asg永远是列表
* 不能单独存在
*tail = tuple(range(0,10))
运行结果:
File "<ipython-input-278-0a880552cf3e>", line 1
*tail = tuple(range(0,10))
^
SyntaxError: starred assignment target must be in a list or tuple
不能同时存在多个*
head , *mid ,*tail = tuple(range(0,10))
运行结果:
File "<ipython-input-279-feac08157463>", line 1
head , *mid ,*tail = tuple(range(0,10))
^
SyntaxError: two starred expressions in assignment
强调:head ,tail ,mid 只是为了方便大家理解,而定义的变量,换成a b c 等任意字符均可
x , *y ,z = tuple(range(0,10))
print(y)
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8]
python的一个惯例,使用单个下划线表示需要丢弃的变量,只是约定俗称,当然你可以不遵守,后果就是降低代码可读性
head ,*_,tail = list(range(10))
print(_)
运行结果:
[1, 2, 3, 4, 5, 6, 7, 8]
多层解构
题目:Q = [“a”,”b”,”c”,”d”] ,使用解构方式取出正数第二个和倒数第二个值
Q = ["a","b","c","d"]
head,*mid,tail = Q
print(mid)
运行结果:
['b', 'c']
head,tail = mid
print(head,tail)
运行结果:
b c
更好的方式
Q = ["a","b","c","d","e","f"]
_,x,*_,y,_ = Q
print(x,y)
运行结果:
b e
实际工作中,我们一般这样用:
比如我们会经常遇到key,value类型的配置文件,例如ip=127.0.0.1 之类的,我们可以通过解构的方式,轻松的把key和value取出来
s = "ip=127.0.0.1"
print(s,type(s))
运行结果:
ip=127.0.0.1 <class 'str'>
s.partition("=")
运行结果:
('ip', '=', '127.0.0.1')
ip,*_,value = s.partition("=")
print(ip)
print(value)
运行结果:
ip
127.0.0.1
迭代
迭代:在python中表现就是用for循环,从对象中获得一定数量的元素
将for循环用于列表、字符串、字典的键值对,这就是迭代
迭代并不只是线性结构特性,比如集合set ,也可以使用for循环进行迭代
可以迭代的都叫做可迭代对象(iterable)
name = "dai"
for i in name :
print(i)
运行结果:
d
a
i
name = ["a","b","c"]
for i in name :
print(i)
运行结果:
a
b
c
name = {"a","b","c"} #集合内的元素没有顺序,不是线性结构,不能取索引和下标
print(name ,type(name))
for i in name:
print(i)
运行结果:
{'a', 'c', 'b'} <class 'set'>
a
c
b
成员运算符in 与 not in
成员运算符可以不用遍历对象语句类似于for i in ,直接in 或者 not in 即可
c = ["a","b","c","d","e"]
if "c" in c :
print("ok")
else:
print("not")
运行结果:
ok
name = {"a","b"}
if "a" not in name :
print("yes")
else:
print("no")
运行结果:
no