一、关于解决问题的思路

1、删除列表中索引为单数的元素。

别人的思路:

  • 利用切片
li = [11, 22, 33, 44, 55]
li = li[::2]
print(li)

  思考:虽然学了python,学了切片,但一直都没好好利用过

  • 建立新列表
li = [11, 22, 33, 44, 55]
li1 = []
for i in range(len(li)):
if i % 2 == 0:
li1.append(li[i])
li = li1
print(li)

  思考:写程序一定不能思维定式,表面呈现并不一定就是内部过程

  • 倒叙删除
li = [11, 22, 33, 44, 55]
for i in range(len(li) - 1, -1, -1):
if i % 2 == 1:
print(i)
li.pop(i) # del li[i]
print(li)

  思考:如果正序循环,删除元素会影响后面元素的索引,而倒叙则不会,是一种好方法

自己的思路:

  • 第一种
li = [11, 22, 33, 44, 55]
i = 0
while i < len(li) - 1:
i += 1
del li[i]
print(li)
  • 第二种
li = [11, 22, 33, 44, 55]
flag = True
for i in li:
if flag:
flag = False
continue
li.remove(i)
print(li)

  反思:自己写的两种方法比较讨巧,第二种更是经过了debug探寻了for循环的运行情况才想到的,之后再看很可能都不知道自己为什么这么写。for in循环应该也是按索引循环的,因此删除一个元素后,该元素紧邻的后面元素就不会取到了。

  自己写的整个思路相较上面的思路实在是太死板了。。。

2、删除dic中key值含有‘k’的键值对

  • 建立新字典
dic = {'k1': 'v1', 'k2': 'v2', 'a3': 'v3', 'k4': 'v4', 'a5': ' v5'}
dic1 = {}
for i in dic:
if i.find('k') == -1: # if 'k' not in i:
dic1[i] = dic[i]
dic = dic1
print(dic)
  • 列表保存含‘k’的键,删除
dic = {'k1': 'v1', 'k2': 'v2', 'a3': 'v3', 'k4': 'v4', 'a5': ' v5'}
li = []
for i in dic:
if 'k' in i:
li.append(i)
for i in li:
dic.pop(i)
print(dic)

  思考:这个题自己没做,只能参考下别人的思路。第一种同上面列表删除的第二种方法。第二种方法,因为dict在循环中不能做修改操作,会报错,所以要把要删除的键保存下来。

二、dict的fromkeys()方法

  fromkeys(*args, **kwargs)  --  直接看源代码注释:

  Returns a new dict with keys from iterable and values equal to value.

  再看示例:

dic = dict.fromkeys([1, 2, 3])
print(dic) dic = dict.fromkeys([1, 2, 3], 'python')
print(dic) dic = dict.fromkeys([1, 2, 3], ['python'])
print(dic)

  结果:

  这个方法基本就这么个意思了。

  重点:这里有个小坑,如下:

dic = dict.fromkeys([1, 2, 3], ['python'])
print(dic)
dic[1].append('java')
print(dic)
dic[2].extend('C++')
print(dic)
dic[3] = 'js'
print(dic)

  结果:

  由上例可看出,使用fromkeys()创建的dict,在对任何一个键的列表做修改操作时会同时修改所有键下的值。而赋值操作却对其他的键的值没有影响。

  这是因为fromkeys()在生成dict时,因为每个键对应的值相同,所以直接将所有key的value指向了同一个地址。。。因此,对所有值是可变元素的value,修改其中一个,所有的都会变。。。直接赋值是因为将该value指向了新的地址。。。类似浅复制,理解原理都好说,就是要记得这个坑!!!

三、set

set的创建,两种方式:

1、s = {1, 2, 3}

2、s = set([1, 2, 3])

其实也就是一种方式,第二种创建方式仔细看其实就是用set()方法转化,将list转化为set

至于set为什么用{}表示呢,因为set的性质基本与dict的key相同,再就是因为。。。刚刚想到。。这是集合呀,当然要用{}

set的基本性质:无序、不重复、可哈希、且set的元素只能是不可变数据类型(因此若需要去重的,可直接转为set,至于去重比较的是值还是地址就不清楚了,因为不可变元素在python的内存中都只存在一份,应该跟java一样是值和地址吧)

add()

update()  --  类似list的extend,是迭代的增加的

pop()  --  随机删除

remove()  --  按元素删除

clear()  --  清空

del  删除

改是不可能改的,都是不可变元素怎么改呢  ╮(╯_╰)╭

只能用for in循环查

set的重点

1、交集   & 或 intersection()

2、并集   | 或 union()

3、反交集/补集  ^ 或 symmetirc_difference()

4、差集  - 或 difference()

5、包含关系

< 或 issubset()  真子集

> 或 issuperset()  这个。。叫真母集嘛

>=   <=   ==  这些都可以用,一看就明白

frozenset

创建即用frozenset(),参数是个可迭代的就可以

frozenset就是个冻结的集合,不能增、删(当然可以删除整个集合),只能查

四、深浅拷贝

1、赋值

  说深浅拷贝前先说说赋值,我们都知道赋值即是把对象地址赋给新变量,两个变量指向同一个地址。如下例:

li = [1,2,3]
li[1] = li
print(li)

  结果:

  可以看到li[1]变成了[...],即内容为无限的,这是因为li[1]又指向了li这个对象,li里的1又指向了li,无限循环。

2、浅拷贝

  浅拷贝有四种形式:切片操作,list的copy方法(set、list、dict都有这个方法,tuple没有,其他的对象以后遇到再查源码),工厂函数,copy模块中的copy方法

li = [1, 2, 3]
li1 = li[:] # 切片
li2 = li.copy() # copy方法
li3 = list(li) # 工厂函数
import copy
li4 = copy.copy(li) #copy模块中的copy方法 print(li, id(li))
print(li1, id(li1))
print(li2, id(li2))
print(li3, id(li3))
print(li4, id(li4))

  结果:

  可以看到,都实现了复制操作,原li对象地址与所有复制得到的变量地址均不同

  再看li[1] = li的例子,只用一种浅拷贝方法测试:

li = [1, 2, 3]
li[1] = li.copy()
print(li)

  结果:

  可以看到,浅拷贝不同于赋值操作,变量li[1]指向的不再是原来的li,所以在底层是确确实实做了一次拷贝工作的。

  浅拷贝的最大问题就是,当拷贝的内容出现引用类型时,如:

li1 = [1, [2, 3], 4]
li2 = li1[:]
li2[1].append(5)
print(li1)
print(li2)
print(id(li1[1]))
print(id(li2[1]))

  结果:

  从上可看出,浅拷贝对于元素内部的引用类型,拷贝时只是将新拷贝的对象里的该元素指向了原对象里的该元素的地址,即新旧元素中的引用对象是同一个

3、深拷贝

  深拷贝使用copy中的deepcopy()方法,深拷贝即相对于浅拷贝,解决了上面所述的问题。deepcopy 本质上是递归 copy,例:

import copy
li1 = [1, [2, 3], 4]
li2 = copy.deepcopy(li1)
print(id(li1[1]))
print(id(li2[1]))

结果:

总结

赋值即最外层元素是同一个地址

浅拷贝即最外层元素不是同一个,但里面的引用都是同一个

深拷贝则所有的元素,不管外层父元素还是内层子元素等等全部都是新的

小知识

1、关于转化成bool

  转化成bool值是False的有:None  、0  、‘’  、[]  、()  、{}  、set() (即0和所有空的东西)

2、元祖表示的问题,例:

tu = (1)
print(tu, type(tu))
tu = (1,)
print(tu, type(tu))
tu = ([1, 2])
print(tu, type(tu))
tu = ([1, 2],)
print(tu, type(tu))

结果:

  从上可以看出,对于元祖中只有一个元素的情况,在初始化定义时,一定要在该元素后面加个“,”。

  这个问题很好理解的,因为在这里程序中的()有两种含义,一是表示()里面内容是个整体,二是表示()是个元祖,为了不产生歧义,自然是只能有一种意思,而第一种意思肯定是要先考虑的啦,所以第二种就得换个表示方法了啦

3、enumerate()

  对于一个可迭代的(iterable)/可遍历的对象(如列表、字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值

  enumerate多用于在for循环中得到计数

  像之前想在for循环得到索引,一直用的是for i in range(len(li)),i能表示索引,但这只是一种变通方法,循环的也只是数字,得到列表的值还需要用li[i]。有了enumerate()后,可以使用如下方法:

li = ['豆浆', '油条', '包子', '烧麦', '油饼', '鸡蛋']
for index, i in enumerate(li, 2):
print(index, i)

  结果:

可以看到,enumerate(iterable, start=0) ,第一个为循环内容(必须可迭代),第二个为起始序号,默认为0

Python学习 day07的更多相关文章

  1. Python学习day07 - Python进阶(1) 内置方法

    figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...

  2. python学习 day07打卡 文件操作

    本节主要内容: 初识文件操作 只读(r,rb) 只读(w,wb) 追加(a,ab) r+读写 w+写读 a+追加写读 其他操作方法 文件的修改以及另一种打开文件句柄的方法 一. 初识文件操作 使用py ...

  3. Python学习第五堂课

    Python学习第五堂课推荐电影:华尔街之狼 被拯救的姜哥 阿甘正传 辛德勒的名单 肖申克的救赎 上帝之城 焦土之城 绝美之城 #上节内容: 变量 if else 注释 # ""& ...

  4. python学习之旅

    python学习分类 python基础    +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...

  5. Python学习--04条件控制与循环结构

    Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...

  6. Python学习--01入门

    Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...

  7. Python 学习小结

    python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...

  8. Python学习路径及练手项目合集

    Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159

  9. python学习笔记-python程序运行

    小白初学python,写下自己的一些想法.大神请忽略. 安装python编辑器,并配置环境(见http://www.cnblogs.com/lynn-li/p/5885001.html中 python ...

随机推荐

  1. 通过网页发布ios应用。

    原文地址:http://www.zhihu.com/question/24304345 两种方法: 1. 测试版本 支持任何类型的开发者帐号,需要在developer后台设置授权deviceID,可以 ...

  2. PAT 1017 Queueing at Bank (25) (坑题)

    Suppose a bank has K windows open for service. There is a yellow line in front of the windows which ...

  3. delphi 创建DLL文件 及其调用和注意事项

    首先创建一个DLL文件,项目自带的代码为: library ProjectPnr; { Important note about DLL memory management: ShareMem mus ...

  4. Ubuntu在用root账户使用xftp连接时提示拒绝连接

    一般来说Linux不允许使用root账户连接,修改配置 vi /etc/ssh/sshd_config #Authentication: LoginGraceTime PermitRootLogin ...

  5. 【C#】 ref out

    ref 通常我们向方法中传递的是值,方法获得的是这些值的一个拷贝,然后使用这些拷贝,当方法运行完毕后,这些拷贝将被丢弃,而原来的值不会受到影响. 这种情况是通常的,当然还有另外一种情况,我们向方法传递 ...

  6. IE11下使用fixed定位时鼠标滚动不平滑

    很久不用IE了,近期做兼容性测试发现一个fixed定位的问题,当元素使用fixed定位时,其应该不随页面滚动,在chrome/firefox/edge下都很完美,元素完全不动,但是使用IE11时,如果 ...

  7. C# 微信openid 用户信息

    前段demo index.html <!DOCTYPE html> <html> <head> <meta charset="utf-8" ...

  8. .Net Core 项目引用本地类库方式(二)

    上篇文章有详细的介绍.Net Core 项目中引用本地类库通过打包,然后Nugety引用方式,这里再介绍一种引用包的方式

  9. 「BZOJ 1001」狼抓兔子

    题目链接 luogu bzoj \(Solution\) 这个貌似没有什么好讲的吧,直接按照这个给的图建图就好了啊,没有什么脑子,但是几点要注意的: 建双向边啊. 要这么写,中间还要写一个\(whil ...

  10. BZOJ 1061 [Noi2008]志愿者招募(费用流)

    题目描述 申奥成功后,布布经过不懈努力,终于成为奥组委下属公司人力资源部门的主管.布布刚上任就遇到了一个难题:为即将启动的奥运新项目招募一批短期志愿者.经过估算,这个项目需要N 天才能完成,其中第i ...