Python学习 day07
一、关于解决问题的思路
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的更多相关文章
- Python学习day07 - Python进阶(1) 内置方法
figure:last-child { margin-bottom: 0.5rem; } #write ol, #write ul { position: relative; } img { max- ...
- python学习 day07打卡 文件操作
本节主要内容: 初识文件操作 只读(r,rb) 只读(w,wb) 追加(a,ab) r+读写 w+写读 a+追加写读 其他操作方法 文件的修改以及另一种打开文件句柄的方法 一. 初识文件操作 使用py ...
- Python学习第五堂课
Python学习第五堂课推荐电影:华尔街之狼 被拯救的姜哥 阿甘正传 辛德勒的名单 肖申克的救赎 上帝之城 焦土之城 绝美之城 #上节内容: 变量 if else 注释 # ""& ...
- python学习之旅
python学习分类 python基础 +- day01——python初始.变量.常量.注释.基础数据类型.输入.if day02——while.字符串格式化.运算符.编码初识 day03—— ...
- Python学习--04条件控制与循环结构
Python学习--04条件控制与循环结构 条件控制 在Python程序中,用if语句实现条件控制. 语法格式: if <条件判断1>: <执行1> elif <条件判断 ...
- Python学习--01入门
Python学习--01入门 Python是一种解释型.面向对象.动态数据类型的高级程序设计语言.和PHP一样,它是后端开发语言. 如果有C语言.PHP语言.JAVA语言等其中一种语言的基础,学习Py ...
- Python 学习小结
python 学习小结 python 简明教程 1.python 文件 #!/etc/bin/python #coding=utf-8 2.main()函数 if __name__ == '__mai ...
- Python学习路径及练手项目合集
Python学习路径及练手项目合集 https://zhuanlan.zhihu.com/p/23561159
- python学习笔记-python程序运行
小白初学python,写下自己的一些想法.大神请忽略. 安装python编辑器,并配置环境(见http://www.cnblogs.com/lynn-li/p/5885001.html中 python ...
随机推荐
- (转)关于Update语句的锁
原文地址:http://www.cnblogs.com/wdfrog/p/3144020.html 环境:MSSQL2005,在Read Committed级别 语句A:begin tranUpdat ...
- The Suspects——Asia Kaohsiung 2003
原创 The Suspects Time Limit: 1000MS Memory Limit: 20000K Total Submissions: 48698 Accepted: 23286 Des ...
- Recyclerview添加头布局和尾布局,点击效果
简介: 本篇博客主要包括recyclerview添加多种布局以及添加头布局和尾布局,还有item点击事件 思路: 主要重写Recyclerview.Adapter中的一些方法 1.public int ...
- CentOS 系统管理与yum软件仓库搭建
重启 reboot shutdown -r now init 6 关闭 init 0 shutdown -h now shutdown -h 20:25 #8点25关机查看内存 free CPU利用率 ...
- WinForm中自定义搜索框(水印、清空按钮、加载中图标)
public partial class CustomSearchBar : TextBox { private readonly Label lblwaterText = new Label(); ...
- php CI框架 使用PDO 的连接配置
$db['default'] = array( 'dsn' => 'mysql:dbname=hejun;host=192.168.137.127', //'hostname' => '' ...
- 强制所有网页链接在同一页面打开或者在TabControl中弹出新窗口
IEwebbrowser中老生常谈的话题. 一般的解决都是通过 // webBrowser.Navigating += WebBrowser_Navigating; 注册转跳前事件 private v ...
- 《C#多线程编程实战》2.6 ManualResetEventSlim
这个比较好理解的. 正如书上所言,如同一直在打开的大门的屋子,谁要进去,谁就自己的关门,出来的时候在开开. 常用的方法 有三个: Set() //设置为有信号,也就是让等待的线程不用继续等待,唤醒等 ...
- BeanShell Processor_使用Java处理脚本
版权声明:本文为博主原创文章,未经博主允许不得转载. [try-catch] 建议使用Try----Catch块,这样Java语句出现问题时,日志更清晰: try { //java代码 } catch ...
- IO相关3(string流)
sstream 头文件定义了三个类型来支持内存 IO,这些类型可以向 string 写入数据,从 string 读取数据,就像 string 是一个 IO 流一样. istringstream 从 s ...