前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python3--中一些常见的坑(机制上的问题)

python3--中一些常见的坑(机制上的问题)

作者头像
py3study
发布2018-08-02 16:22:14
3550
发布2018-08-02 16:22:14
举报
文章被收录于专栏:python3python3

python中

is,==,id 的意思

== :数值的比较

is :内存地址的比较

id :查看内存地址

list(列表)中存在的一些坑

重点:在循环一个列表时,最好不要进行删除的动作(一旦删除,索引会随之改变),容易错误。

将下面列表中索引为奇数的元素删除

li = ['python', 'php', 'java', 'ios', 'C++', 'C', 'Go']

错误的方法

代码语言:javascript
复制
li = ['python', 'php', 'java', 'ios', 'C++', 'C', 'Go']
for i in li:
    s = li.index(i)
    if s % 2 == 1:
        li.pop(s)
print(li)

执行结果

['python', 'java', 'ios', 'C', 'Go']

很明显,这结果跟我们想的不一样

正确的方法:

1.利用切片的方式

代码语言:javascript
复制
del li[1::2]
print(li)

执行结果为

['python', 'java', 'C++', 'Go']

2.将偶数添加到新列表,最后将原始列表覆盖

代码语言:javascript
复制
li_new =[]
for i in li:
    if li.index(i) % 2 == 0:
        li_new.append(i)
li = li_new
print(li)

执行结果

['python', 'java', 'C++', 'Go']

3.如果想要在循环列表的时候,删除呢?

倒着删除就可以了

代码语言:javascript
复制
for i in range(len(li)-1, -1, -2):
    print(li[i])

执行结果

Go

C++

java

python

倒着删除不影响前面列表的索引顺序

这个答案才是正确的,因为每次列表删除后,原列表的索引值都会改变,导致结果不一样

dict(字典)中一些错误的使用方法

重要:在循环列表或者字典的时候,千万不要做添加或者删除操作

代码语言:javascript
复制
dic = dict.fromkeys('abc', 'sam') # 'abc'为一个可迭代对象
print(dic)

执行结果

{'c': 'sam', 'a': 'sam', 'b': 'sam'}

这里有个坑

代码语言:javascript
复制
dic = dict.fromkeys([1, 2, 3], [])
print(dic)

执行结果

{1: [], 2: [], 3: []}

给上面的空列表添加一元素

dic[1].append('你好')

print(dic)

执行结果

{1: ['你好'], 2: ['你好'], 3: ['你好']}

上面,dic里面的3个列表,在内存中对应的是同一个列表,所以里面的内容相同

例2

dic = {'k1':'value1','k2':'value2','name':'sam'}

将dic字典中含有k元素的键,对应的键值对删除

错误的方法

代码语言:javascript
复制
for i in dic.keys():
    if 'k' in i:
        del dic[i]
print(dic)

执行报错

RuntimeError: dictionary changed size during iteration

意思就是,在循环字典过程中,不允许改变字典

不能删除,那么尝试一下能否添加吧

count = 0

for i in dic:

    dic[i + str(count)] = dic[i]

    count += 1

上面代码,第一次添加k10,第二次添加k21

执行代码也报错

RuntimeError: dictionary changed size during iteration

那么如果一定要添加,怎么做?

先将含有k的键值对,添加到列表,然后循环列表,删除字典的key

代码语言:javascript
复制
s = []
for i in dic:
    if 'k' in i:
        s.append(i)
for x in s:
    del dic[x]
print(dic)

执行结果

{'name': 'sam'}

set集合

数据类型:

不重复,无序,它里面的元素是可哈希的,他本是不可哈希的,他不能作为字典的key

去重有2种方法。1,用集合,2.用算法

set的作用:

1,去重

2,数据关系的测试

例子

代码语言:javascript
复制
li = [11, 11, 22, 22, 33, 33, 33, 44]
li = list(set(li))
print(li)

执行结果为

[33, 11, 44, 22]

列表的去重,直接转换为集合,就可以了

set集合的用法

add 增

代码语言:javascript
复制
s1 = set()
s1.add('sam')
print(s1, type(s1))

执行结果

{'sam'}

update迭代增加

代码语言:javascript
复制
s1 = set()
s1.add('sam')
s1.update('abc')
print(s1)

2.set 删

代码语言:javascript
复制
set1 = {'sam', 'tom', 'zhangsan', 'lisi', 'wangwu'}
set1.remove('sam') #删除一个指定元素
print(set1)
set1.pop()  #随机删除一个元素
print(set1)
set1.clear() #清空集合
print(set1)
del set1    #删除集合

pop随机删除方法有返回值

set()表示一个空集合

集合没有改的方法,查只能for循环

for i in set1:

    print(i)

执行结果

tom

sam

lisi

zhangsan

wangwu

set关系测试

交集& ,intersection

代码语言:javascript
复制
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}
print(set1 & set2)
print(set1.intersection(set2))

执行输出

{4, 5}

{4, 5}

并集 |,union

print(set1 | set2)

print(set1.union(set2))

执行输出

{1, 2, 3, 4, 5, 6, 7, 8}

{1, 2, 3, 4, 5, 6, 7, 8}

反交集 ^  symmetric_difference

print(set1 ^ set2)

print(set1.symmetric_difference(set2))

执行输出

{1, 2, 3, 6, 7, 8}

{1, 2, 3, 6, 7, 8}

差集

print(set1 - set2)

执行输出

{1, 2, 3}

子集 issubset

例子

代码语言:javascript
复制
set1 = {1, 2, 3}
set2 = {1, 2, 3, 4, 5, 6}
print(set1.issubset(set2))

执行结果

True

超集

print(set2.issuperset(set1)) #set2是set1的超集

执行结果

True

将集合转换为可哈希的类型,可以作为字典的key

代码语言:javascript
复制
set1 = {'barry', 'tom'}
set2 = frozenset(set1)
print(set2)

执行结果为

frozenset({'tom', 'barry'})

深浅copy

代码语言:javascript
复制
l1 = [1, 2, 3]
l2 = l1
l2.append(111)
print(l1, l2)

执行结果,结果是一样的

[1, 2, 3, 111] [1, 2, 3, 111]

对于赋值运算,指向的是同一个内存地址,字典,列表,集合都一样

copy不是指向同一个,在内存中开辟了一个内存空间

代码语言:javascript
复制
l1 = [1, 2, 3]
l2 = l1.copy()
l1.append(111)
print(l1, l2)
print(id(l1), id(l2)) #打印出内存地址

执行结果

[1, 2, 3, 111] [1, 2, 3]

2230811766152 2230811765256

例子2

代码语言:javascript
复制
l1 = [1, 2, [1, 2, 3], 4]
l2 = l1.copy()
l1[2].append(666)
print(l1)
print(l2)

执行结果

[1, 2, [1, 2, 3, 666], 4]

[1, 2, [1, 2, 3, 666], 4]

重点:对于浅copy来说,第一层创建的是新的内存地址,而从第二层开始,指向的都是同一个内存地址

深copy,需要导入一个模块copy

代码语言:javascript
复制
import copy
l1 = [1, 2, [1, 2, 3], 4]
l2 = copy.deepcopy(l1)
l1[2].append(666)
print(l1)
print(l2)

执行结果

[1, 2, [1, 2, 3, 666], 4]

[1, 2, [1, 2, 3], 4]

重点:

深copy,两个是完全独立的,改变任意一个的任何元素(无论多少层),另一个绝对不会改变

浅copy,第一层是新的,从第二次开始,共用一个

python开发面试题:

下面的例子,l2是深copy还是浅copy

代码语言:javascript
复制
l1 = [1, 2, 3, [22, 33]]
l2 = l1[:]
l1[3].append(666)
print(l2)

对于切片来说,它是执行了浅copy

总结,切片就是浅copy

编码补充

python内部编码,使用unicode

s = 'sam'

s1 = s.encode('utf-8') # unicode ---> utf-8

s2 = s.encode('gbk') # unicode ---> gbk

utf-8转换成unicode

s3 = s1.decode('utf-8')

print(s3)

sam

blob.png
blob.png

重点:utf-8和gbk不能直接互相转化,必须通过unicode才可以

例子

代码语言:javascript
复制
s = '你好'
s1 = s.encode('gbk') #unicode转化为gbk
s2 = s1.decode('gbk') #gbk转化为unicode
s2.encode('utf-8') #unicode转化为utf-8
print(s2)

执行为

你好

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-03-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档