专栏首页python3python3--中一些常见的坑(机制上的问题)

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

python中

is,==,id 的意思

== :数值的比较

is :内存地址的比较

id :查看内存地址

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

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

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

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

错误的方法

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.利用切片的方式

del li[1::2]
print(li)

执行结果为

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

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

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.如果想要在循环列表的时候,删除呢?

倒着删除就可以了

for i in range(len(li)-1, -1, -2):
    print(li[i])

执行结果

Go

C++

java

python

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

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

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

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

dic = dict.fromkeys('abc', 'sam') # 'abc'为一个可迭代对象
print(dic)

执行结果

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

这里有个坑

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元素的键,对应的键值对删除

错误的方法

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

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,数据关系的测试

例子

li = [11, 11, 22, 22, 33, 33, 33, 44]
li = list(set(li))
print(li)

执行结果为

[33, 11, 44, 22]

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

set集合的用法

add 增

s1 = set()
s1.add('sam')
print(s1, type(s1))

执行结果

{'sam'}

update迭代增加

s1 = set()
s1.add('sam')
s1.update('abc')
print(s1)

2.set 删

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

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

例子

set1 = {1, 2, 3}
set2 = {1, 2, 3, 4, 5, 6}
print(set1.issubset(set2))

执行结果

True

超集

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

执行结果

True

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

set1 = {'barry', 'tom'}
set2 = frozenset(set1)
print(set2)

执行结果为

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

深浅copy

l1 = [1, 2, 3]
l2 = l1
l2.append(111)
print(l1, l2)

执行结果,结果是一样的

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

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

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

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

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

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

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

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

例子

s = '你好'
s1 = s.encode('gbk') #unicode转化为gbk
s2 = s1.decode('gbk') #gbk转化为unicode
s2.encode('utf-8') #unicode转化为utf-8
print(s2)

执行为

你好

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 004 python 流程控制语句

    py3study
  • Centos 7 安装python 版本

    py3study
  • 习题29:循环和列表

    创建一个列表使用[],在里面放入列表的数据,然后用逗号隔开,然后python接收这个列表以及里面所有的内容,将其赋给一个变量

    py3study
  • 基础学习python(4)

    adventureisoutthere
  • 12.程序编程基础6:选择和循环

    正常情况下,我们完成一件事情的过程中,可能会存在多种条件限制 如:用户去ATM机取钱->输入取款密码->输入正确,取钱成功 | 输入错误,退卡。 这样的情况...

    大牧莫邪
  • Python语句

    >>> range(1, 11, 2) #起始写了表示从起始开始,后面的11不包含,2表示步长值

    py3study
  • 百布(baibu.la)完成1.65亿B+轮融资

      2017年8月10日,纺织品B2B交易平台“百布”宣布完成1.65亿元B+轮融资。本轮融资由云启资本领投,成为资本、源码资本继续跟投,又是一个B轮融资过...

    躲在树上的域小名
  • python 入门笔记[语法基础(上)]

    以下源码均可直接运行,python其实对于学过c++或c语言的人来说是比较好上手的,主要差别是python更注重格式缩进之类,...

    glm233
  • 福特10亿美元入股AI创业公司,成就底特律无人车领域最大投资

    这是“汽车城”底特律在无人驾驶技术方面的最大投资:福特周五宣布,10亿美元收购人工智能创业公司Argo AI的多数股权。 Argo AI由来自Google和Ub...

    量子位
  • Android APP集成新浪微博分享功能

    直接导入weibosdkcore.jar:适用于只需要授权、分享、网络请求框架功能的项目。 无论使用哪一种方式,都需要先将demo中lib目录下的对应的全部...

    砸漏

扫码关注云+社区

领取腾讯云代金券