Python基础学习笔记(一) | Dayu's Blog

Python基础学习笔记(一)

一、Python基础

0x01 运行机制

  • python解释型语言,因此在运行时解释器将源码转换为字节码,然后再由解释器来执行这些字节码。虚拟机执行脚本:1.完成模块的加载和链接;2.将源代码翻译为PyCodeObject对象(这货就是字节码),并将其写入内存当中(方便CPU读取,起到加速程序运行的作用);3.从上述内存空间中读取指令并执行;4. 程序结束后,根据命令行调用情况(即运行程序的方式)决定是否将PyCodeObject写回硬盘当中(也就是 直接复制到.pyc或.pyo文件中);5.之后若再次执行该脚本,则先检查本地是否有上述字节码文件。有则执行,否则重复上述步骤。

0x02 !/usr/bin/env python 和 #!/usr/bin/python

  • #! /usr/bin/env python是防止用户没有把python安装在默认路径,它执行过程就是先到env设置中查找 python路径,然后调出对应解释器。而/usr/bin/python就是固定死了python的路径。一般推荐#!/usr/bin/env python 然后保存好之后在目录下chmod a+x hello.py,然后直接就可以运行啦。 其次加不加这个头有一个明显区别,如果加了这个头,运行xxx.py可以切到目录下直接./xx.py,如果没有加 这个头则需要python ./xxx.py

0x03 if name == ‘main’: 的解析

  • 首先 if name==“main“ :是 程序的入口。
  • 在python中,当一个module作为整体被执行时, moduel.name 的值将是 ”main” ;而当 一个module被其它module引用时, module.name 将是module自己的名字,当然一个module被 其它module引用时,其本身并不需要一个可执行的入口main了。可以说python中的这种用法很灵活 啊。(用于判断是不是本身执行的还是被别人导入的,如果是别人导入的话就执行就起到函数调用作 用,不会执行导入模块,这样好处就是我导入了你,但是我不想要你的输出,我只想要你模块里面部分 内容。如果不这样我导入了你你还输出显示我不想要的内容。)
  • 用来检测该文件代码是否是主程序文件,也即非模块。从而可以避免执行不必要代码。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #代码1 
    def run():
    print "test is running"
    if __name__ == "__main__":
    print "test main is working"
    #代码2:
    import untitled
    if __name__=="__main__":
    untitled.run()

如果是代码1单独运行的话下面的print会输出,但是如果被代码2导入的话,他只执行函数体,不执行if name 下面的。是用来检测该文件代码是否是主程序文件,也即非模块

  • 最简单理解这个问题就是 print name ,如果是直接执行,那么 name 的值就是 main 。如果是被调用的执行的话,则值是被调用的那个脚本的名称。

0x04 其他

  • 当语句以:结尾时,缩进的语句视为代码块。缩进有利有弊。好处是强迫你写出格式化的代码,但没有规定缩进是几个空格还是Tab。按照约定俗成的管理,应该始终坚持使用4个空格的缩进。缩进的另一个好处是强迫你写出缩进较少的代码,你会倾向于把一段很长的代码拆分成若干函数,从而得到缩进较少的代码。
  • Python程序是大小写敏感的,如果写错了大小写,程序会报错。
  • Python中的变量不需要声明,可以直接输入:a=10;那么你的内存里就有了一个变量a, 它的值是10, 它的类型是integer (整数)。 在此之前你不需要做什么特别的声明,而数据类型是Python自动决定的。

二、Python数据类型

0x01 列表

  • 简介
    列表就是可变的数组,之所以是可变的是因为随随便便就可以增加和减少操作。形式如下:list = []。 访 问列表主要是索引和切片,索引从左到右第一个是0,从右到左第一个是-1;切片包含起始的数字,但 不包含末尾的数字。

    1
    2
    3
    4
    5
    6
    Example:(访问列表两种方式,单个元素访问通常下标,多个元素访问通常切片。)
    list=[1,2,9,4]
    print list[0],list[1:3]
    print list[::-1] 步长切片
    Result: 1 [2,9]
    [4921]
  • 追加

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    Example1:(单一追加)
    dota=[1,2,3]
    dota.append(9)
    print dota
    Result: [1,2,3,9]

    Example2:(列表和列表之间追加)
    dota1=[1,2,3]
    dota2=[4,5,6]
    dota1.extend(dota2)
    Result: [1,2,3,4,5,6]

    Example3:(+连接,*重复)
    dota1 = [1,2,3,4]
    dota2 = [3,4]
    dota3 = dota1+dota2
    dota4 = dota2*2
    print dota3,dota4
    Result:[1,2,3,4,3,4] [3,4,3,4]
  • 插入指定位置

    1
    2
    3
    4
    5
    Example:
    dota=[1,2,3]
    dota.insert(2,9)
    print dota
    Result: [1,2,9,3]
  • 删除列表元素

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    Example1:(删除末尾元素)
    dota=[1,2,3]
    dota.pop()
    print dota
    Result: [1,2]

    Example2:(删除指定位置的元素)
    dota=[1,2,3]
    dota.pop(0)
    print dota
    Result: [2,3]
    Example3:(del通过下标删除序列元素)

    dota=[1,2,3]
    del dota[0]
    print dota
    Result: [2,3]
    Example4:(remove删除指定元素,ps用于移除列表中某个值的第一个匹配项)

    dota=[1,3,4,5,6,4]
    dota.remove(4)
    Result:dota[1,3,5,6,4]
  • 统计列表元素

    1
    2
    3
    4
    5
    Example:(统计列表中元素出现的次数) 
    dota=[1,2,3,4,4,4,4,4]
    num=dota.count(4)
    print num
    Result: 5
  • 查找元素返回其第一次出现的下标

    1
    2
    3
    4
    5
    Example:
    dota = [1,1,2,3,2]
    num=dota.index(2)
    print num
    Result: 2
  • 列表其他技巧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Example1:列表嵌套列表,形成二维数组 
    s = ['python', 'java', ['asp', 'php'], 'scheme']
    s[2][1]
    Result: php

    Example2:列表中数据类型可以混杂
    s = ['python',1True]

    Example3:其他数据类型转换成列表(也可以说是列表的其他写法)
    d=list('abcd')
    print d,type(d)
    Result: ['a', 'b', 'c', 'd'] <type 'list'>

0x02 元组

  • 简介
    元组是不可变数组,因此当定义一个tuple时候它的元素就必须被确定下来,不能改变;list和tuple区别 主要表现在list可以变能给下标赋值修改,而tuple不能;因此tuple不可变代码更安全,如果可能,能用 tuple代替list就尽量用tuple,比如你写了一个API,然后要交给别人来对接,但是你想保证你的代码的安 全以及不想让别人动你的代码,此时tuple就是相对合适的选择。

  • 查找元素返回其第一次出现的下标

    1
    2
    3
    4
    5
    Example:
    dota = (1,1,2,3,2)
    num=dota.index(2)
    print num
    Result: 2
  • 统计元组中元素出现的次数

    1
    2
    3
    4
    5
    Example: 
    dota=(1,2,3,4,4,4,4,4)
    num=dota.count(4)
    print num
    Result: 5
  • 元组其他技巧

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Example1: 其他类型转换成元组
    a=[1,2,3,4]
    b=tuple(a)
    print b
    Result: (1,2,3,4)

    Example2: 区别点
    a= (4) 类型type(a)是int
    a=(4,) 类型type(a)是tuple

0x03 字典

  • 简介
    格式如下:d = {key1 : value1, key2 : value2 } 方法.keys()返回字典所有键的列表,.items()返回字典所有值的列表。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    常用方法: 
    Example1:访问元素
    a={'1':'dota','2':'dota2'}
    a['1']
    Result:‘dota’

    Example2:
    a={'1':'dota','2':'dota2'}
    a[a.keys()[0]]
    Result:dota

    Example3:
    a.items显示所有元素
    for k,v in d.iteritems():迭代列生成
    print k ,v

    Example4:
    dict(zip(‘abc’,range(2)))字典生成
    {k:v for k,v in zip(“abc”,range(3))}生成字典

三、Python文件操作

0x01 读文件

1
2
3
4
5
6
+ 文本模式【r ASCll编码】
with open('password.txt','r') as f: #使用这种方式打开文件,不用考虑close()
print f.read() #一次读取所有内容,返回str(在列知道文件大小下别随便用,万一大于自己内存的大小直接爆)
print f.read(1) #读取第一个字符
print f.readline() #读取每行内容
print f.readlines() #一次读取所有行内容,返回list
1
2
3
4
5
6
7
8
9
+ 二进制模式   【rb 图片,视频等】 
with open('mm.jpg','rb') as fr:
fr.read()
Result:'\xff\xd8\xff\xe1\x00\x18Exif\x00\x00...'
ps:如果读取非ascll编码文件,就必须用二进制模式打开,然后再解码,但是解码会很麻烦,因此可以使用codecs
import codecs
with codecs.open('mm.jpg'.'rb','gbk') as fr:
fr.read()
Result:u'\u6d4b\u8bd5'

0x02 写文件

1
2
with open("password.txt",'w') as fw: 
fw.write('Dota') #注意每次写会覆盖掉前一次。

0x03 其他读写方式

r 只读不可写(默认如果不写就是r)
w 只写(如果用w会把之前内容清空掉)
a 追加(自动添加在文件的末尾)
r+ 可读可写,若文件不存在,报错
w+ 可读可写,若文件不存在,创建

1
2
3
4
5
6
7
8
对文件读写操作优雅写法
try:
with open('password.txt','r') as fr,open('save.txt','w') as fw:
for line in fr:
fw.write(line.lstrip('/'))
fw.flush()
except IOError, e:
pass

1
2
3
4
对文件的读取并且自动去换行优雅写法 
with open('1.txt','r') as fr:
data = [line.strip() for line in fr.readlines()]
print data
1
2
3
4
5
6
7
8
9
减压读取文件优雅写法
with open('1.txt','r') as fr:
for i in fr:
print i

with open('1.txt','r')as fr:
for i in fr.readlines():
print i
#虽然都能读取文件,但是当文件数量大的时候第一种明显不合适。
1
2
3
4
5
同时读取多个文件 
with open(filename1) as fp1, open(filename2) as fp2, open(filename3) as fp3:
for l1 in fp1:
l2 = fp2.readline()
l3 = fp3.readline()

0x04 备注

  • 结尾换行标志(通过os.linesep获取当前系统换行标志) Linux \n Mac \r Windows \r\n
  • 文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件 数量也 是有限的,由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所 以,为了保证无论是否出错都能正确地关闭文件,我们可以使用try … finally来实现,但是这样不够优 美,因此用with…as方式最合适。
  • readline和readlines如果不对每一行空白字符做处理,然后print输出的话,每一行输出的末尾会有两个换行,一个是读取附带的,还一个是print带的,因为print自带一个换行,如果不希望print带换行,则输出的时候末尾加个逗号。
  • fr.name 输出当前文件名 fr.flush() 刷新 fw.truncate() 清空文件