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 条评论
登录 后参与评论

相关文章

来自专栏思考的代码世界

Python基础学习05天

15450
来自专栏用户2442861的专栏

static在C和C++中的用法和区别

http://blog.csdn.net/skyereeee/article/details/8000512

31710
来自专栏Phoenix的Android之旅

动态代理-进阶高级开发必学技能

关于代理模式的话题有很多, 在开发中经常用到的应该是静态代理模式,能很好的去耦合。 动态代理是代理模式的另外一种实现。

9630
来自专栏MelonTeam专栏

Fork/Join 框架

1. 简介 1.1 什么是Fork/Join框架 Java 5 引入了 Executor 和 ExecutorService 接口,使得 Java在并发支持...

22760
来自专栏尚国

PHP反序列化漏洞

这里你可以看到, 我代码里的类定义为: class F, 这个序列化就是 F, 我定义变量名字是filename, 它这里也是 filename, 我们可以修改...

12220
来自专栏技术之路

实例化和具体化详解

primer Plus在解释具体化和实例化看的有点乱,分解出来备忘 在代码中包含函数模板本身并不会生成函数定义,它只是用于生成函数定义的方案 编译器使用模板为我...

21550
来自专栏coding for love

JS入门难点解析7-this

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

13010
来自专栏xingoo, 一个梦想做发明家的程序员

c++中类长度解析

通常我们定义一个类,它所占的空间有多大呢? 首先我们看一下下面的这个类 class A{ public: void func1(void){ ...

20250
来自专栏程序员互动联盟

【Java基础】Java语言中的流程控制

前言: 上一篇文章写了面向对象的基础知识,接下来就开始写真正的代码了。逻辑判断和控制流程是编码中最小的逻辑单元,是整体逻辑的基石,所以每一个写代码的对于这一块...

38850
来自专栏乐百川的学习频道

Python 正则表达式

最近研究Python爬虫,很多地方用到了正则表达式,但是没好好研究,每次都得现查文档。今天就专门看看Python正则表达式。本文参考了官方文档 re模块。 模式...

247100

扫码关注云+社区

领取腾讯云代金券