guxh的python笔记一:数据类型

1,基本概念

1.1,数据类型

基本数据类型:字符串,数字,布尔等

引用数据类型:相对不可变(元组),可变(列表,字典,集合等)

基本数据类型存放实际值,引用数据类型存放对象的地址(即引用)

==:判断值是否相等

is:判断id是否相等,即内存地址,id()可以返回内存地址

 

1.2,序列类型

容器类型:list,tuple,collections.deque,存放引用,可嵌套

扁平序列:str,bytes,bytearray,memoryview,array.array,存放值,只包含原子数据

可变序列:list,bytearray,array.array,collections.deque,memoryview

不可变序列:tupe,str,bytes

 

2,str

1)格式化:

%s:'%s plus %s equals %s'  % (1, 1, 2)

2)find/rfind:返回最左边/最右边索引,没有返回-1,例如路径中提取文件名

s1 ='c:/../../text.txt'
s1[s1.rfind('/')+1: s1.find('.txt')]  # s1结果是text

3)lower/upper:小写/大写

4)startswith/endswith:判断开始/判断结尾,例如endswith('com'),接受多个参数时必须用元组name.endswith(('.c', '.h'))

5)strip/lstrip/rstrip:去除两边/左边/右边的空格字符串,也可以传参指定去除的内容

6)join:合项

','.join(['a', 'b', 'c'])  # 结果是a,b,c

7)split:裂项,不传参就对空格、制表、换行进行分割

'a b    \nc'.split(),# 结果是['a', 'b', 'c']

8)count:统计出现次数

9)index:判断索引位置

10)replace:替换,默认全替,但可以传第3参数指定替换几个

'aba'.replace('a', 'b', 1)  # 指定替换1个,结果是'bba',

11)center:居中打印

'title'.center(50, '-')  # 结果是'----------------------title-----------------------'

12)isdigit:判断数字

'322'.isdigit() # 结果是True

  

3,bytes

码位:每个字符占若干字节,python3(str),python2(unicode)

字节序列:每个字符占一个字节,python3(bytes),python2(str/bytes)

 

4,列表

4.1,list函数

功能一:用于将可迭代对象iterator转换为列表

功能二:实现浅拷贝

例如:

list('hello')  # 结果是['h','e','l','l','o']
list(range(5))  # 结果是[1, 2, 3, 4, 5]
list({'a': 1, 'b': 2})  # 结果是['a', 'b'],因为对字典迭代获取到的是key

 

4.2,list操作

1)增:lista.append(4),就地添加返回None

2)删:删元素用del、remove、pop;删列表用del、clear

3)改:lista[2] = 2

4)插:lista.insert[3, 'insert_value'],或者:lista[3:3] = ['insert_value']

7)切片:访问切片:y=x[1:3];插入序列x[1:1] = [2,3,4];删除序列:x[1:4]=[];替换序列:x[1:4]=[2,3,4]

8)extend追加:就地加lista.extend(listb),等效于lista = lista + listb,或者lista[len(lista):] = listb

9)列表相加:lista + listb,原序列不会变

10)乘法:[1,2,3] * 2,结果为[1,2,3,1,2,3],原序列不变

11)创建5个空序列:

lists = [[] for i in range(5)]  # 5个不同的空序列
lists = [[]] * 5   # 5个id相同的空序列

12)reverse / reserved:反向存放,lista.reverse()就地反向无返回值,reversed(list)有返回值(原序列不变)

13)sort / sorted:排序,x.sort()就地排序无反向值,sorted(list)有返回值(原序列不变)

14)copy:浅拷贝,list.copy()

15)enumerate:遍历index和value

for i,v in enumerate(lista):
    print(i, v)  # i索引,v值

16)in,len,max,min,index,count:略

 

4.3,列表的拷贝

t = [1, [2, 3], (4, 5)]

起别名,连第一层都不拷贝:

a = t

浅拷贝:拷贝第一层:

b = list(t) 
b = t[:]
b = t.copy()
b = copy.copy(t)

深拷贝:拷贝所有层:

c = copy.deepcopy(t) 

看看有什么区别:

t[0] = 0 
t[1].append(0)
t[2] += (0, )

输出结果:

t : [0, [2, 3, 0], (4, 5, 0)]
a : [0, [2, 3, 0], (4, 5, 0)] # 别名,全跟着变
b : [1, [2, 3, 0], (4, 5)] # 浅拷贝,第一层以及第二层内的不可变序列不变,第二层的可变序列跟着变
c : [1, [2, 3], (4, 5)] # 深拷贝,全都不变

总结:

判断时可以用is或者id(),看下不同的变量名,是否指向同一引用对象

a和t的id完全相同,b/c和t的id不同

如果列表内部有“可变的引用对象”(例如字典、集合、列表,元组算不可变的引用对象),t发生改变时,会影响到浅拷贝b,但不会影响到深拷贝c

 

5,元组

5.1,tupple函数

和list函数一样,将某个序列转换为tupple

 

5.2,元组操作

1)切片:只支持切片访问即查,不支持插,删,改

2)元组相加:tu1 + tu2,原序列不会变

3)乘法:(1,2,3) * 2,结果为(1,2,3,1,2,3),原序列不变

4)in,len,max,min,index,count,enumerate:略

 

5.3,元组和列表的区别

列表不建议存放不同类型的东西,否则无法排序

元组经常用来存放不同类型的东西

 

5.4,具名元组

具有名字的元组

from collections import namedtuple
TU = namedtuple('manincity', 'name city')
tu1 = TU('guxh', 'shanghai')
print(tu1)  # manincity(name='guxh', city='shanghai')

  

6,字典

6.1,字典的创建

d = {'a':1, 'b':2, 'c':3}
d = dict(a=1, b=2, c=3)
d = dict([('a','1'), ('b',2), ('c',3)]) # 元组列表,列表列表都可以,只要是2个值的小序列组成的大序列,不用写字典推导了!!!

 

6.2,字典操作

1)增和改:d['d'] = 4,有改/无增

2)d.update(d2),用字典d2区更新d,有改/无增

3)删除

d.pop('d') # 删除key-values键值对
del d['a']  # 删除key-values键值对
popitem() # 删最后一个,由于字典是无序的所以实际上是随机删一个

4)清空字典

y = d
d.clear()     # 无返回值,d和y都能清掉
d = {}    # 直接赋空值也可以清,只能清d

5)查

'a' in d  # 判断是否含有键为K的项,list中是判断的是值
d['a']    # 返回关联键K的value,如果不存在会报错KeyError
d.get('a', 123)   # 有就返回value,没有则返回缺省值123

6)copy

d2 = d1.copy()  # 是浅拷贝,替换值时原始字典不受影响,但是修改值是原始字典也会改变。
d2 = d1.deepcopy()   # 深拷贝

7)fromkeys

从给定的key创建新字典,可以指定values,默认为None

d = dict.fromkeys(['east', 'west'], 20)  # dict可以改成任何已经存在的字典,但是结果和该字典无任何关系
print(d)   # {'west': 20, 'east': 20}

8)has_key:检测是否有key

9)items/iteritems, keys/iterkeys, values/itervalues:返回值/迭代对象

d = {'west': 10, 'east': 20, 'south':30, 'north':40}
print d.items()  # [('west', 10), ('east', 20), ('north', 40), ('south', 30)],即字典转列表
print d.keys()   # ['west', 'east', 'north', 'south']
print d.values()   # [10, 20, 40, 30]

直接对字典进行循环获取的是keys

10)len:略

 

6.3,字典应用-统计单词出现的位置

sentence = """I'm a big big girl
in a big big world
It's not a big big thing if you leave me
but I do do feel
that I too too will miss you much"""

sentence = sentence.split()
d = {}

方法一:

for index, word in enumerate(sentence):
	if word not in d:
		d[word] = []
	d[word].append(index)

 方法二:get

for index, word in enumerate(sentence):
	temp = d.get(word, [])
	temp.append(index)
	d[word] = temp

方法三:setdefault

for index, word in enumerate(sentence):
	d.setdefault(word, [])
	d[word].append(index)

方法三(合一句):setdefault

for index, word in enumerate(sentence):
	d.setdefault(word, []).append(index)

方法四:defaultdict

from collections import defaultdict
d = defaultdict(list)
for index, word in enumerate(sentence):
	d[word].append(index)

  

6.4,其他

1)字符串格式化时可以使用字典

phonebook = {'cecil' : 56845 }
"cecil's phone number is %(cecil)s." % phonebook 

2)根据values求最小值,最大值,排序

d = {'a': 10, 'b':6, 'c': 5, 'd':17, 'e':12}

方法一:zip

min(zip(d.values(), d.keys()))     # (5, 'c')
max(zip(d.values(), d.keys()))     # (17, 'd')
sorted(zip(d.values(), d.keys()))  # [(5, 'c'), (6, 'b'), (10, 'a'), (12, 'e'), (17, 'd')]

方法二:lambda

d[min(d, key=lambda k: d[k])]                  # 5
d[max(d, key=lambda k: d[k])]                  # 17
[d[i] for i in sorted(d, key=lambda k: d[k])]  # [5, 6, 10, 12, 17]

3)对字典使用集合的操作:字典的keys()和items()支持集合操作,但values()不支持

d1 = {'a': 1, 'b': 2, 'c': 3}
d2 = {'b': 4, 'c': 3, 'd': 6}
d1.keys() & d2.keys()                # {'b', 'c'}
d1.keys() - d2.keys()                # {'d'}
d1.items() & d2.items()              #  {('c', 3)}
{key: d1[key] for key in d1.keys() - {'c'}}  # {'b': 2, 'a': 1}

  

7,集合

集合最重要的2个内容:

去重(把列表变成集合就自动去重了)

关系测试(测试2组数据的交集、差集、并集)

list1 = [1, 3, 5, 6, 7, 8, 1, 3, 5, 7, 2, 3]
list1 = set(list1)  # {1, 2, 3, 5, 6, 7, 8}  集合也是无序的
list2 = {1, 3, 11, 22, 55, 78, 90, 90, 1, 3}  # 实际结果是{1, 3, 11, 78, 22, 55, 90}
print(list1.intersection(list2))  # 取交集,结果是{1,3}
print(list1.union(list2))  # 取并集,结果是{1, 2, 3, 5, 6, 7, 8, 11, 78, 22, 55, 90} 
print(list1.difference(list2)) # 取差集,结果是{2, 5, 6, 7, 8},list1里有的,但是list2里没有的
print(list1.issubset(list2)) # 判断list1是否是list2的子集
print(list1.issuperset(list2)) # 判断list2是否是list1的父集

如果集合是空集,必须写成set(),写成{}是字典

 

7.1,集合运算的符号

& 交集

| 并集

- 差集

^ 对称差集

 

7.2,集合操作

1)增

t.add(5)  # 增加一项,注意增加是add,不是append
t.update(5,6,7)  # 增加多项

2)删

t.remove(5)  # 删除5,如果set中不存在5则会报错    
t.discard(5)  # 删除5,如果set中不存在5则不会报错 
a = t.pop()  # 随机删除一个值,并且把该值返回给a

3)len,in,copy:略

 

7.3,集合去重

a = [1, 3, 5, 1, 7, 3, 9, 2, 6, 1, 3]

去重:

set(a)  # {1, 2, 3, 5, 6, 7, 9}

去重保持顺序不变,序列中的元素可hash:

def dedupe(items):
    seen = set()
    for item in items:
        if item not in seen:
            yield item   # 不用generator的话,还要在新建个列表,然后用该列表append并返回值
            seen.add(item)
list(dedupe(a))  # [1, 3, 5, 7, 9, 2, 6]

去重保持顺序不变 ,序列中的元素不可hash,要先想办法转成可哈希(待补充)

 

8,其他类型

数字(略)

布尔类型(略)

 

9,数据运算

9.1,运算符

+,-, *, /:加减乘除

%:取模

**:次方,即幂

//:整除,返回商的整数部分

 

9.2,比较运算

==:等于

!= : 不等于

<>:不等于

>:大于

<:小于

>=:大于等于

<=:小于等于

 

9.3,赋值运算

=:等于

+=:A+=B即A=A+B,下同

-=:

*=:

/=:

%=:

**=:

//=:

 

9.4,逻辑运算

and

or

not

and或者or可以连接多个,例如 a and b and c,还可以加or,例如a and b and c or d,即(a and b and c) or d

 

9.5,成员运算

in:判断值是否在序列中

not in:判断值是否在序列中

 

9.6,身份运算

is:id是否一样,类型是否是XXX等等,例如type(a) is list

is not

 

9.7,位运算

&:与

|:或

^:异或

~:反

<<:左移动

>>:右移动

 

9.8,三元运算

result = value1 if condition else value2

  

9.9,boolean表达式

result = a or b    # 如果a是真result=a,如果a是假result=b

备注:写boolean可能会代码难以阅读,建议使用三元运算,或者辅助函数

 

10,操作数据

10.1,各类推导式

列表推导:

[i for i in range(10) if i > 5]

生成器表达式:

(i for i in range(10) if i > 5)

集合推导:

{i for i in range(10) if i > 5}

字典推导:

prices = {'ACME': 31, 'AAPL': 26, 'IBM': 29, 'HPQ': 35, 'FB': 33}
items = ('ACME', 'IBM', 'FB')
{key: value for key, value in prices.items() if value > 30}       # {'ACME': 31, 'HPQ': 35, 'FB': 33}
{key: value for key, value in prices.items() if key in items}     # {'ACME': 31, 'IBM': 29, 'FB': 33}
# 另一种形式:
dict((key, value) for key, value in prices.items() if value > 30) # {'ACME': 31, 'HPQ': 35, 'FB': 33}

注意:没有元组推导

 

11,切片

11.1,切片原理

“[]”运算符是交给__getitem__和__setitem处理的(详见guxh的python笔记:类的属性)

class Seq:

    def __init__(self, components):
        self.components = components

    def __getitem__(self, index):
        return self.components[index]

s = Seq([1, 2, 3, 4, 5, 6])
print(s[0])     # 1
print(s[0:3])   # [1, 2, 3]

 对s[0],s[0:3]的取值委托给了self.components[index]处理,看看self.components拿到的index到底是什么?

class Seq:

    def __getitem__(self, index):
        return index

s = Seq()
print(s[0])       # 0
print(s[0:3])     # slice(0, 3, None)
print(type(s[0:3]))   # <class 'slice'>
print(dir(s[0:3]))    # 有'indices', 'start', 'step', 'stop'这些方法

S.indices(len)  —> (start, stop, stride)

给定长度为len的序列,计算start,stop,stride,超出边界的索引被截掉。

 

11.2,切片技巧

序列反转:

>>> s = [1, 2, 3, 4]
>>> s[::-1]
[4, 3, 2, 1]

 

  

12,不同数据类型的传参

可以参考一篇文章:《Python学习系列之值类型与引用类型》

摘取如下:

C++中是传值和传引用(指针)。c语言加上*号传递指针就是引用传递,而直接传递变量名就是值传递)

Java是传值(传值和传引用,只不过引用就是内存地址,所以也是值)。Java里区分值和引用,是因为值存储在栈里,而引用对象存储在堆里(引用本身在栈里)。

而Python所有的都是对象,都是引用,所以所谓的值类型都是不可变类型。类似于Java的字符串类型。

所以Python中的参数传递都是传递引用,也就是传递的是内存地址。只不过对于不可变类型,传递引用和传递值没什么区别。而对于可变类型,传递引用是真的传递内存的地址。

听说python只允许引用传递是为方便内存管理,因为python使用的内存回收机制是计数器回收,就是每块内存上有一个计数器,表示当前有多少个对象指向该内存。每当一个变量不再使用时,就让该计数器-1,有新对象指向该内存时就让计数器+1,当计时器为0时,就可以

收回这块内存了。当然还有其他的GC方法,否则计数器回收,无法解决循环引用的问题。

posted @ 2019-01-09 22:56  GUXH  阅读(436)  评论(0编辑  收藏  举报