您的位置:首页 > 理论基础 > 数据结构算法

python程序设计第4课第二章复合数据结构

2020-05-11 04:12 78 查看

四,在Linux下运行python

怎么装Linux?

Ubuntu Docker(有点类似虚拟机一样,可以让你在A系统上很快的启动B系统的东西)也可以用Cygwin,Cygwin可以在windows下运行类似于Unix的内核,没有图形界面。但是实际上你去用Linux绝大多数情况下也不是用Linux的图形界面而是用它的shell,Cygwin就是windows上面类似于Unix和Linux的shell,你在里面键入的命令必须是Linux命令而不是window commond line里的命令。Cygwin的优点在于装起来很容易,不会对windows造成什么损害

在Linux下运行python脚本
*演示中出现的命令:
$ls-l                        显示文件及其详细信息
$ls                          显示当前目录中的文件名字
$dir                         dir命令的功能和ls命令类似,不过参数比较少
$vi hello.py                 查看hello.py的内容
$python hello.py             运行
$vi job.sh                   查看job.sh脚本内容

接下来已经在目录下写了个hello.py的文件,内容是print ‘Hello there,Im in %s…’ %_ name _ (例子里老师在Linux底下或者说是Cygwin底下用的是python2)。你直接$python hello.py就可以运行了。但是linux底下还有叫做脚本的东西。脚本可以做一些批处理的任务,一般来说对于一些大型程序,我们会把执行的命令写在脚本里面让脚本自动执行,就不用每天去重复手动键入命令

例子:
现在已经建立了一个python源程序hello.py。现在为了演示,在Cygwin底下建一个叫job.sh的脚本。脚本内容如下
#!/bin/bash                  linux底下shell脚本的第一行,不用去管它
python hello.py              要运行的命令,刚刚是自己手动输入的

那么怎么运行job.sh脚本呢(它能帮你自动执行命令而不需要自己手动键入)?

得先把mod变成executable(可执行的)

法一(不是好方法):
1.创建job.sh文件

2.$chmod +x job.sh
(表示把mod变成executanle,+x表示executable,把它的模式要换一下。详细的说明可以看PPT里的chmod命令)

演示时老师已经改了它的chmod,改变后的job.sh用ls-l查看得到结果:
-rwxr-xr-x 1 gli  None 28 3月   3 14:05  job.sh
*头上的东西是它的权限,三个字母表示一组权限。rwx是文件拥有者的权限,r-x表示文件拥有者所在组的权限,r-x表示所有人的权限(r表示read权限,x表示executable权限,w表示write权限)

3. ./job.sh        在shell底下执行脚本
法二:
#!/usr/bin/env python
要在python源程序首行加上这行东西。让Linux系统使用env命令找到python并执行,一般写程序会加上,这行只对linux的shell起作用。#!叫做shebang,用于指定运行脚本所需的解释器

$chmod +x hello.py             修改权限,保证hello.py文件是executable的

$./hello.py
运行时没有在任何地方写python来指定python作为解释器来运行hello.py脚本。在Linux底下它就自动的知道python解释器来运行py这样就不需要job.sh文件,直接把python源程序当作脚本来运行

与上节课的知识相联系就构成了python源程序的规范写法:

例:
#!/usr/bin/env python

def say_something():
print 'Hey! This is a standard way to write python grogram'

if _name_=='_main_':
say_something()
*函数的定义和调用分开

有可能你的程序在windows里写的和编辑的,也按照老师要求的写了。但是你的脚本在Linux就是不能用$…/hello3.py这种运行Linux脚本的通用方式运行,怎么运行都会出错。问题在于在windows底下换行不是用了换行,它用了回车中换行两个字,回车中换行的两个字符是不可见的。所以在Linux中想用这种方式运行你在windows底下写的一个python script时,有可能在python script每一行的末尾都不是用了换行符,而用了回车+换行符。有时候Linux shell就不认这种结果,因为你加进去了回车。windows在每行的末尾回车(CRLF)时都用了Carriage return +Line feed两个字符来标识一行的结尾,这就是问题所在。本身后面应该只有Line feed一个换行符,但是因为你是在windows种编辑的,给你加上了Carriage return。
解决这种问题的方法是用Linux底下的vim。使用命令:set ff=unix,它会自动检查每一行的末尾,把所有windows底下的Carriage return+Line feed统一改为Line feed。所以更好的办法是你如果要在window底下写python程序的时候,你最好把换行的形式换成unix,让它只用一个字符来换行。

五,python的"动态类型" 赋值语句a = 3发生了什么?

a是变量,3是对象,变量和对象在内存中通过引用(或者说指针)相联系,它们不在内存中同一个东西。"类型"的概念属于对象,而不是变量。对于3这个对象除了有整数3这个值外,在python内存中它实际是个结构体,还有其他的信息,其中就有类型标识符和引用计数器(与垃圾收集机制相配合)。所以变量是"通用"的。因此给一个变量赋新值是生成一个新对象再让变量去引用这个新对象。

但是对于列表这种可以原地修改的对象,情况会不一样。之前的b=a的情况,会让你觉得改了a,b不会变
。列表则会让你觉得改了a,b也会变。

例:
>>>a=[1,2,3]
>>>b=a
>>>b
[1,2,3]
>>>a[0]=111
>>>a
[111,2,3]
>>>b
[111,2,3]

之所以如此,原因在于a,b引用的是同一个列表对象(具体见PPT),要防止这种情况可以用对象拷贝。列表的列表,情况比较复杂,仅进行shallow copy是不会把列表的列表进行完全拷贝的。对于这种shallow copy,它还是在被shallow copy的对象跟新生成的对象两者之间共享了对列表的列表的引用。具体见PPT的例子

六,元组

*元组是不可变序列。但是元组可以通过下标访问,有双向索引功能
*>>>a=(1,) 定义只有一个元素的元组时不要忘了加逗号

1.元组的创建

法一:直接等于号将一个元组赋值给变量
法二:使用tuple函数将其他序列转换为元组

*>>>x=tuple()可用于创建空元组
*tuple()函数如果传进去一个元组,不会给你创建一个新的对象。产生的元组id与传进去 的元组id相同

2.元组的删除

*元组是不可变序列,要用del只能是一次性删除整个元组

3.元组操作,元组与列表的区别

因为元组是不可变序列,所以不能用.append() .extend() .insert()增加元素不能用pop(),remove() del tuple[index]删除元素

因为元组仍可以访问,所以有index(),count()方法。也可以用切片来访问元组,但是不能用切片操作来改变元组

4.元组的优点(具体见PPT)

一些包含不可变数据的元组可以用作字典的键。列表则不可以当作字典的键使用,因为列表可变

5.对于元组不可变性的讨论

(实际上关于可变与不可变的微妙理解在上节课已经讨论过,一样的道理)元组的不可变性只适用于元组本身顶层而并非其内容

例子中元组还是不可变的,两次下标索引改的不是元组本身。元组第二个元素存的是一个引用,引用并没有被改变,改变的是引用所指向的列表的第一个元素。

6.序列解包(具体见PPT)

字典的序列解包只会把键提出来,相应的值会丢失掉。而且因为字典是无序的,提出的键不是按你看到的顺序解包的

*通过PPT中序列解包的例子可以加深对zip函数的理解

7.生成器推导式

虽然与列表推导式很像,但是生成器推导式使用圆括号,不返回元组(没有元组推导式,这点强调过许多次)。而是返回一个一次性的generate object(生成器对象)。

对于generate object对象。可以1.转化为列表和元组2.使用生成器的. _ next _ ()方法遍历3.作为迭代器对象来使用。这个在第五章也会讲到

七,字典

*字典属于键值对的无序可变序列
*字典中的键要为任意不可变对象,如数字,字符串,元组等,反正没有列表

1.创建字典

法一:直接用等于号把一个字典对象赋值给一个变量

法二:使用dict()函数来创建字典
1.利用已有数据创建(配合zip来联系提前创建的keys和values)

例:
>>>keys=['spam','eggs','ham']
>>>values=[1,2,3]
>>>d=dict(zip(keys,values))
>>>d
{'eggs':2,'ham':3,'spam':1}
2.根据给定的键,值创建字典
例:
>>>d=dict(spam=1,eggs=2,ham=3)

*注意>>>d=dict(1=‘spam’,2=‘eggs’,3=‘hams’)会报错,>>>d={1:‘spam’,2:‘eggs’,3:‘hams’}才是对的

*使用=dict.fromkeys()创建值为空的字典。通常用来初始化字典,即只知道键不知道赋什么值的时候

3.字典的删除

del删除整个字典(如del d)或者单个键值对(如 del d[‘eggs’])

4.字典元素的读取

法一:以键作为下标读取键值对的值(如 d[‘hams’])

法二:使用.get方法读取键值对的值(如 d.get(‘eggs’))
*法一和法二的差别在于法一键不存在抛出异常,法二则是返回指定值(如 d.get(‘apple’,4) 不存在返回4)或者返回默认的None,这是法二相对法一的优点
*keyerrror实际上是python内置的异常类名词,专门针对用户读取的key不存在的情况

法三:.item() .keys() .values()

*items( ) keys( ) values( ) 要注意区别,在python2都是返回列表。在python3则不再返回list,
而是返回dict items,dict keys,dict values

例:
python2: >>>d={'spam':1,'eggs':2,'hams':3}
>>>d.items()
[('eggs',2),('hams',3),('spam',1)]
>>>d.keys()
['eggs','ham','spam']
>>>d.values()
[2,3,1]
python3:>>>d={'spam':1,'eggs':2,'hams':3}
>>>d.items()
dict_items([('eggs',2),('hams',3),('spam',1)])
>>>type(d.items())
<class 'dict items'>
....

不过这种改变在for循环中使用时也没什么影响

例:
>>>for k,v in d.items():
...      print("%s=%s" %(k,v))
...
eggs=2
ham=3
spam=1

*字典视图
字典视图总是反映着字典的变化。但是使用起来一般不受影响,因为无论是.items()方法,.keys()方法,一般都不需要手动调用,而是放在for循环里使用。如:>>>for key,value in d.items():或者>>>for item in d.items():(返回一个个元组)。考试时只要这些方法知道分别返回什么东西,而python3字典视图的深入理解不会重点考察

5.字典元素的添加与修改

法一:直接添加或者修改(如 d[‘apple’]=4)

法二:.update()方法
使用.update()方法来添加时可以接收一个字典(如d.update(spam=111),d.update({‘apple’:4}) )。也可以接收一个元组或者一个列表,但是要用元组套元组的方法,否则会报错。也可以传入大的嵌套列表和元组,只要最小元素能配对就行

法三:del删除,.clear(),.pop(),.popitems() (没怎么讲,具体见PPT)

*注意像字典和集合这样的无序数据类型,用.pop()方法是没有参数的

6.字典推导式

(没仔细讲,具体看PPT)

*用于构造字典。大括号包裹,头部需要出现冒号分隔的key与value的组合,后面一般是一个for循环

编辑于2020-3-5 16:52
修改于2020-4-26 21:03

CS_Lee_ 原创文章 16获赞 0访问量 2304 关注 私信
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: