python笔记

前言:

最近整理一些以前的学习笔记,这是学习python时的笔记。
过去都是存储在本地,此次传到网络留待备用。
因为是使用vim随着学随着记,所以基本没有图排版也有些乱。


 

Python

Python起源

  • 贵铎·范·罗萨姆(Guido van Rossum)于1989年底始创了python。

  • 1991年初,python发布了第一个公开发行版。

  • 为了更好的完成荷兰的CWI(国家数学和计算机科学研究院)的一个研究项目而创建。

Python版本

  • Python2.x

    • 目前所有系统默认安装的版本

  • Python3.x

    • 2009年2月13日发布

    • 在语法和功能上有较大调整

    • Python的发展趋势

    • 不兼容以前版本

Python的特点

  • 高级:有高级的数据结构,缩短开发时间与代码量;

  • 面向对象:为数据和逻辑相分离的结构化和过程化编程添加了新的活力;

  • 可升级:提供了基本的开发模块,可以在它上面开发软件,实现代码的重用;

  • 可扩展:通过将其分离为多个文件或模块加以组织管理;

  • 可移植性:python是用c写的,又由于c的可移植性,使得python可以运行在任何带有ANSI C编译器的平台上;

  • 易学:python关键字少、结构简单、语法清晰;

  • 易读:没有其他语言通常用来访问变量、定义代码块和进行模式匹配的命令式符号;

  • 内存管理器:内存管理是由python解释器负责的;

python官网

  • 官网: https://www.python.org/

  • 帮助: https://docs.python.org/zh-cn/3/


 

python安装

1.获取python3源码

  • 官网: http://www.python.org

  • 选择需要的系统版本

2.安装python3

2.1 安装依赖包

]# yum -y install gcc gcc-c++ zlib-devel openssl-devel readline-devel libffi-devel sqlite-devel tcl-devel tk-devel
    #gcc、gcc-c++       //编译器
    #zlib-devel         //压缩开发模块
    #openssl-devel      //加密开发模块
    #readline-devel     //python自动补全开发模块
    #libffi-devel       //动态调用、定义c函数
    #sqlite-devel       //SQLite3可嵌入SQL数据库引擎的开发工具
    #tcl-devel          //tcl脚本语言开发环境
    #tk-devel           //tk图形工具开发文件

2.2 安装python3

]# tar -xf Python-3.7.3.tgz
]# cd Python-3.7.3/
]# ./configure --prefix=/usr/local
]# make && make install

3.设置变量环境

]# Pypath=`which python3`
]# echo $Pypath
/usr/local/bin/python3
]# export PATH="$PATH:$Pypath"              #将python路径写入环境变量

 

4.python工具

4.1pycharm

  • pycharm是由JetBrains打造的一款python IDE,分为 收费专业版 和 免费社区版

  • 支持的功能有:

    • 调试、语法高亮

    • Project管理、代码调转

    • 智能提示、自动完成

    • 单元测试、版本控制

  • 官网: firefox https://www.jetbrains.com/pycharm/download

  • 系统要求:

    • 建议使用64位系统

    • 最低4G内存,建议8G内存

    • 1.5G硬盘空间+最少1G缓存

    • 最低屏幕分辨率1024*768

    • 适用python2.6/2.7,或python3.4~3.7

    • 建议使用KDE、Gnome或unity桌面环境

  • 安装:

    ①下载pycharm

    ]# firefox https://www.jetbrains.com/pycharm/download/previous.html
    或]# wget https://download.jetbrains.com/python/pycharm-professional-2019.1.2.tar.gz
    

    ②解压

    ]# tar -xf pycharm-professional-2019.1.2.tar.gz
    ]# mv pycharm-2019.1.2 /opt/pycharm
    

    ③汉化

    ]# cd /opt/pycharm/lib/
    ]# wget https://github.com/linzhenyuyuchen/Others/blob/master/resources_cn.jar
    

    ④执行使用脚本

    ]# ln -s /opt/pycharm/bin/pycharm.sh /usr/local/bin/pycharm
    ]# pycharm
    

4.2 ipython

  • ipython(interaction python)是一个python的交互式shell

  • 主要组件:

    • 强大的python交互式shell
    • 供Jupyter notebooks使用的一个Jupyter内核(IPython notebook)
  • 功能:

    • 运行ipython控制台
    • 使用ipython作为系统shell
    • 使用历史记录(history)
    • 支持Tab键自动补全,自动缩进
    • 使用%run命令运行脚本
    • 使用%timeit命令快速测量时间
    • 使用%pdb命令快速debug
    • 使用pylab进行交互计算
    • 使用IPython Notebook
    • 内置很多的功能和函数
  • 官网: firefox https://ipython.org/install.html

  • 安装IPython:

    ]# whiereis pip                 #查看pip程序
    ]# pip3 install --upgrade pip   #更新pip
    ]# pip -V                       #确认pip版本
    ]# pip install ipython          #安装ipython
    ]# pip install jupyter          #在notebook或qt console中使用ipython需要
    ]# pip install numpy            #高性能多维数矢量运算库
    ]# pip install matplotlib       #交互式可视化及绘图
    
  • 交互式使用ipython

    ]# ipython
    ]# ipython qtconsole            #ipython图形交互界面
    

 

运行Python

1.交互式解释器

]# python3
>>> print ('hello world')               #输出hello world
>>> quit() 或 exit() 或 [ctrl]+[D]      #退出交互式解释器
>>> python3 -c 'import this'            #python之禅

2.指定使用python3解释程序文件

]# vim hello.py
#!/usr/local/bin/python3               #指定解释器
# -*- coding:utf-8 -*-                 #指定coding,使脚本支持中文
print("hello world")
str="""令脚本支持中文: # -*- coding: UTF-8 -*-  或 # coding=utf-8   """
print(str)

]# chmod +x hello.py
]# python3 hello.py                     #执行python3脚本

3.python3命令行参数

    -d      #在解析时显示调试信息
    -O      #生成优化代码(.pyo文件)
    -S      #启动时不引入查找python3路径的位置
    -V      #输出python3版本号
    -c      #执行python3命令
    file    #使用python3执行file文件

4.获取帮助

  • 交互式

    >>> help()              #进入help帮助文档界面
    help> 查询内容
    
  • 直接查询

    >>> help(查询名)        #查询模块时需要先导入模块 import 模块名
    

 

python语句结构

1.语句块缩进

  • python代码块通过缩进对齐表达代码逻辑而不是使用大括号;
  • 缩进表达一个语句属于哪个代码块;
  • 缩进风格:
    • 1或2:可能不够,很难确定代码语句属于哪个块;
    • 8至10:可能太多,如果代码内嵌的层次太多,就会使得代码很难阅读;
    • 4个空格:非常流行,范·罗萨姆支持的风格;
  • 缩进相同的一组语句构成一个代码块,称之代码组;
  • 首行以关键字开始,以冒号:结束,该行之后的一行或多行代码构成代码组;
  • 若代码组只有一行,可以将其直接写在冒号后面,但可读性差,不推荐; >>> if 10 > 5: print('aaa')

2.注释及续行

2.1 注释

  • 尽管python是可读性最好的语言之一,但并不意味着程序员在代码中就可以不写注释
  • 单行注释: #
    • 与很多UNIX脚本类似,python注释语句以#字符开始
    • 注释可以在一行的任何地方开始,解释器会忽略掉该行#之后的所有内容
  • 多行注释: """ 或 '''
  • 实例:
    ]# vim test.py
    #第一个注释
    '''
    第二个注释
    '''
    """
    第三个注释
    """
    print('hello world')
    
    ]# python3 test.py
    hello world                        #不会输出注释行
    

2.2 续航

  • 续行,一行过长的语句可以使用反斜杠\分解成几行
    >>> str = 'abc' +\
    ...       'qaz' +\
    ...       'zxc'
    >>> str
    'abcqazzxc'
    

3.同行多个语句

  • 分号;允许你将多个语句写在同一行上
  • 但有些语句不能在这行开始一个新的代码块
  • 因为可读性会变差,所以不推荐使用

4.输出语句

  • 获取帮助
    >>> help(命令)
    >>> help(print)
    
  • 使用方式
    >>> print('Hello World!')                       ==>    Hello World!
    >>> print('Hello' + 'World!')                   ==>    HelloWorld!
    >>> print('Hello','World!')                     ==>    Hello World!
    >>> print('Hello','World!',sep='***')           ==>    Hello***World!
    >>> print('Hello','World',sep='***',end='')     ==>    Hello***World>>>
    >>> num = 10
    >>> print('a',num)        ==>    a 10           #字符串连接数值变量不能使用+
    

5.输入语句

  • 获得帮助
    >>> help(input)
    
  • 使用方式(注意,返回值一定是字符类型)
    >>> num = input("Number: ")
    Number: 20
    >>> num + 10
    Traceback (most recent call last):
     File "", line 1, in 
    TypeError: must be str, not int
    
  • 实例: 模拟用户登陆
    ]# vim login.py
    #!/usr/local/bin/python3
    username=input("请输入用户名:")           #输入用户名,并赋值给变量username
    print('Welcome',username)
    print("欢迎" + username)
    
    ]# python3 login.py
    请输入用户名:admin
    欢迎 admin
    欢迎admin
    

 

Python变量

1.定义python变量

  • 变量名约定
    • 第一个字符只能是大小写字母或下划线
    • 后续字符只能是大小写字母或数字或下划线
    • 区分大小写
  • python是动态类型语言,即不需要预先声明变量的类型
  • 推荐采用的全名方法:
    • 变量名全部采用小写字母
    • 简短、有意义
    • 多个单词间用下划线分隔
    • 变量名用名词,函数名用谓词(动词+名词)
    • 类名采用驼峰形式

2.变量赋值

  • 变量的类型和值在赋值那一刻被初始化
  • 变量赋值通过等号来执行
    >>> counter = 0
    >>> name = 'bob'
    
  • python也支持增量赋值
    >>> n += 1
    >>> n *= 1
    >>> i++            #不支持自增、自减
    File "", line 1
      i++
        ^
    SyntaxError: invalid syntax
    

3.运算符

  • 标准算术运算符
    +加、 -减、 *乘、 /除、 //除取整、 %除取余、 **幂运算
    
  • 比较运算符
    < <= > >= == != <>
    
  • 逻辑运算符
    and not or
    
  • 例:
    >>> print(5 / 2)   ==>    2.5              #除
    >>> print(5 // 2)  ==>    2                #除,取整
    >>> print(5 % 2)   ==>    1              #求余,模运算
    >>> print(2 ** 3)  ==>    8                #幂运算
    >>> print(3 == 3)  ==>    True             #判断是否相等,返回True
    >>> print(3 != 3)  ==>    False            #判断是否不相等,返回False
    >>> print(10 < 20 < 30)  ==>    True       #python支持连续比较
    >>> print(True and False)   ==>    False
    >>> print(True and True)    ==>    True
    >>> print(True or False)    ==>    True
    >>> print(not True)         ==>    False
    

 

数据类型概述

1.数字

  • 基本数字类型

    • int:有符号证书
    • bool:布尔值
      • True 1 真
      • False 0 假
    • float:浮点数
    • complex:复数
  • 数字表示方式

    • python默认以十进制数显示
    • 数字以0o或0O开头表示8进制数,八进制=octal
    • 数字以0x或0X开头表示16进制数,十六进制=hex
    • 数字以0b或0B开头表示2进制数,二进制=binary

2.字符串(序列对象)

  • 定义字符串

    • python中字符串被定义为引号之间的字符集合
    • python支持使用成对的单引号或双引号,表示的意义相同
    • python还支持三引号(三个连续的单引号或双引号),可以用来包含特殊字符
    • python不区分字符和字符串,均认定为字符串
  • 字符串切片(字符串截取)

    • 使用 索引运算符[] 和 切片运算符[:]可得到子字符串
    • 第一个字符的索引是0,最后一个字符的索引是-1
    • 子字符串包含切片中的起始下标,但不包含结束下标
      >>> py_str = 'python'    #定义变量
      >>> py_str[0]            #获取第一个下标的子串
       'p'
      >>> py_str[-2]            #获取倒数第二个下标的子串
       'o'
      >>> py_str[2:4]           #获取第三到第四个下标的子串
       'th'
      >>> py_str[2:]            #获取第三个下标到最后的子串
       'thon'
      >>> py_str[:4]            #获取开始到三号下标的子串
       'pyth'
      >>> print(py_str[:])      ==>    python        #获取从开头到结尾
      >>> print(py_str[::2])    ==>    pto           #获取从开头到结尾,步长为2
      >>> print(py_str[::-1])   ==>    nohtyp        #步长为负,从右向左取
      
  • 字符串连接操作

    • 使用+号可以将多个字符串拼接在一起
    • 使用*号可以将一个字符串重复多次
      >>> py_str = 'python'                    #定义变量
      >>> is_cool = 'is Cool'                  #定义变量
      >>> print(py_str + ' ' + is_cool)        #输出,直接引用变量
       python is Cool
      >>> py_str * 2                           #重复2次输出变量
       'pythonpython'
      
  • 定义列表(list)

    • 可以将列表当成普通的"数组",它能保存任意数量任意类型的python对象
    • 像字符串一样,列表也支持下标和切片操作
    • 列表中的项目可以改变
      >>> alist = [1,"tom",2,"alice"]                      #定义列表
      >>> alist[2:]        ==>    [2, 'alice']
      >>> alist            ==>    [1, 'tom', 2, 'alice']
      >>> alist[1] = "bob"                                 #修改列表中下标为1的字符串为bob
      >>> alist[0:2]       ==>    [1, 'bob']
      
  • 列表操作

    • 使用in或not in判断成员关系
    • 使用append方法向列表中追加元素
      >>> alist = [1,'tom',2,'alice']
      >>> 'tom' in alist          ==>    Ture
      >>> 'alice' not in alist    ==>    False
      >>> print(2 in alist)       ==>    Ture
      >>> alist.append('追加')                    #追加元素
      >>> alist[-1]               ==>    '追加'
      >>> len(alist)              ==>    5
      >>> alist[6] = 'bob'                        #不能超出下标已有范围修改元素
       Traceback (most recent call last):
         File "", line 1, in 
       IndexError: list assignment index out of range
      
  • 元组(tuple)的定义及操作

    • 可以认为元组是"静态"的列表
    • 元组一旦定义,不能改变
      >>> atuple = (1,'tom',2,'alice')        #定义元组
      >>> 'tom' in atuple        ==>    Ture
      >>> atuple[3] = 'aa'                    #元组内容不能改变
       Traceback (most recent call last):
         File "", line 1, in 
       TypeError: 'tuple' object does not support item assignment    #'元组'对象不支持项目赋值
      

3.字典

  • 字典的定义及操作

    • 字典是由 键-值(key-value)对 构成的映射数据类型
    • 通过键取值,不支持下标操作
      >>> user_dict = {'name':'bob','age':23}         #定义字典
      >>> user_dict['gender'] = 'male'                #添加键值
      >>> user_dict
       {'name': 'bob', 'age': 23, 'gender': 'male'}
      >>> 'bob' in user_dict        ==>    False       #字典中不能用值查询,
      >>> 'name' in user_dict       ==>    True        #只能按键查询。
      
  • 数据类型比较

    • 按存储模型分类:

      标量类型: 数值、字符串
      容器类型: 列表、元组、字典
      
    • 按更新模型分类:

      可变类型:   列表、字典
      不可变类型: 数字、字符串、元组
      
    • 按访问模型分类:

      直接访问: 数字
      顺序访问: 字符串、列表、元组
      映射访问: 字典
      

 

python判断语句if

1.if语句语法结构

  • 标准if条件语句的语法:

    if expression:        #    if 判断表达式:
        if_suite          #        if执行
    else:                 #    else:
        else_suite        #        else执行
    
  • 如果表达式的值非0或者为布尔值True,则代码组if_suite被执行;否则就执行else_suite;

  • 代码组是一个python术语,它由一条或多条语句组成,表示一个子代码块;

2.if语句示例解析:

  • 只要表达式数字为非0值即为True

    >>> if 10:
    ...   print('Yes')
    Yes
    
  • 空字符串、空列表、空元组、空字典的值均为False

    >>> if "":
    ...     print('Yes')
    ... else:
    ...     print('No')
    ...
    No
    
  • 判断合法用户:

    ]# vim login2.py                                   #编辑py文件
    import getpass                                      #引入getpass模块
    username = input("用户名: ")                         #输入用户名,并赋值给username
    password = getpass.getpass("密码: ")                 #使用getpass模块,密文输入密码并赋值
    if username == 'bob' and password == '123456':      #如果 判断条件:
        print("Login successful")                        #    输出
    else:                                               #否则
        print("Login incorrect")                         #    输出
    
    ]# chmod +x login2.py                             #添加执行权限
    

3.扩展if语句

  • 扩展if语句结构:

    if expression1:            #if 判断1:
        if_suite                 #    if程序
    elif expression2:          #elif 判断2:
        elif_suite               #    elif程序
    else:                      #else:
        else_suite               #    else程序
    
  • 条件表达式:

    • python在很长的一段时间里没有条件表达式(C?X:Y),或称三元运算符, 因为范·罗萨姆一直拒绝加入这样的功能
    • 从python2.5集成的语法确定为: X if 判断 else Y
      >>> x,y = 3,4                              #赋值x=3,y=4
      >>> smaller = x if x < y else y            #若x>> print(smaller)        ==>    3         #输出smaller
      

4.实例:

  • 判断成绩1

    ]# vim grade.py
    #!/usr/local/bin/python3
    score = int(input('请输入分数: '))
    if score >= 90:
        print('优秀')
    elif score >= 80:
        print('好')
    elif score >= 70:
        print('良')
    elif score >= 60:
        print('及格')
    else:
        print('你要努力了')
    
    ]# chmod +x grade.py
    
  • 判断成绩2

    ]# vim grade2.py
    #!/use/local/bin/python3
    score = int(input('输入分数:'))
    if score >= 60 and score <70:
        print('及格')
    elif 70 <= score < 80:
        print('良')
    elif 80 <= score < 90:
        print('好')
    elif score >= 90:
        print('优秀')
    else:
        print('你要努力了')
    
    ]# chmod +x grade2.py
    
  • 石头剪刀布小游戏1

    ]# vim game.py
    #!/usr/local/bin/python3
    import random                                       #引入random随机数模块
    computer = random.choice(['石头', '剪刀', '布'])     #电脑随机出拳,choice=选择
    player = input("请出拳(石头/剪刀/布): ")              #玩家出拳
    
    # print("Your choice:", player, ", Computer's choice:", computer)
    # "%s...%s" % (aaa, bbb)                            #%s格式化输出()中的字符串
    print("Your choice: %s, Computer's choice: %s" % (player, computer))
    if player == '石头':
        if computer == '石头':
            print('平局')
        elif computer == '剪刀':
            print('You WIN!!!')
        else:
            print('You LOSE!!!')
    elif player == '剪刀':
        if computer == '石头':
            print('You LOSE!!!')
        elif computer == '剪刀':
            print('平局')
        else:
            print('You WIN!!!')
    else:
        if computer == 'You WIN!!!石头':
            print('')
        elif computer == '剪刀':
            print('You LOSE!!!')
        else:
            print('平局')
    
    ]# chmod +x game.py
    
  • 石头剪刀布小游戏2(使用列表判断)

    ]# vim game2.py
    #!/usr/local/bin/python3
    #实现三局两胜
    import random
    win_list = [['石头', '剪刀'], ['剪刀', '布'], ['布', '石头']]            #使用胜利列表
    computer = random.choice(['石头', '剪刀', '布'])                        #电脑随机出拳
    player = input("请出拳(石头/剪刀/布): ")                                 #玩家出拳
    print("Your choice: %s, Computer's choice: %s" % (player, computer))
    if player == computer:
        print('\033[33;1m平局\033[0m')                  #黄色输出
    elif [player, computer] in win_list:                        #判断人机列表是否在胜利列表中
        print('\033[32;1mYou WIN!!!\033[0m')           #绿色输出
    else:
        print('\033[31;1mYou LOSE!!!\033[0m')          #红色输出
    
  • 石头剪刀布游戏3

    ]vim game3.py
    #!/usr/local/bin/python3
    import random
    all_choice = ['石头', '剪刀', '布']
    win_list = [['石头', '剪刀'], ['剪刀', '布'], ['布', '石头']]
    prompt = """(0) 石头
    (1) 剪刀
    (2) 布
    Please input your choice(0/1/2): """
    computer = random.choice(all_choice)
    ind = int(input(prompt))
    player = all_choice[ind]
    print("Your choice: %s, Computer's choice: %s" % (player, computer))
    if player == computer:
        print('\033[33;1m平局\033[0m')
    elif [player, computer] in win_list:
        print('\033[32;1mYou WIN!!!\033[0m')
    else:
        print('\033[31;1mYou LOSE!!!\033[0m')
    
  • 石头剪刀布游戏4(字典)

    ]# vim game4.py
    #!/usr/local/bin/python3
    import random
    all_choice = ['石头', '剪刀', '布']
    win_list = [['石头', '剪刀'], ['剪刀', '布'], ['布', '石头']]
    cdict = {'a': '石头', 'b': '剪刀', 'c': '布'}
    prompt = """(a) 石头
    (b) 剪刀
    (c) 布
    Please input your choice(a/b/c): """
    computer = random.choice(all_choice)
    key = input(prompt)
    player = cdict[key]
    print("Your choice: %s, Computer's choice: %s" % (player, computer))
    if player == computer:
        print('\033[33;1m平局\033[0m')
    elif [player, computer] in win_list:
        print('\033[32;1mYou WIN!!!\033[0m')
    else:
        print('\033[31;1mYou LOSE!!!\033[0m')
    

 

python格式化输出

1.打印字符串 %s

>>> print("His name is: %s" %("Aviad"))
His name is: Aviad

2.打印整数 %d

>>> print("He is %d years old" %(25))
He is 25 years old

3.打印浮点数 %f

>>> print("His height is %f m" %(1.83))
His height is 1.830000 m

4.打印浮点数(保留指定小数点位数) %.保留位数f

>>> print("His height is %.2f m"%(1.8321))      #保留2位小数
His height is 1.83 m

5.指定占位符宽度(格式化符号中间加入占位符宽度) %占位符宽度s

>>> print ("Name:%10s Age:%8d Height:%8.2f"%("Aviad",25,1.83))
    # %10s,空10格输出%s;%8d,空8格输出%d;%8.2f,空8格输出%.2f
    Name:     Aviad Age:      25 Height:    1.83           #空格+输出内容 补全占位符宽度

6.指定占位符宽度,左对齐(格式化符号%后加-) %-s

>>> print ("Name:%-10s Age:%-8d Height:%-8.2f"%("Aviad",25,1.83))
Name:Aviad      Age:25       Height:1.83               #输出内容+空格 补全占位符宽度

7.指定占位符,用0占位(在数字型格式化符号%后加0) %0s

>>> print ("Name:%-10s Age:%08d Height:%08.2f"%("Aviad",25,1.83))
Name:Aviad      Age:00000025 Height:00001.83

8.科学计数法

>>> format(0.0015,'.2e')
'1.50e-03'

 

python循环

循环

  • 一组被重复执行的语句称之为循环体,能否继续重复,决定循环的终止条件;
  • python中的循环体有while循环和for循环;
  • 循环次数未知的情况下,建议采用while循环;
  • 循环次数可以预知的情况下,建议采用for循环;

while循环

  • while循环语法结构

    • 当需要语句不断的重复执行时,可以使用while循环
      while 判断:
      while_suite             #suite=程序组
      
    • 语句while_suite会被连续不断的循环执行,直到表达式的值变为0或False
    • 实例:计算1~100之和
      sum100 = 0
      counter = 1
      while counter <= 100:
          sum100 += counter
          counter += 1
      print("result is %d" % sum100)        #%d,格式化输出整数
      
  • while循环语句进阶

    • break语句

      -- break语句可以结束当前循环然后跳转到下条语句;
      -- 写程序的时候,应尽量避免重复的代码,在这种情况下可以使用while-break结构;\
      name = input('输入用户名: ')
      while name != 'tom':
          name = input('输入用户名: ')
      #可以替换为
      while True:
          name = input('输入用户名: ')
      if name == 'tom':
          break
      
    • continue语句

      -- 当遇到continue语句时,程序会终止当前循环,并忽略剩余的语句,然后回到循环的顶端;
      -- 如果仍然满足循环条件,循环体内语句继续执行,否则退出循环;
      -- 实例:计算100内的偶数和
      result = 0
      counter = 0
      while counter < 100:
          counter += 1
          # if counter % 2:           # 非0为真,0为假
          if counter % 2 == 1:
              continue                # 跳过本次循环,循环体内后续代码被跳过,回到判断条件
              result += counter
      print("result is %d" % result)
      
    • else语句

      -- python中的while语句也支持else子句
      -- else子句只在循环完成后执行
      -- break语句也会跳过else块
      sum10 = 0
      i = 1
      while i <= 10:
          sum10 += i
          i += 1
      else:
          print(sum10)
      
  • while循环实例:

    • 猜数字

      ]# vim guess.py
      #!/usr/local/bin/python3
      import random
      num = random.randint(1,100)
      i = 1
      while i <= 5:                              #设置猜的次数
          result = int(input("猜数字:"))
          i += 1
          if result > num:
              print('猜大了')
          elif result < num:
              print('猜小了')
          else:
              print('猜对了')
              break
      else:
          print("正确值:",num)
      
      ]# chmod +x guess.py
      
    • 猜数字2

      import random
      num = random.randint(1, 10)  # 随机生成一个10以内的数字
      running = True
      while running:
          result = int(input("guess the number: "))
          if result > num:
              print('猜大了')
          elif result < num:
              print('猜小了')
          else:
              running = False
              print('猜对了')
      print(num)
      
  • for循环

    • python中的for接受可迭代对象(例如序列或迭代器)作为参数,每次迭代其中一个元素;

      for iter_var in iterable:    #for 引入值 in 值列表:
          suite_to_repeat          #    重复执行程序
      
    • 与while循环一样,支持break、continue、else语句;

    • 一般情况下,循环次数未知采用while循环,循环次数已知,采用for循环

    • 例:

      >>> for word in ['hello','greet','welcom']:
      ...     print(word)
      ...     print('*' * 30)
      hello
      ******************************
      greet
      ******************************
      welcom
      ******************************
      
  • range函数

    • for循环常与range函数一起使用;

    • range函数提供循环条件;

    • range函数的完整语法为: range(start, end, step = 1)

    • range不包含end值

    • 实例:

      -- 数列

      >>> print(range(5))
      range(0, 5)
      >>> print(list(range(5)))
      [0, 1, 2, 3, 4]
      >>> for i in range(5):
      ...     print(i) 
      0
      1
      2
      3
      4
      >>> print(list(range(11,21)))
      [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
      >>> print(list(range(1,11,2)))          #10以内的奇数
      [1, 3, 5, 7, 9]
      >>> print(list(range(10,0,-1)))
      [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
      

      -- 斐波那契数列1

      ]# vim fibonacci1.py                        #斐波那契数列,某数总等于前两数之和
      #!/usr/local/bin/python3
      n = int(input('输入长度:'))                 #输入整数,需要生成的长度
      lis = []                                   #空列表,用于存数列
      for i in range(n):                         #设置生成范围
          if i == 0 or i == 1:
              lis.append(i)
          else:
              lis.append(lis[i-2]+lis[i-1])      #第三位开始,数=前两位数之和
      print(lis)
      ]# chmod +X fibonacci1.py
      

      -- 斐波那契数列2

      a, b = 1, 1
      for i in range(10):
          print(a)
          a, b = b, a + b
      

      -- 斐波那契数列3

      def gen_fib(l):                      #定义函数
          fib = [0, 1]                        #初始列表
          for i in range(l - 2):              #前两位是 0,1
              fib.append(fib[-1] + fib[-2])       #追加 倒数第一位 + 倒数第二位
          return fib                          #返回值,而不打印,不返回变量名[0, 1, 1, 2, 3]
      length = int(input("数列长度: "))     # 输入10
      a = gen_fib(length)                  #调用函数时,将参数传入
      print(a)
      with open('/tmp/fib.txt', 'w') as fobj:     #写入文件
          fobj.write(str(a))
      

      -- 九九乘法表

      ]# vim mtable.py
      #!/usr/local/bin/python3
      n = int(input('输出多少内的乘法表:'))
      def gen_mtable(n):
          for i in range(1, n+1):
              for j in range(1, i+1):
                  print('%s*%s=%-2s' % (i, j, i*j), end=' ')
                  #end=' ',输出空符,不用换行符
              print()
      gen_mtable(n)
      ]# chmod +x mtable.py
      
  • 列表解析

    • 语法: [expr for iter_var in iterable]

      [表达式 for 引入值 in 值列表]
      
    • 它是一个非常有用、简单、而且灵活的工具,可以用来动态地创建列表;

    • 这个语句的核心是for循环,它迭代iterable对象的所有条目;

    • expr应用于序列的每个成员,最后的结果值是该表达式产生的列表

      >>> L = [ i**2 for i in range(1,11)]        # 1~10的平方
      >>> print(L)
      [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
      

 

python文件对象(文件操作)

  • 文件操作的三个步骤: 打开 、 读写 、 关闭

1.文件打开方法

  • open及file内建函数

    • 作为打开文件之门的钥匙,内建函数open()及file()提供了初始化输入/输出(I/O)操作的通用接口;
    • 成功打开文件后会返回一个文件对象,否则引发一个错误;
    • open()方法和file()方法可以完全相互替换
    • 基本语法:
      >>> file_object = open(file_name [,access_mode='r'][,buffering=-1])
      >>> 目标文件 = open(文件名称, 访问模式, 缓冲)             #默认以读的方式打开
      >>> file_object.close()                                #关闭打开的文件
      
    • 测试:
      ]# echo -e "a\nb\nc\nd\ne\n" > test.txt
      ]# python3
      >>> f = open('test.txt')
      >>> f.close()
      
  • 文件对象访问模式

        文件模式      操作
        r            以读方式打开(文件不存在则报错)
        w            以写方式打开(文件存在则清空,不存在则创建)
        a            以追加模式打开(必要时创建新文件)
        r+           以读写模式打开(参见r)
        w+           以读写模式打开(参见w)
        a+           以读写模式打开(参见a)
        b            以二进制模式打开
    

2.文件输入

  • read方法

    • read()方法用来直接读取字节到字符串中,最多读取给定数目个字节
    • 若没有给定size参数(默认值为-1)或者size值为负,文件将被读取直至末尾
      >>> data = fobj.read()        #fobj,open后的目标文件
      >>> print(data)
      
    • 测试:
      >>> f = open('test.txt')
      >>> str = f.read() 
      >>> print(str)
      a
      b
      c
      d
      e
      
  • readline方法

    • 读取打开文件的一行(读取下个行结束符之前的所有字节)
    • 然后整行,包括行结束符,作为字符串返回
    • 它也有一个可选的size参数,默认为-1,代表读至行结束符
    • 如果提供了该参数,那么在超过size个字节后会返回不完整的行
      >>> data = fobj.readline()
      >>> print(data)
      
    • 测试:
      >>> f = open('test.txt')
      >>> str = f.readline()
      >>> print(str)
       a
      >>> str = f.readline()
      >>> print(str)
       b
      
  • readlines方法

    • readlines()方法读取所有(剩余的)行,然后把它们作为一个字符串列表返回
      >>> data = fobj.readlines()
      >>> print(data)
      
    • 测试:
      >>> str = f.readlines()
      >>> print(str)
       ['c\n', 'd\n', 'e\n']
      
  • 文件迭代

    • 如果需要逐行处理文件,可以结合for循环迭代文件
    • 迭代文件的方法与处理其它序列类型的数据类似
      >>> fobj = open('文件名')
      >>> for eachLine in fobj:
      ...     print(eachLine, end='')
      
    • 测试:
      >>> f = open('test.txt')
      >>> for i in f:
      ...     print(i, end='')
      a
      b
      c
      d
      e
      

3.文件输出

  • write方法

    • write()内建方法功能与read()和readline()相反。它把含有文本数据或二进制数据块的字符串写入到文件中;
    • 写入文件时,不会自动添加行结束标志,需要程序员手工输入;
      >>> f = open('test.txt','a')    #追加模式打开
      >>> f.write('abc\n')
       4                              #写入的字符串长度
      >>> f.flush()                   #立即将缓存中的数据写入到磁盘,非必须
      >>> f.open('test.txt')
      >>> f.read()
      
  • writelines方法

    • 和readlines()一样,writelines()方法是针对列表的操作;
    • 它接受一个字符串列表作为参数,将它们写入文件;
    • 行结束符并不会被自动加入,所以如果需要的话,必须在调用writelines()前给每行结尾加上结束符
      >>> fobj.writelines(['Hello World!\n', 'python programing\n'])
      
    • 测试:
      >>> f = open('test.txt','w')
      >>> f.writelines(['aaa\n','bbb\n'])
      >>> f = open('test.txt')
      >>> f.read()
       'aaa\nbbb\n'
      

4.操作文件

  • with子句

    • with语句是用来简化代码的;
    • 在将打开文件的操作放在with语句中,代码块结束后,文件将自动关闭
      >>> with open('test.txt') as f:
      ...     data = f.readlines()
      >>> f.closed
       True
      >>> print(data)
       ['aaa\n', 'bbb\n']
      
  • 文件内移动

    • fobj.seek(offset [,whence]) :移动文件指针到不同的位置
      offset:开始的偏移量,也就是代表需要移动偏移的字节数
      whence的值,0表示从文件开头开始(默认),1表示当前位置开始,2表示文件的结尾开始
      
    • tell() :返回当前文件指针的位置
    • 实例:
      >>> f = open('test.txt','r+')           #打开文件
      >>> f.name        ==>    'test.txt'     #显示文件名
      >>> f.readline()  ==>    'a\n'          #读取一行
      >>> f.tell()      ==>    2              #返回当前文件指针位置,前边读取了a\n个字符
      >>> f.seek(0,0)   ==>    0              #重置指针位置,到开头
      >>> f.tell()      ==>    0              #返回当前文件指针位置
      >>> f.close()                           #关闭文件
      
  • 标准文件

    • 程序一执行,就可以访问三个标准文件
      标准输入:一般是键盘,使用sys.stdin
      标准输出:一般是显示器缓冲输出,使用sys.stdout
      标准错误:一般是显示器的非缓冲输出,使用sys.stderr
      
      >>> import sys
      >>> sys.stdout.write('hello world!\n')
      hello world!
      13
      >>> hi = sys.stdin.readline()
      hello    #输入值
      >>> hi
      'hello\n'
      
  • 实例:模拟cp操作

    ]# vim cp.py                            #实现cp /usr/bin/ls /tmp/ls
    import sys
    def copy(src_fname, dst_fname):        #定义函数
        src_fobj = open(src_fname, 'rb')       #源文件
        dst_fobj = open(dst_fname, 'wb')       #目标文件
        while True:                            #循环
            data = src_fobj.read(4096)             #每次读4096字节
            if not data:                           #读不到数据意味着读写完毕,中断循环
                break                                  #结束
            dst_fobj.write(data)                   #将数据写到目标文件
        src_fobj.close()                       #关闭
        dst_fobj.close()
    copy(sys.argv[1],sys.argv[2])
    print('    \033[32m[done]\033[0m    copy %s to %s' %(sys.argv[1],sys.argv[2]))
    
    ]# chmod +x cp.py
    ]# python3 cp.py /usr/bin/ls /tmp/list
    

 

python函数

  • 函数是对程序逻辑进行结构化或过程化的一种编程方法
  • 将整块代码巧妙地隔离成易于管理的小块
  • 把重复代码放到函数中而不是进行大量的拷贝,这样既能节省空间,也有助于保持一致性
  • 通常函数都是用于实现某一种功能

函数基本操作

1.创建函数

  • 函数是用def语句来创建的,语法如下:
    def function_name(arguments):            #def 函数名(参数):
        "function_documentation_string"          #"函数文档字串"
        function_body_suite                      #函数体
        return [表达式]                           #
    
  • 标题行由def关键字,函数名,及参数的集合(有的话)组成
  • def子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必须的函数体

2.调用函数

  • 同大多数语言相同,python用一对圆括号调用函数;
  • 如果没有加圆括号,只是对函数的引用;
    >>> def foo():                #定义函数
    ...     print('hello')            #函数体
    >>> foo()                     #调用函数
    hello
    

3.函数的返回值

  • 多数情况下,函数并不直接输出数据,而是向调用者返回值
  • 函数的返回值使用return关键字
  • 没有return的话,函数默认返回None
    >>> def foo():            # >>> def foo():            #定义函数
    ...     res = 3 + 4       # ...     res = 3 + 4           #函数体
    ...                       # ...     return res            #返回值
    >>> i = foo()             # >>> i = foo()             #调用函数赋值
    >>> print(i)              # >>> print(i)    ==>    7  #输出
    None                      #  7
    

 

函数参数

1.定义参数

  • 形式参数:
    • 函数定义时,紧跟在函数名后(圆括号内)的参数被称为 形式参数,简称 形参;
    • 由于它不是实际存在变量,所以又称为虚拟变量;
  • 实际参数:
    • 在主调函数中调用一个函数时,函数名后面括号中的参数(可以是一个表达式),称为 实际参数,简称 实参

2.传递参数

  • 调用函数时,实参的个数需要与形参个数一致
  • 实参将依次传递给形参
    >>> def foo(x,y):
    ...     print('x=%d,y=%d' % (x,y))
    >>> foo()
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: foo() missing 2 required positional arguments: 'x' and 'y'    #缺少参数
    >>> foo(3)
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: foo() missing 1 required positional argument: 'y'            #缺少参数
    >>> foo(3,4)
    x=3,y=4
    

3.位置参数

  • 与shell脚本类似,程序名以及参数都以位置参数的方式传递给python程序
  • 使用sys模块的argv列表接收
  • argv是sys模块中的列表,用于保存命令行上的参数
    ]# vim args.py
    #!/usr/bin/env python3
    import sys
    print(sys.argv)                #输出全部参数
    print(sys.argv[2])             #输出第二个参数
    ]# ./test.py hello world
    ['./test.py', 'hello', 'world']
    world
    

4.默认参数

  • 默认参数就是声明了默认值的参数
  • 因为给参数赋予了默认值,所以在函数调用时,不向该参数传入值也是允许的
    >>> def pstar(num = 30):
    ...     print('*' * num)
    >>> pstar()
    ******************************
    >>> pstar(40)
    ****************************************
    

 

模块基础

  • 模块是从逻辑上组织python代码的形式;
  • 当代码量变得相当大的时候,最好把代码分成一些有组织的代码段,前提是保证它们的彼此交互;
  • 这些代码片段相互间有一定的联系,可能是一个包含数据成员和方法的类,也可能是一组相关但彼此独立的操作函数;

1.查看帮助

  • 交互式help文档界面

    >>> help()
    help> 对象名                         #输入需要查询的对象名
    help> modules                       #查看所有可用(已安装)模块
    help> sys                           #模块名
    #输出对象帮助信息
    help> q                             #退出
    
  • 直接输出帮助信息

    >>> help(对象名)
    >>> help(print) ==> 输出print帮助    #查看print帮助信息
    >>> import sys                      #直接查看模块帮助时,先要导入模块
    >>> help(sys)                       #查看sys模块帮助信息
    

2.定义模块

  • 创建模块

    • 模块物理层面上组织模块的方法是文件,每一个以.py作结尾的python文件都是一个模块;

    • 模块名称切记不要与系统中已存在的模块重名;

    • 模块文件名字去掉后面的扩展名(.py),即为模块名;

3.使用模块

  • 导入模块(import)

    • 使用import导入模块
    • 模块被导入后,程序会自动生成pyc的字节码文件以提升性能
    • 模块属性通过"模块名.属性"的方法调用
    • 如果仅需模块中的某些属性,也可以单独导入
      >>> import 模块名                    #导入模块
      >>> import os,string
      >>> string.digits                   #使用整个导入的模块时,需要写 模块名.属性
       '0123456789'
      >>> import 模块名 as 属性名           #导入模块的某个属性
      >>> import os as path
      >>> from 模块名 import 属性名         #导入模块的某个属性
      >>> 属性名                           #使用单独导入的模块属性时,可以直接写属性名
      >>> from random import randint
      >>> randint(1,10)                   #生成随机整数
       9
      
  • 模块加载(load)

    • 一个模块只被加载一次,无论它被导入多少次
    • 只加载一次可以阻止多重导入时代码被多次执行
    • 如果两个文件相互导入,防止了无限的相互加载
    • 模块加载时,顶层代码会自动执行,所以只将函数放入模块的顶层是良好的变成习惯
  • 模块导入的特性

    • 模块具有一个_name_特殊属性
    • 当模块文件直接执行时,__name__的值为'main'
    • 当模块被另一个文件导入时,__name__的值就是该模块的名字
      ]# vim foo.py
       #!/usr/bin/env python3
       print(__name__)
      ]# ./foo.py
       __main__
      ]# python3
      >>> import foo
       foo
      
  • 实例:

    • 生成随机密码

      ]# vim randpass.py                    #生成8位随机密码
      #!/usr/local/bin/python3
      import random
      all_chs = '0123456789qazxswedcvfrtgbnhyujmkiolpQAZXSWEDCVFRTGBNHYUJMKIOLP'
      result = ''
      for i in range(8):
          ch = random.choice(all_chs)      #使用random的choice函数随机取值
          result += ch
      print(result)
      

 

python中shell相关模块

shutil模块

  • shell utility #shell实用工具

复制和移动

  • shutil.copy(src,dst,*,follow_symlinks=True)

    • 将文件src复制到文件或目录dst。src和dst应为字符串。

    • 如果dst指定目录,则文件将使用src的基本文件名复制到dst中。

    • 返回新创建的文件的路径。

  • shutil.copy2(src,dst,*,follow_symlinks=True)

    • 与copy()相同,但copy2()也尝试保留所有文件元数据。

  • shutil.copyfile(src,dst,*,follow_symlinks=True)

    • 将名为src的文件的内容(无元数据)复制到名为dst的文件,然后返回dst。

  • shutil.copyfileobj(fsrc,fdst [,length])

    • 将类似文件的对象fsrc的内容复制到类似文件的对象fdst。

  • shutil.move(src,dst,copy_function=copy2)

    • 递归地将文件或目录(src)移动到另一个位置(dst),并返回目标。

目标操作

  • shutil.copytree(src,dst,symlinks=False,ignore=None,copy_function=copy2,ignore_dangling_symlinks=False)

    • 递归地复制以src为根的整个目录树,返回目标目录。由dst命名的目标目录不能已经存在。

  • shutil.rmtree(path,ignore_errors=False,οnerrοr=None)

    • 删除整个目录树;路径必须指向目录(而不是指向目录的符号链接)。

权限管理

  • shutil.copymode(src,dst,*,follow_symlinks=True)

    • 将权限位从src复制到dst。文件内容,所有者和组不受影响。

    • src和dst是以字符串形式给出的路径名称。

  • shutil.copystat(src,dst,*,follow_symlinks=True)

    • 将权限位,最后访问时间,上次修改时间和标志从src复制到dst。

  • shutil.chown(path,user=None,group=None)

    • 更改给定路径的所有者用户和/或组


 

语法风格

变量赋值

  • python支持链式多重赋值

    >>> x = y = 10
    
  • 多元赋值:将多个变量同时赋值的方法,采用这种方式赋值时,等号两边的对象都是元组

    >>> a,b = 10,20
    

合法标识符

  • python标识符字符串规则和其它大部分用C编写的高级语言相似

  • 第一个字符必须是字母或下划线(_)

  • 剩下的字符可以是字母和数字或下划线

  • 大小写敏感

关键字

  • 和其它的高级语言一样,python也拥有一些被称作关键字的保留字符;

  • 任何语言的关键字应该保持相对的稳定,但是因为python是一门不断成长和进化的语言,其关键字偶尔会更新;

  • 关键字列表和iskeyword()函数都放入了keyword模块以便查阅;

    >>> import keyword
    >>> print(keyword.kwlist)           #查看关键字
    

内建

  • 除了关键字之外,python还有可以在任何一级代码使用的"内建"的名字集合,这些名字可以由解释器设置或使用

  • 虽然built-in不是关键字,但是应该把它当作"系统保留字"

  • 保留的常量,如:True、False、None

模块结构及布局

  • 编写程序时,应该建立一种统一且容易阅读的结构,并将它应用到每一个文件中去。

    #!/usr/bin/env python3            #起始行,声明环境变量
    "this is a test module"           #模块文档字符串,模块说明
    import sys,os                     #导入模块
    debug = True                      #全局变量声明
    class FooClass(object):           #类定义
        'Foo class'
        pass
    def test():                       #函数定义
        "test function"
        foo = FooClass()
    if __name__ == '__main__':        #程序主体
        test()
    

 

python字符串详解

序列

序列类型操作符          //作用                           | #示例 >>> a,b = 'python','nice'
    seq[ind]          //获得下标位ind的元素              |       >>> a[2]    ==> 't'
    seq[ind1:ind2]    //获得下标从ind1到ind2间的元素集合  |       >>> a[1:3]  ==> 'yt'
    seq * expr        //序列重复expr次                  |       >>> a * 2   ==> 'pythonpython'
    seq1 + seq2       //连接序列seq1和seq2              |       >>> a + b   ==> 'pythonnice'
    obj in seq        //判断obj元素是否包含在seq中       |       >>> 'py' in a   ==> True
    obj not in seq    //判断obj元素是否不包含在seq中     |       >>> 'py' not in a   ==> False

内建函数

  • list(iter)

    • 把可迭代对象转换为列表

  • str(obj)

    • 把obj对象转换成字符串

  • tuple(iter)

    • 把一个可迭代对象转换成一个元组对象

      >>> list('hello')
       ['h', 'e', 'l', 'l', 'o']
      >>> list(('hello','world'))
       ['hello', 'world']
      >>> str(['hello','world'])
       "['hello', 'world']"
      
  • len(seq)

    • 长度,返回seq的长度

  • max(iter,key=None)

    • 最大,返回iter中的最大值

  • enumerate

    • 枚举,接受一个可迭代对象作为参数(如列表、字符串等),返回索引值和对应的元素值

      >>> a='python'
      >>> len(a)
       6
      >>> max(a)
       'y'
      >>> alist = ['hello','world']
      >>> for i,j in enumerate(alist):
      ...     print('index %d: %s' % (i,j))
       index 0: hello
       index 1: world
      
  • reversed(seq)

    • 相反的,接受一个序列作为参数,返回一个以逆序访问的迭代器

  • sorted(iter)

    • 排序,接受一个可迭代对象最为参数,返回一个有序的列表

      >>> a='python'
      >>> reversed(a) ==> 
      >>> sorted(a)   ==> ['h', 'n', 'o', 'p', 't', 'y']
      

字符串

字符串操作符

  • 比较操作符: 字符串大小按ASCII码值大小进行比较

  • 切片操作符: []、[:]、[::]

  • 成员关系操作符: in、not in

    >>> py_str = 'Hello World!'
    >>> py_str[::2]     ==> 'HloWrd'        #步长2,每2个字符输出(隔1个输出1个)
    >>> py_str[::-1]    ==> '!dlroW olleH'  #步长-1,反向输出
    
  • 案例:检查标识符

    ]# vim check_str.py
    #!/usr/bin/env python3
    ''' 1.程序接受用户输入
        2.判断用户输入的标识符是否合法
        3.用户输入的标识符不能使用关键字
        4.有不合法字符,需要指明第几个字符不合法'''
    import keyword                          #导入模块
    str = input('请输入标示符:')             #输入字符串
    if keyword.iskeyword(str):              #判断是不是关键字
        print('%s 是关键字' %(str))
    else:
        print('%s 不是关键字' %(str))
    print(keyword.iskeyword(str))           #True | False
    print(str in keyword.kwlist)            #True | False
    

格式化操作符

  • 字符串可以使用格式化符号来表示特定含义

      格式化字符         //转换方式
      %c                //转换成字符
      %s                //优先用str()函数进行字符串转换
      %d / %i           //转成有符号十进制数,只能输出int类整数
      %o                //转成无符号八进制数
      %e / %E           //转成科学计数法
      %f / %F           //转成浮点数
    
  • 字符串可以使用格式化符号来表示特定含义

      辅助指令      //作用
      *            //定义宽度或者小数点精度
      -            //左对齐
      ^            //居中
      +            //在正数前面显示加号
               //在正数前面显示空格
      #            //在八进制数前面显示0,在十六进制前面显示0x或者0X
      0            //显示的数字前面填充0,而不是默认的空格
    

format函数

  • 使用位置参数 {} ,依次赋予值

    '{} {} ...'.format(参数1,参数2,...)
    'my name is {} , age {}'.format('hoho',18)
    
  • 使用关键字参数 {关键字} ,按关键字赋值

    '{关键字1} {关键字2} ...'.format({关键字1:参数1,关键字2:参数2,...})
    'my name is {name},age is {age}'.format({'name':'bob','age':23})
    
  • 填充与格式化

    {[位置参数|关键字参数]:[填充字符][对齐方式][限制宽度]}
    
  • 使用索引

    '{列表号[下标]} {列表号[下标]}'.format([列表1],[列表2],...)
    'name is {0[0]} sex is {1[1]}'.format(['bob','jack'],['girl','boy'])
    
  • 案例:创建用户

    ]# vim add_user.py
    #!/usr/bin/env python3
    '''
    1.编写一个程序,实现创建用户的功能
    2.提示用户输入用户名
    3.随机生成8位密码
    4.创建用户并设置密码
    5.将用户相关信息写入指定文件'''
    import sys,string,subprocess
    from random import choice
    def gen_pass(n=8):
        '''生成密码'''
        all_chs = string.ascii_letters + string.digits                  #生成字母a-Z数字0-9
        pwd = ''
        for i in range(n):
            pwd += choice(all_chs)                                      #创建随机密码
        return pwd
    def add_user(username,password,fname):
        """添加用户"""
        if subprocess.call('id %s &>/dev/null' %username, shell=True):  #测试用户是否存在
            info = '''user information:
            username: %s
            password: %s \n\n\n'''
            subprocess.call('useradd %s >/dev/null' %username , shell=True)
            subprocess.call('echo %s | passwd --stdin %s >/dev/null' %(password,username), shell=True)
            with open(fname,'a') as fobj:
                fobj.write(info %(username,password))
            print('用户 %s 已创建,信息存储在 %s' %(username,fname))
        else:
            print('用户 %s 已存在' %username)
    if __name__ == '__main__':                          #此脚本直接运行的时候才执行下面命令
        username = sys.argv[1]
        password = gen_pass()
        fname = '/tmp/users.txt'
        add_user(username,password,fname)
    

原始字符串操作符 r'str'

  • 原始字符串操作符是为了对付那些在字符串中出现的特殊字符

  • 在原始字符串里,所有的字符都是直接按照字面的意思来使用,没有转义特殊或不能打印的字符

    >>> winPath = 'c:\windows\temp'
    >>> print(winPath)
     c:\windows    emp                          #\t被转义成tab
    >>> newPath = r'c:\windows\temp'            #在字符串前加r,使字符串不被转义
    >>> print(newPath)
     c:\windows\temp                            #正常输出
    
  • 案例:格式化输出

    #!/usr/bin/env python3
    '''
        1.提示用户输入(多行)数据
        2.假定屏幕的宽度位50,用户输入的多行数据如下显示(文本内容居中):
            +************************************************+
            +                   hello world                  +
            +                   great work!                  +
            +************************************************+
    '''
    
    #!/usr/bin/env python3
    
    #import subprocess
    import os
    
    #width=50                                               #设置宽度
    #width=subprocess.getoutput('echo $COLUMNS')            #获取终端宽度,转换int报错
    #width=int(width)
    #width=subprocess.getstatusoutput('echo $COLUMNS')      #获取中段宽度,转换int报错
    #width=int(width[1])
    width=os.popen('stty size', 'r').read().split()         #获取终端高度、宽度,可行
    width=int(width[1])                                     #获取宽度,并转为int
    
    #多行输入
    end = 'EOF'                               #结束符
    #lines = ['*'*48]
    lines = ['*'*(width-2)]                   #首尾行格式,保存2位首尾字节
    print("请输入多行数据(输入EOF结束):")
    for line in iter(input,end):              #利用iter迭代生成列表
        lines.append(line)                      #读取多行信息写入列表
    lines.append(lines[0])                    #尾行格式
    
    #输出信息
    print("\n输出:")
    for i in range(len(lines)):                     #循环读取列表索引
        #lines[i] = '{0:^48s}'.format(lines[i])
        lines[i] = lines[i].center(width-2,' ')     #空格填充字符串
        #print('{0:+^50s}'.format(lines[i]))
        print(lines[i].center(width,'+'))           #填充行的首尾符,输出格式信息
    

内建函数

  • string.capitalize()

    把字符串的第一个字符大写

    >>> 'python'.capitalize()   ==> 'Python'
    
  • string.lower()

    返回源序列的副本,其所有大写ascll字符转换为小写

  • string.upper()

    转换string中的小写字母为大写

    >>> 'python'.upper()    ==> 'PYTHON'
    
  • string.islower()

    如果string中包含至少一个区分大小写的字符,且所有这些字符都是小写,则返回True,否则返回False;

    >>> str='python'; str.islower() ==> True
    >>> str='pyThon'; str.islower() ==> False       #有大写字母
    
     
  • string.center(width[,fillchar])

    返回一个原字符串居中,并使用空格填充至长度width的新字符串

    使用指定的fillchar填充两边的空位,默认使用ascii空格符

    >>> 'python'.center(10)     ==> '  python  '
    >>> 'python'.center(10,'+') ==> '++python++'
    
  • string.ljust(width[,fillchar])

    返回长度是width的字符串,源字符串靠左对齐,使用fillchar填充空位

    >>> str.ljust(10,'#')   ==> 'python####'
    
  • string.rjust(width[,fillchar])

    返回长度为width的字符串,源字符串右对齐,使用fillchar填充空位

    >>> str.rjust(20,'#')   ==> '##############python'
    
     
  • string.count(str,[start[,end]])

    返回str在string里面出现的次数,如果beg或end指定则返回指定范围内str出现的次数。

    >>> 'i like python'.count('i')  ==> 2
    >>> string,str = 'abbccc','c'
    >>> string.count(str , 4 , len(string)) ==> 2
    
     
  • string.endswith(suffix[,start[,end]])

    若string字符串以指定的suffix结束则返回True,否则返回False

    suffix也可以是由多个供查找的后缀构成的元组

    可选项start,从所指定位置开始检查;可选项end,将在所指定位置停止比较

    >>> str,suffix = 'python','on'
    >>> str.endswith(suffix)        ==> True
    >>> suffix=('th','on')
    >>> str.endswith(suffix)        ==> True
    >>> str.endswith(suffix,2,4)    ==> True
    >>> str.endswith(suffix,2,3)    ==> False
    
     
  • string.strip([chars]) #strip=剥离

    删除string字符串两端的空白

    参数chars是要删除的字符串中字符的所有组合

    >>> '   spacious   '.strip()            ==> 'spacious'
    >>> 'www.example.com'.strip('cmowz.')   ==> 'example'
    
     
  • string.split([sep[,maxsplit=-1]])

    以sep为分隔符切片string,maxsplit指定分隔子字符串的数量(默认-1,不限制分割数量)

    >>> '1,2,3,4,5'.split(',')      ==> ['1', '2', '3', '4', '5']
    >>> '1,2,3,4,5'.split(',',2)    ==> ['1', '2', '3,4,5']
    

 

python的列表和元组

1.列表

1.1 创建及访问列表

  • 列表是有序、可变的数据类型
  • 列表中可以包含不同类型的对象
  • 列表可以由[]或工厂函数创建
  • 支持下标及切片操作

1.2 更新列表

  • 通过下标只能更新值,不能使用下标添加新值
    >>> alist = [10,35,20,80]
    >>> alist[-1] = 100
    >>> alist[1:3] = [30,50,80]
    >>> alist   ==> [10, 30, 50, 80, 100]
    

1.3 列表内建函数

    列表方法                 //操作
    list.append(obj)        //向列表中添加一个对象obj
    list.count(obj)         //返回一个对象obj在列表中出现的次数
    list.extend(seq)        //把序列seq的内容添加到列表中
    list.index(obj)         //返回obj对象的下标
    list.insert(index,obj)  //在索引量为index的位置插入对象obj
    list.reverse()          //原地翻转列表
    list.sort()             //排序,不支持数字、字符串混排
>>> list=[]
>>> list.append('a'); list                  ==> ['a']
>>> list.count('a')                         ==> 1
>>> list.extend(range(3)); list             ==> ['a', 0, 1, 2]
>>> list.index(1)                           ==> 2
>>> list.insert(2,'qq'); list               ==> ['a', 0, 'qq', 1, 2]
>>> list.reverse(); list                    ==> [2, 1, 'qq', 0, 'a']
>>> list=[2,1,3,5,4]; list.sort(); list     ==> [1, 2, 3, 4, 5]
>>> list=['b','c','a']; list.sort(); list   ==> ['a', 'b', 'c']

2.元组

2.1 创建元组

  • 通过()或工厂函数tuple()创建元组
  • 元组是有序的、不可变类型
  • 与列表类似,作用于列表的操作,绝大数也可以作用于元组

2.2 单元素元组

  • 如果一个元组中只有一个元素,那么创建该元组的时候,需要加上一个逗号
    >>> atuple = ('hello')
    >>> print(atuple)
    hello
    >>> type(atuple)            #没有,号的话,atuple作为字符串存储
    
    >>> atuple = ('hello',)
    >>> print(atuple)
    ('hello',)
    >>> type(atuple)            #加上,的话,atuple才作为元组存储
    
    

2.3 "更新"元组

  • 虽然元组本身是不可变的,但是因为它同时属于容器类型,
  • 也就意味着若元组的某一个元素是可变的容器类型,
  • 那么这个元素中的项目仍然可变。
    >>> atuple = ('bob',['boy',23])        #创建元组,包含一个列表
    >>> print(atuple)
    ('bob', ['boy', 23])
    >>> atuple[-1] = ['boy',22]            #直接修改失败
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: 'tuple' object does not support item assignment
    >>> atuple[-1][-1] = 22                #指定元组中的列表下标,指定列表中的下标修改
    >>> atuple
    ('bob', ['boy', 22])
    >>> atuple[-1].append(175)             #指定元组中的列表下标,追加元素
    >>> atuple
    ('bob', ['boy', 22, 175])              #追加成功
    

 

字典和集合

1.字典基础操作

1.1 创建字典

  • 通过{}操作符创建字典

    >>> 字典名={键1:值1,键2:值2,...}
    >>> adict = {'name':'bob','age':23}
    >>> adict   ==> {'name': 'bob', 'age': 23}
    
  • 通过dict()工厂方法创建字典

    >>> bdict = dict((['name','bob'],['age',23]))
    >>> print(bdict)    ==> {'name': 'bob', 'age': 23}
    
  • 通过fromkeys()创建具有相同值的默认字典

    >>> cdict = {}.fromkeys(('bob','alice'),23)
    >>> print(cdict)    ==> {'bob': 23, 'alice': 23}
    

1.2 访问字典

  • 字典是映射类型,意味着它没有下标,访问字典中的值需要使用相应的键

    >>> for each_key in adict:                                      #读取键
    ...     print('key=%s,value=%s' % (each_key,adict[each_key]))   #输出键,及对应的值
    key=name,value=bob
    key=age,value=23
    >>> print('%(name)s' % adict)       #输出adict中name键的值
    bob
    

1.3 更新字典

  • 通过键更新字典

    • 如果字典中有该键,则更新相关值

    • 如果字典中没有该键,则向字典中添加新值

      >>> print(adict)
       {'name': 'bob', 'age': 23}
      >>> adict['age'] = 22
      >>> print(adict)
       {'name': 'bob', 'age': 22}
      >>> adict['email'] = '[email protected]'
      >>> print(adict)
       {'name': 'bob', 'age': 22, 'email': '[email protected]'}
      

1.4 删除字典

  • 通过del可以删除字典中的元素或整个字典

    >>> del adict['email']
    >>> print(adict)
    {'name': 'bob', 'age': 22}
    
  • 使用pop()方法可以"弹出(删除)"字典中的元素

    >>> adict.pop('age')
    22
    >>> print(adict)
    {'name': 'bob'}
    
  • 使用内部方法clear()可以清空字典

    >>> adict.clear()
    >>> print(adict)
    {}
    

1.5 字典操作符

  • 使用字典键查找操作符[],查找键所对应的值

  • 使用in和not in判断键是否存在于字典中

    >>> adict = {'age':23,'name':'bob'}        #定义字典
    >>> adict
    {'age': 23, 'name': 'bob'}
    >>> print(adict['name'])                   #根据键查值
    bob
    >>> 'bob' in adict                         #不能直接查找值
    False
    >>> 'name' in adict
    True
    

2.字典相关函数

2.1 作用于字典的函数

  • len() :返回字典中元素的数目

  • hash() :本身不是为字典设计的,但是可以判断某个对象是否可以作为字典的键

    >>> print(adict)
    {'age': 23, 'name': 'bob'}
    >>> print(len(adict))
    2
    >>> hash(3)
    3
    >>> hash([])
    Traceback (most recent call last):
      File "", line 1, in 
    TypeError: unhashable type: 'list'
    

2.2 字典内建方法

  • dict.copy() :返回字典(深复制)的一个副本

    >>> print(adict)    ==> {'age': 23, 'name': 'bob'}
    >>> bdict = adict.copy()
    >>> bdict
    {'age': 23, 'name': 'bob'}
    >>> bdict['name'] = 'alice'
    >>> print(adict)    ==> {'age': 23, 'name': 'bob'}
    >>> print(bdict)    ==> {'age': 23, 'name': 'alice'}
    
  • dict.get(key,default) :获取字典dict中的键key的值,若字典中不存在此键,则返回default的值

    >>> adict.get('name')           ==> 'bob'
    >>> adict.get('namem','None')   ==> 'None'
    
  • dict.setdefault(key,default) :获取key的值,若字典中不存在key键,由dict[key]=default为它赋值

    >>> print(adict)    ==> {'age': 23, 'name': 'bob'}
    >>> adict.setdefault('age',20)
    23
    >>> print(adict)    ==> {'age': 23, 'name': 'bob'}
    >>> adict.setdefault('phone','12345678901')
    '12345678901'
    >>> print(adict)    ==> {'age': 23, 'name': 'bob', 'phone': '12345678901'}
    
  • dict.items() :返回一个包含字典中(键、值)对元组的列表

    >>> adict.items()
    dict_items([('name', 'bob'), ('age', 23), ('phone', '12345678901')])
    
  • dict.keys() :返回一个包含字典中键的列表

    >>> adict.keys()
    dict_keys(['name', 'age', 'phone'])
    
  • dict.values() :返回一个包含字典中所有值的列表

    >>> adict.values()
    dict_values(['bob', 23, '12345678901'])
    
  • dict.update(dict2) :将字典dict2的键-值对添加到字典dict

    >>> adict   ==> {'name': 'bob', 'age': 23, 'phone': '12345678901'}
    >>> bdict   ==> {'email': '[email protected]', 'sex': 'boy'}
    >>> adict.update(bdict)
    >>> adict
    {'name': 'bob', 'age': 23, 'phone': '12345678901', 'email': '[email protected]', 'sex': 'boy'}
    

2.3 实例

  • 案例:模拟用户登录信息系统

      1.支持新用户注册,新用户和密码注册到字典中
      2.支持老用户登录,用户名和密码正确提示登录成功
      3.主程序通过循环询问进行何种操作,根据用户的选择,执行注册或是登录操作
    
  • 案例:编写unix2dos的程序

      1.windows文本文件的行结束标志是\r\n
      2.类unix文本文件的行结束标志是\n
      3.编写程序,将unix文本文件格式转换为windows文本文件的格式
    
  • 案例:编写类进度条程序

      1.在屏幕上打印20个#号
      2.符号@从20个#号穿过
      3.当@符号到达尾部,再从头开始
    

3.集合

3.1 创建集合

  • 数学上,把set称作由不同的元素组成的集合,集合(set)的成员通常被称作集合元素

  • 集合对象是一组无序排列的可哈希的值

  • 集合有两种类型:

    • 可变集合set

    • 不可变集合frozenset #frozen,冰冻的

      >>> s1 = set('hello')
      >>> s2 = frozenset('hello')
      >>> s1
       {'o', 'e', 'l', 'h'}
      >>> s2
       frozenset({'o', 'e', 'l', 'h'})
      

3.2 集合类型操作符

  • 集合支持用in和not in操作符检查成员

  • 能够通过len()检查集合大小

  • 能够使用for迭代集合成员

  • 不能取切片,没有键

    >>> len(s1)    ==> 4
    >>> for ch in s1:
    ...     print(ch) 
    o
    e
    l
    h
    
  • | :联合,取并集

  • & :交集

  • - :差补

    >>> s1 = set('abc')
    >>> s2 = set('cde')
    >>> s1 | s2    ==> {'c', 'e', 'a', 'b', 'd'}
    >>> s1 & s2    ==> {'c'}
    >>> s1 - s2    ==> {'a', 'b'}
    >>> s2 - s1    ==> {'e', 'd'}
    

3.3 集合内建方法

  • set.add() :添加成员

  • set.update() :批量添加成员

  • set.remove() :移除成员

    >>> s1 = set('hello')
    >>> s1.add('new')
    >>> s1    ==> {'e', 'o', 'l', 'h', 'new'}
    >>> s1.update('new')
    >>> s1    ==> {'e', 'n', 'o', 'w', 'l', 'h', 'new'}
    >>> s1.remove('n')
    >>> s1    ==> {'e', 'o', 'w', 'l', 'h', 'n'}
    
  • s.issubset(t) :(is sub set,子集)如果s是t的子集,则返回True,否则返回False

    >>> s2 =  set('hello')
    >>> s2.issubset(s1)    ==> True
    
  • s.issuperset(t) :(is super set,超集)如果t是s的超集,则返回True,否则返回False

    >>> s3=set('helloworldmynameispython')
    >>> s3.issuperset(s1)  ==> True
    
  • s.union(t) :(union,联合)返回一个新集合,该集合是s和t的并集

    >>> s1    ==> {'n', 'e', 'o', 'h', 'w', 'l'}
    >>> s2    ==> {'h', 'e', 'o', 'l'}
    >>> s1.union(s2)
    {'n', 'e', 'o', 'h', 'w', 'l'}
    
  • s.intersection(t) :(intersection,交集)返回一个新集合,该集合是s和t的交集

    >>> s1.intersection(s2)
    {'h', 'e', 'l', 'o'}
    
  • s.difference(t) :(difference,差异)返回一个新集合,该集合是s的成员,但不是t的成员

    >>> s1.difference(s2)
    {'n', 'w'}
    

 

时间方法

time模块

1.时间表示方式

  • 时间戳timestamp :表示的是从1970年1月1日00:00:00开始按秒计算的偏移量
  • UTC(Coordinated Universal Time,世界协调时),即格林威治天文时间,世界标准时间。
  • 中国为UTC+8。DST(Daylight Saving Time)即夏令时。
  • 元组(struct_time):由9个元素组成。

2.struct_time元组

索引     //属性                        //值
0        //tm_year                    //2000
1        //tm_mon                     //1-12
2        //tm_mday                    //1-31
3        //tm_hour                    //0-23
4        //tm_min                     //0-59
5        //tm_sec                     //0-61
6        //tm_wday                    //0-6(0表示周一)
7        //tm_yday(一年中的第几天)      //1-366
8        //tm_isdst(是否为dst时间)     //默认为-1

3.time模块方法

  • import time

  • time.localtime([secs])

    将一个时间戳转换为当前时区的struct_time。secs参数未提供,则以当前时间为准。

  • time.gmtime([secs])

    和localtime()方法类似,gmtime()方法是将一个时间戳转换为UTC时区(0时区)的struct_time。

  • time.time()

    返回当前时间的时间戳

  • time.mktime(t)

    将一个struct_time转化为时间戳

  • time.sleep(secs)

    线程推迟指定的时间运行。单位为秒

  • time.asctime([t])

    把一个表示时间的元组或者struct_time表示为这种形式:'Sun Jun 20 23:21:05 1993'

    若没有参数,将会将time.localtime()作为参数传入。

  • time.ctime([secs])

    把一个时间戳(按秒计算的浮点数)转化为time.asctime()的形式。

  • time.strftime(format[,t])

    把一个代表时间的元组或者struct_time(如由time.localtime()和time.gmtime()返回)

    转化为格式化的时间字符串。若t未指定,将传入time.localtime()

  • time.strptime(string[,format])

    把一个格式化时间字符串转化为struct_time。实际它和strftime()是逆操作。

    >>> time.strptime("30 Nov 00", "%d %b %y")
    time.struct_time(tm_year=2000, tm_mon=11, tm_mday=30, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=335, tm_isdst=-1)
    
  • time.strftime(format[,t])

    将struct_time转化为格式化时间

    若布指定t,则使用由localtime()返回的当前时间

    >>> time.strftime('%Y-%m-%d %X',time.localtime())
    '2017-12-12 12:58:19'
    

4.时间样式

格式    含义                              |    格式    含义
%a      本地简化星期名称                   |    %m      月份(01-12)
%A      本地完整星期名称                   |    %M      分钟数(00-59)
%b      本地简化月份名称                   |    %p      本地am或pm的相应符
%B      本地完整月份名称                   |    %S      秒(01-61)
%c      本地相应的日期和时间               |    %U      一年中的星期数(00-53,周日是一周的开始)
%d      一个月中的第几天(01-31)            |    %w      一个星期中的第几天(0-6,0是星期日)
%H      一天中的第几个小时(24h制,00-23)    |    %x      本地相应日期
%I      第几个小时(12h制,01-12)           |    %X      本地相应时间
%j      一年中的第几天(001-366)            |    %y      去掉世纪的年份(00-99)
%Z      时区的名字                        |    %Y      完整的年份

datetime模块

1.datetime模块方法

  • import datetime

  • datetime.date.today()

    返回一个表示当前本地时间的datetime对象

    >>> datetime.date.today()   ==> datetime.date(2000, 5, 17)
    
  • datetime.datetime.now([tz])

    返回一个表示当前本地时间的datetime对象

    参数tz指定时区,获取tz参数所指时区的本地时间;

    >>> datetime.datetime.now() ==> datetime.datetime(2019, 5, 17, 3, 23, 7, 397040)
    
  • datetime.datetime.strptime(date_string,format)

    将格式字符串转换为datetime对象

    >>> datetime.datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
    datetime.datetime(2006, 11, 21, 16, 30)
    
  • datetime.datetime.ctime(datetime对象)

    返回时间格式字符串

    >>> datetime.datetime.ctime(datetime.datetime(2006, 11, 21, 16, 30))
    'Tue Nov 21 16:30:00 2006'
    
  • datetime.strftime(format)

    返回指定格式字符串

    >>> t=datetime.datetime.now()
    >>> t.strftime('%Y-%m-%d %H:%M:%S')
    '2019-05-17 03:45:05'
    

2.时间计算

  • 使用timedelta可以很方便的在日期上做天days,小时hour,分钟,秒,毫秒,微秒的时间计算

    >>> dt = datetime.datetime.now()
    >>> days = datetime.timedelta(days=100,hours=3)
    >>> dt + days
    datetime.datetime(2050,6,10,20,41,20,106546)
    

 

异常

1.什么是异常

  • 当python检测到一个错误时,解释器就会指出当前流已经无法继续执行下去,这时候就出现了异常

  • 异常是因为程序出现了错误而在正常控制流以外采取的行为

  • 这个行为又分为两个阶段:

    • 首先,是引起异常发生的错误

    • 然后,是检测(和采取可能的措施)阶段

2.python中的异常

  • 当程序运行时,因为遇到未解的错误而导致终止运行。便会出现traceback消息,打印异常

    异常                //描述
    NameError           //未声明/初始化对象
    IndexError          //序列中没有此索引
    SyntaxError         //语法错误
    KeyboardInterrupt   //用户中断执行
    EOFError            //没有内建输入,到达EOF标记
    IOError             //输入/输出操作失败
    

3.try-except语句

  • 定义了进行异常监控的一段代码,并且提供了处理异常的机制

    try:
        try_suite            #监控这里的异常
    except Exception[as reason]:
        except_suite         #异常处理代码
    
  • >>> try:
    ...     f = open('foo.txt')
    ... except FileNotFoundError:
    ...     print('No such file')
    No such file
    

4.带有多个expect的try语句

  • 可以把多个except语句连接在一起,处理一个try块中可能发生的多种异常

    >>> try:
    ...     data = int(input('input a number:'))
    ... except KeyboardInterrupt:
    ...     print('user cancelled')
    ... except ValueError:
    ...     print('you must input a number!')
    input a number:a
    you must input a number!
    

5.捕获所有异常

6.异常参数

  • 异常也可以有参数,异常引发后它会被传递给异常处理器

  • 当异常被引发后参数是作为附加帮助信息传递给异常处理器的

    >>> try:
    ...     10/0
    ... except ZeroDivisionError as e:
    ...     print('error',e)
    error division by zero
    
  • 案例:简化除法判断

      1.提示用户输入一个数字作为除数
      2.如果用户按下Ctrl+C或Ctrl+D则退出程序
      3.如果用户输入非数字字符,提示用户应该输入数字
      4.如果用户输入0,提示用户0不能作为除数
    

7.else子句

  • 在try范围中没有异常被检测到时,执行else子句

  • 在else范围中的任何代码运行前,try范围中的所有代码必须完全成功

    >>> try:
    ...     result = 100/int(input('number:'))
    ... except Exception as e:
    ...     print('Error:',e)
    ... else:
    ...     print(result)
    number:10
    10.0
    

8.finally子句

  • finally子句是无论异常是否发生,是否捕捉都会执行的一段代码

  • 如果打开文件后,因为发生异常导致文件没有关闭,可能会发生数据损坏。

  • 使用finally能保证文件总是能正常的关闭。

 

异常处理(触发异常)

1.raise语句

  • 要想引发异常,最简单的形式就是输入关键字raise,后面跟要引发的异常的名称

  • 执行raise语句时,python会创建指定的异常类的一个对象

  • raise语句还可指定对异常对象进行初始化的参数

2.断言

  • 断言是一句必须等价于布尔值为真的判定

  • 此外,发生异常也意味着表达式为假

    >>> assert 10 > 100 ,'Wrong'
    Traceback (most recent call last):
      File "", line 1, in 
    AssertionError: Wrong
    
  • 案例:自定义异常

      1.编写第一个函数,函数接收姓名和年龄,如果年龄不在1到120之间,产生ValueError异常
      2.编写第二个函数,函数接收姓名和年龄,如果年龄不在1到120之间,产生断言异常
    

 

os模块

1.os模块简介

  • 对文件系统的访问大多通过python的os模块实现

  • 该模块是python访问操作系统功能的主要接口

  • 有些方法,如copy等,并没有提供,可以使用shutil模块作为补充

2.os模块方法

  • 函数

    • mkdir(path,mode=0o777,*,dir_fd=None)

      创建目录

      >>> os.mkdir('/var/tmp/demo')
      
    • listdir(path='.')

      列出指定目录的文件

      >>> os.listdir('/var/tmp/demo')    ==> []
      
    • symlink(src,dst,target_is_directory=False,*,dir_fd=None)

      创建指向名为dst的src的符号链接

      >>> os.symlink('/etc/hosts','/var/tmp/demo/zhuji')
      
    • chdir(path)

      切换工作目录

      >>> os.chdir('/var/tmp/demo')
      
    • getcwd()

      //获得当前工作路径

      >>> os.getcwd()    ==> '/var/tmp/demo'
      
    • shutil.copy()

      //shutil模块,复制文件

      >>> shutil.copy('/etc/passwd','.')    ==> './passwd'
      
    • curdir

      //当前工作路径

      >>> os.curdir    ==> '.'
      
    • pardir

      //父目录

      >>> os.pardir    ==> '..'
      
    • stat(path,*,dir_fd=None,follow_symlinks=True)

      //获取文件属性

      >>> os.stat('passwd')            ==> os.stat_result(st_mode=33188, st_ino=778907, ...)
      >>> os.stat('passwd').st_size    ==> 2295
      
    • chmod(path,mode,*,dir_fd=None,follow_symlinks=True)

      //修改文件权限

      >>> os.chmod('passwd',0o600)
      
    • mknod(path,mode=0o600,device=0,*,dir_df=None)

      //创建空文件

      >>> os.mknod('abc.txt')
      
    • remove(path,*,dir_fd=None)

      //删除文件

      >>> os.remove('zhuji')
      
    • path.abspath(path)

      //获取文件的绝对(absolute)路径

      >>> os.path.abspath('abc.txt')    ==> '/var/tmp/demo/abc.txt'
      
    • path.basename(p)

      //返回路径名的最后一个组件

      >>> os.path.basename('/var/tmp/demo/abc.txt')    ==> 'abc.txt'
      
    • path.dirname(p)

      //返回路径名的目录组件

      >>> os.path.dirname('/var/tmp/demo/abc.txt')    ==> '/var/tmp/demo'
      
    • path.split(p)

      //路径拆分,以路径名的最后一个/为分割点,进行拆分

      >>> os.path.split('/var/tmp/demo/abc.txt')    ==> ('/var/tmp/demo', 'abc.txt')
      
    • path.join(a,*p)

      //拼接路径,将各参数用/连接;若后边的参数是绝对路径,则丢弃前边的参数

      >>> os.path.join('/var/tmp/demo', 'abc.txt')    ==> '/var/tmp/demo/abc.txt'
      
    • path.exists(path)

      //判断路径是否存在

      >>> os.path.exists('abc.txt')    ==> True
      
    • path.isfile(isfile)

      //判断路径存在且是文件

      >>> os.path.isfile('abc.txt')    ==> True
      
    • path.isdir(s)

      //判断路径存在且是目录

      >>> os.path.isdir('/etc')    ==> True
      
  • 案例:操作文件系统

      1.切换到/tmp目录
      2.创建example目录
      3.切换到/tmp/example目录
      4.创建test文件,并写入字符串foo bar
      5.列出/tmp/example目录内容
      6.打印test文件内容
      7.反向操作,把test文件以及example目录删除
    

 

pickle模块

1.pickle模块简介

  • 把数据写入文件时,常规的文件方法只能把字符串对象写入。其它数据需先转换成字符串再写入文件。

  • python提供了一个标准的模块,称为pickle。

  • 使用它可以在一个文件中储存任何python对象,之后又可以把它完整无缺地取出来。

2.pickle模块方法

  • 分别调用dump()和load()可以存储、写入

    >>> import pickle as p
    >>> shop_file = '/tmp/shop.data'
    >>> shop_list = ['eggs', 'apple', 'banana']
    >>> f = open(shop_file, 'wb')
    >>> p.dump(shop_list, f)  # 将列表写入到文件
    >>> f.close()
    >>> # ----------------------
    >>> f = open('/tmp/shop.data', 'rb')
    >>> shop_list = p.load(f)  # 把列表从文件中读出来
    >>> f.close()
    >>> print(shop_list)  #
    ['egg', 'apple', 'banana']
    
  • 案例:记账程序

      1.假设在记账时,有一万元钱
      2.无论是开销还是收入都要进行记账
      3.记账内容包括时间、金额和说明等
      4.记账数据要求永久存储
    

 

函数基础

1.创建函数

1.1 def语句

  • 函数用def语句创建,语法如下:

    >>> def function_name(arguments):           # >>> def 函数名(参数):
    ...     "function_documentation_string"     # ...     "函数说明"
    ...     function_body_suite                 # ...     函数体
    
  • 标题行由def关键字,函数的名字,以及参数的集合(若有的话)组成

  • def子句的剩余部分包括了一个虽然可选但是强烈推荐的文档字串,和必须的函数体

1.2 前向引用

  • 函数不允许在函数未声明之前对其进行引用或者调用

    >>> def foo():
    ...     print('in foo')
    ...     bar()
    >>> foo()                                #报错,因为bar没有定义
        in foo
        Traceback (most recent call last):
        File "", line 1, in 
        File "", line 3, in foo
        NameError: name 'bar' is not defined
    -------------------------------------------
    >>> def foo():
    ...     print('in foo')
    ...     bar()
    >>> def bar():
    ...     print('in bar')
    >>> foo()                                        #正常执行,虽然bar的定义在foo定义后面
        in foo
        in bar
    

1.3 内部函数

  • 在函数体内创建另外一个函数是完全合法的,这种函数叫做内部/内嵌函数;不能直接调用内嵌函数

    >>> def foo():
    ...     def bar():
    ...         print('bar() is called')
    ...     print('foo() is called')
    ...     bar()
    >>> foo()
        foo() is called
        bar() is called
    >>> bar()
        Traceback (most recent call last):
        File "", line 1, in 
        NameError: name 'bar' is not defined
    

2.调用函数

2.1 函数操作符

  • 使用一对圆括号()调用函数,若没有圆括号,只是对函数的引用

  • 任何输入的参数都必须放置在括号中

    >>> def foo():
    ...     print('Hello World!')
    >>> foo()
        Hello World!
    >>> foo
        
    

2.2 关键字参数

  • 关键字参数的概念仅仅针对函数的调用

  • 这种理念是让调用者通过函数调用中的参数名字来区分参数

  • 这样规范允许参数缺失或者不按顺序

    >>> def get_info(name,age):
    ...     print("%s's age is %s" % (name,age))
    >>> get_info(23,'bob')
        23's age is bob
    >>> get_info(age=23,name='bob')
        bob's age is 23
    

2.3 参数组

  • python允许程序员执行一个没有显示定义参数的函数

  • 相应的方法是通过一个把元组(非关键字参数)或字典(关键字参数)作为参数组传递给函数

    >>> func(*tuple_grp_nonkw_args,**dict_grp_kw_args)
    
  • 案例:简单的加减法数学游戏

      1.随机生成两个100以内的数字
      2.随机选择加法或减法
      3.总是使用大的数字减去小的数字
      4.如果用户答错三次,程序给出正确答案
    

3.lambda(匿名函数)

  • python允许用lambda关键字创造匿名函数

  • 匿名是因为不需要以标准的def方式来声明

  • 一个完整的lambda"语句"代表了一个表达式,这个表达式的定义体必须和声明放在同一行

  • 格式: lambda [arg1[,arg2,...argN]]:expression

    >>> a = lambda x,y: x + y
    >>> print(a(3,4))
        7
    

4 filter()函数

  • 格式: filter(func,seq)

  • 调用一个布尔函数func来迭代遍历每个序列中的元素;

  • 返回一个使func返回值为Ture的元素的序列;

  • 若布尔函数比较简单,直接使用lambda匿名函数就显得非常方便

    >>> data = filter(lambda x: x%2, [num for num in range(10)])
    >>> print(list(data))            #过滤出10以内的奇数
    [1,3,5,7,9]
    

5 map()函数

  • 格式: map(函数,序列,序列...)

  • map()函数会根据提供的函数对指定序列做映射

  • 使用input赋值多个变量

    >>> a,b,c = map(int,input("请输入值:").split(','))  #split,指定分隔符,默认是空格
    

 

函数高级应用

1.变量作用域

1.1 全局变量

  • 标识符的作用域是定义为其声明在程序里的可应用范围,也就是变量的可见性;

  • 在一个模块中最高级别的变量有全局作用域;

  • 全局变量的一个特征是除非被删除掉,否则它们存活到脚本运行结束,

  • 且对于所有的函数,它们的值都是可以被访问的;

1.2 局部变量

  • 局部变量只是暂时地存在,仅仅依赖于定义它们的函数现阶段是否处于活动;

  • 当一个函数调用出现时,其局部变量就进入声明它们的作用域。那时,一个新的局部变量名为那个对象创建了;

  • 一旦函数完成,框架被释放,变量将会离开作用域。

  • 若局部与全局有相同名称的变量,那么函数运行时,局部变量的名称将会把全局变量名遮盖住;

    >>> x = 4
    >>> def foo():
    ...     x = 10
    ...     print('in foo, x=',x)
    >>> foo()
    in foo, x= 10
    >>> print('in main,x=',x)
    in main,x= 4
    

1.3 global语句

  • 因全局变量名能被局部变量名给遮盖掉,所以为了明确地引用一个已命名的全局变量,必须用global语句

    >>> x = 4
    >>> def foo():
    ...     global x
    ...     x = 10
    ...     print('in foo,x =',x)
    >>> foo()
    in foo,x = 10
    >>> print('in mian,x=',x)
    in mian,x= 10
    

1.4 名字空间

  • 任何时候,总有一到三个活动的作用域(内建、全局、局部)

  • 标识符的搜索顺序依次是局部、全局、内建

  • 提到名字空间,可以想象是否有这个标识符

  • 提到变量作用域,可以想象是否可以"看见"这个标识符

2.函数式编程

2.1 偏函数

  • 偏函数的概念是将函数式编程的概念和默认参数以及可变参数结合在一起

  • 一个带有多个参数的函数,若其中某些参数基本上固定的,那么就可以通过偏函数为这些参数赋默认值

    >>> from operator import add
    >>> from functools import partial
    >>> add10 = partial(add,10)
    >>> print(add10(25))
    35
    
  • 案例:简单GUI程序

      1.窗口程序提供三个按钮
      2.其中两个按钮的前景色均为白色,背景色为蓝色
      3.第三个按钮前景色为红色,背景色为红色
      4.按下第三个按钮后,程序退出
    

2.2 递归函数

  • 如果函数包含了对其自身的调用,该函数就是递归的

  • 在操作系统中,查看某一目录内所有文件、修改权限等都是递归的应用

    >>> def func(num):
    ...     if num == 1:
    ...         return 1
    ...     else:
    ...         return num * func(num -1)
    >>> print(func(5))
    120
    >>> print(func(10))
    3628800
    
  • 案例:快速排序

      1.随机生成10个数字
      2.利用递归,实现快速排序
    

2.3 生成器

  • 从句法上讲,生成器是一个带yield语句的函数

  • 一个函数或子程序只返回一次,但一个生成器能暂停执行并返回一个中间的结果

  • yield语句返回一个值给调用者并暂停执行

  • 当生成器的next()方法被调用的时候,它会准确地从离开地方继续

  • 与迭代器相似,生成器以另外的方式来运作

  • 当到达一个真正的返回或者函数结束没有更多的值返回,StopIteration异常就会被抛出

3.内部函数

3.1 闭包

  • 闭包将内部函数自己的代码和作用域以及外部函数的作用结合起来

  • 闭包的词法变量不属于全局名字空间域或局部的,而属于其它的名字空间,带着"流浪"的作用域

  • 闭包对于安装计算,隐藏状态,及在函数对象和作用域中随意地切换是很有用的

  • 闭包也是函数,但它们能携带一些额外的作用域

3.2 闭包实例

  • 创建通用的计数器

    >>> def counter(start=0):
    ...     count = start
    ...     def incr():
    ...         nonlocal count  #nonlocal,外层,访问外层作用域的名称
    ...         count += 1
    ...         return count
    ...     return incr
    >>> a = counter()
    >>> b = counter(10)
    >>> a()
        1
    >>> b()
        11
    

3.3 装饰器

  • 装饰器是在函数调用之上的修饰

  • 这些修饰仅是当声明一个函数或方法的时候,才会应用的额外调用

  • 使用装饰器的情形有:

    • 引入日志

    • 增加计时逻辑来检测性能

    • 给函数加入事务的能力

  • 案例:测试程序运行效率

      1.有个程序包含多个函数
      2.程序运行耗时较长
      3.为了确定哪个函数是瓶颈,需要计算出每个函数运行时间
      4.要求使用装饰器实现
    

 

模块

1.模块和文件

1.1 什么是模块

  • 模块支持从逻辑上组织python代码

  • 当代码量变得相当大的时候,最好把代码分成一些有组织的代码段

  • 代码片段相互间有一定的联系,可能是一个包含数据成员和方法的类,也可能是一组相关但彼此独立的操作函数

  • 这些代码段是共享的,所以python允许"调入"一个模块,允许使用其它模块的属性来利用之前的工作成果,实现代码重用

1.2 模块文件

  • 说模块是按照逻辑来组织python代码的方法,文件是物理层上组织模块的方法

  • 一个文件被看作是一个独立模块,一个模块也可以被看作是一个文件

  • 模块的文件名就是模块的名字加上扩展名'.py'

1.3 名称空间

  • 名称空间就是一个从名称到对象的关系映射集合

  • 给定一个模块名后,只会有一个模块被导入到python解释器中,所以在不同模块间不会出现名称交叉现象

  • 每个模块都定义了它自己的唯一的名称空间

    >>> import foo          #自定义模块
    >>> import bar          #自定义模块
    >>> print(foo.hi)        #调用foo模块中的hi变量
        hello
    >>> print(bar.hi)        #调用bar模块中的hi变量
        greet
    

2.导入模块

2.1 搜索路径

  • 模块的导入需要一个叫做"路径搜索"的过程

  • python在文件系统"预定义区域"中查找要调用的模块

  • 搜索路径在sys.path中定义

    >>> import sys
    >>> print(sys.path)
        ['', '/usr/local/lib/python36.zip', '/usr/local/lib/python3.6', '/usr/local/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/site-packages']
    

2.2 模块导入方法

  • 使用import导入模块

  • 可以在一行导入多个模块,但是可读性会下降

  • 可以只导入模块的某些属性

  • 导入模块时,可以为模块取别名

    >>> import time,os,sys
    >>> from random import choice
    >>> import pickle as p
    

2.3 导入和加载

  • 当导入模块时,模块的顶层代码会被执行

  • 一个模块不管被导入(import)多少次,只会被加载(load)一次

    >>> f = open('foo.py','w+')                            #打开文件
    >>> f.writelines(["hi = 'hello'\n","print(hi)\n"])     #写入文件
    >>> f.close()                                          #关闭文件
    >>> import foo        #第一次导入,执行print语句
        hello
    >>> import foo        #再次导入,print语句不再执行
    

2.4 从zip文件中导入

  • 在2.3版本中,python加入了从zip归档文件导入模块的功能

  • 若搜索路径中存在一个包含python模块(.py、.pyc、.pyo)的.zip文件,导入时会把zip文件当目录处理

    >>> import sys                                #导入sys模块
    >>> sys.path.append('/root/pymodule.zip')     #在搜索路径中加入相应的zip文件
    >>> import foo                                #导入pymodule.zip压缩文件中的foo模块
    

3.包

3.1 目录结构

  • 包是一个有层次的文件目录结构,为平坦的名称空间加入有层次的组织架构

  • 允许程序员把有联系的模块组合到一起

  • 包目录下必须有一个__init__.py文件

    phone/
        __init__.py
        common_util.py
        voicedata/
            __init__.py
            post.py
    

3.2 绝对导入

  • 包的使用越来越广泛,很多情况下导入子包会导致和真正的标准库模块发生冲突;

  • 所有的导入现在都被认为是绝对的,就是说这些名字必须通过python路径(sys.path或PYTHONPATH)来访问

3.3 相对导入

  • 绝对导入特性使得程序员失去了import的自由,为此出现了相对导入

  • 因为import语句总是绝对导入的,所以相对导入只应用于from-import语句

    ]# ls -R phone/
        phone/:
        common_util.py __init__.py voicedata
        phone/voicedata:
        __init__.py post.py
    ]# cat phone/voicedata/post.py
        from .. import common_util
    

4.内置模块

4.1 hashlib模块

  • hashlib用来替换md5和sha模块,并使它们的API一致,专门提供hash算法

  • 包括md5、sha1、sha224、sha256、sha384、sha512,使用非常简单、方便

    >>> import hashlib
    >>> m = hashlib.md5()
    >>> m.update(b'hello world!')
    >>> m.hexdigest()
        'fc3ff98e8c6a0d3087d515c0473f8677'
    

4.2 tarfile模块

  • tarfile模块允许创建、访问tar文件

  • 同时支持gzip、bzip2格式

    ]# ls /home/demo
     install.log mima
    
    ]# python
    >>> import tarfile
    >>> tar = tarfile.open('/home/demo.tar.gz','w:gz')
    >>> tar.add('demo')
    >>> tar.close()
    
  • 案例:备份程序

      1.需要支持完全和增量备份
      2.周一执行完全备份
      3.其他时间执行增量备份
      4.备份文件需要打包为tar文件并使用gzip格式压缩
    

 

OOP基础

1.OOP简介

1.1 基本概念

  • 类(Class):用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

  • 实例化:创建一个类的实例,类的具体对象。

  • 方法:类中定义的函数

  • 对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

1.2 创建类

  • 使用class语句来创建一个新类,class之后为类的名称并以冒号结尾

  • 类名建议使用驼峰形式

    class BearToy:
        pass
    

1.3 创建实例

  • 类是蓝图,实例是根据蓝图创建出来的具体对象

    tidy = BearToy()
    

2.绑定方法

2.1 构造器方法

  • 当实例化类的对象是,构造器方法默认自动调用

  • 实例本身作为第一个参数,传递给self

      ]# vim toy.py
        class BearToy:
            def __init__(self,size,color):          # __init__在实例化时自动调用
                self.size = size                    #实例本身默认作为第一个参数自动传入
                self.color = color
            def sing(song):
                print(song)
        if __name__ == '__main__':
            tidy = BearToy('small','orange')        #实例化对象
            print(tidy.size)
            print(tidy.color)
            tidy.sing('lalala...')
            old = BearToy('large','brown')
            old.sing('wowowow...')
      ]# python3 toy.py
        small
        orange
        lalala...
        wowowow...
    

2.2 其它绑定方法

  • 类中定义的方法需要绑定在具体的实例,由实例调用

  • 实例方法需要明确调用

    class BearToy:
        def __init__(self,size,color):
            self.size = size
            self.color = color
        def speak(self):
            print('hahaha')
    if __name__ == '__main__':
        tidy = BearToy('small','orange')
        tidy.speak()
    

2.3 案例:编写酒店类

    1.用于计算住宿开销
    2.酒店有会员卡可以打九折
    3.每天早餐15元
    4.根据住宿天数返加总费用

 

OOP进阶

1.组合和派生

1.1 什么是组合

  • 类被定义后,目标就是要把它当成一个模块来使用,并把这些对象嵌入到你的代码中

  • 组合就是让不同的类混合并加入到其它类中来增加功能和代码重用性

  • 可以在一个大点的类中创建其它类的实例,实现一些其它属性和方法来增强对原来的类对象

1.2 组合应用

  • 两个类明显不同

  • 一个类是另一个类的组件

    class Manufacture:
        def __init__(self,phone,email):
            self.phone = phone
            self.email = email
    class BearToy:
        def __init__(self,size,color,phone,email):
            self.size = size
            self.color = color
            self.vendor = Manufacture(phone,email)
    

1.3 创建子类

  • 当类之间有显著的不同,并且较小的类是较大的类所需要的组件时组合表现得很好;

  • 但当设计"相同的类但有一些不同的功能"时,派生就是一个更加一个更加合理的选择了;

  • OOP的更强大方面之一是能够使用一个已经定义好的类,扩展它或者对其进行修改,而不会影响系统中使用现存类的其它代码片段

  • OOP(面向对象设计)允许类特征在子孙类或子类中进行继承

  • 创建子类只需要在圆括号中写明从哪个父类继承即可

    class BearToy:
        def __init__(self,size,color):
            self.size = size
            self.color = color
    …
    class NewBearToy:
        pass
    

1.4 继承

  • 继承描述了基类的属性如何"遗传"给派生类

  • 子类可以继承它的基类的任何属性,不管是数据属性还是方法

    class BearToy:
        def __init__(self,size,color):
            self.size = size
            self.color = color
    …
    class NewBearToy:
        pass
    if __name__ == '__main__':
        tidy = NewBearToy('small','orange')
        tidy.speak()
    

1.5 通过继承覆盖方法

  • 如果子类中有和父类同名的方法,父类方法将被覆盖

  • 如果需要访问父类的方法,则要调用一个未绑定的父类方法,明确给出子类的实例

    class BearToy:
        def __init__(self,size,color,phone,email):
            self.size = size
            self.color = color
            self.vendor = Manufacture(phone,email)
        .…
    class NewBearToy(BearToy):
        def __init__(self,size,color,phone,email,date):
            super(NewBearToy,self).__init__(size,color,phone,email)
            self.date = date
    

1.6 多重继承

  • python允许多重继承,即一个类可以是多个父类的子类,子类可以拥有所有父类的属性

    >>> class A:
    ...     def foo(self):
    ...         print('foo method') 
    >>> class B:
    ...     def bar(self):
    ...         print('bar method')
    >>> class C(A,B):
    ...     pass 
    >>> c = C()
    >>> c.foo()
        foo method
    >>> c.bar()
        bar method
    

2.特殊方法

2.1 类方法

  • 使用classmethod装饰器定义

  • 第一个参数cls表示类本身

    >>> class Date:
    ...     def __init__(self,year,month,date):
    ...         self.year = year
    ...         self.month = month
    ...         self.date = date
    >>> if __name__ == '__main__':
    ...     d1 = Date(2018,1,1)
    

2.2 类方法实例

>>> class Date:
...     def __init__(self,year,month,date):
...         self.year = year
...         self.month = month
...         self.date = date
...     @classmethod
...     def create_date(cls,string_date):
...         year,month,date = map(int,string_date.split('-'))
...         instance = cls(year,month,date)
...         return instance 
>>> if __name__ == '__main__':
...     d2 = Date.create_date('2018-05-04')

2.3 静态方法

  • 基本上就是一个函数

  • 在语法上就像一个方法

  • 没有访问对象和它的字段或方法

  • 使用staticmethod装饰器定义

2.4 静态方法实例

class Date:
    def __init__(self,year,month,date):
        self.year = year
        self.month = month
        self.date = date
    @staticmethod
    def is_date_valid(string_date):
        year,month,date = map(int,string_date.split('-'))
        return 1 <= date <= 31 and 1 <= month <= 12 and year < 3999
if __name__ == '__main__':
    print(Date.is_date_valid('2018-02-04'))
    print(Date.is_date_valid('2018-22-04'))

2.5 __init__方法

  • 实例化类实例时默认会调用的方法

    class BearToy:
        __init__(self,size,color):
            self.size = size
            self.color = color
    if __name__ == '__main__':
        tidy = BearToy('small','orange')
    

2.6 __str__方法

  • 打印/显示实例时调用方法

  • 返回字符串

    class BearToy:
        __init__(self,size,color):
            self.size = size
            self.color = color
        def __str__(self):
            return '' % (self.size,self.color)
    if __name__ == '__main__':
        tidy = BearToy('small','orange')
        print(tidy)
    

2.7 __call__方法

  • 用于创建可调用的实例

    class BearToy:
        __init__(self,size,color):
            self.size = size
            self.color = color
        def __call__(self):
            print('I am a %s bear' % self.size)
    if __name__ == '__main__':
        tidy = BearToy('small','orange')
        print(tidy)
    
  • 案例:出版商程序

      1.为出版商编写一个Book类
      2.Book类有书名、作者、页数等属性
      3.打印实例时,输出书名
      4.调用实例时,显示该书由哪个作者编写
    

 

re模块

1.正则表达式

1.1 匹配单个字符

    记号               //说明
    .                 //匹配任意字符(换行符除外)
    [...x-y...]       //匹配字符组里的任意字符
    [^...x-y...]      //匹配不在字符组里的任意字符
    \d                //匹配任意数字,与[0-9]同义
    \w                //匹配任意数字字母字符,与[0-9a-zA-Z_]同义
    \s                //匹配空白字符,与[\r\v\f\t\n]同义

1.2 匹配一组字符

    记号              //说明
    literal          //匹配字符串的值
    re1|re2          //匹配正则表达式re1或re2
    *                //匹配前面出现的正则表达式0次或多次
    +                //匹配前面出现的正则表达式1次或多次
    ?                //匹配前面出现的正则表达式0次或多次
    {M,N}            //匹配前面出现的正则表达式至少M次最多N次

1.3 其它元字符

记号        //说明
^            //匹配字符串的开始
$            //匹配字符串的结尾
\b            //匹配单词的边界
()            //对正则表达式分组
\nn            //匹配已保存的子组

1.4 贪婪匹配

  • *、+和?都是贪婪匹配操作符,在其后加上?可以取消其贪婪匹配行为

  • 正则表达式匹配对象通过groups函数获取子组

    >>> data = 'My phone number is: 150888899999'
    >>> m = re.search('.+(\d+)',data)
    >>> print(m.groups())
        ('9',)
    >>> m = re.search('.+?(\d+)',data)
    >>> m.groups()
        ('150888899999',)
    

2.核心函数和方法

2.1 match函数

  • 尝试用正则表达式模式从字符串的开头匹配,如果匹配成功,则返回一个匹配对象;否则返回None

    >>> import re
    >>> m = re.match('foo','food')            #成功匹配
    >>> print(m)
        <_sre.SRE_Match object; span=(0,3),match='foo'>
    >>> m = re.match('foo','seafood')        #未能匹配
    >>> print(m)
        None
    

2.2 search函数

  • 在字符串中查找正则表达式模式的第一次出现,如果匹配成功,则返回一个匹配对象;否则返回None

    >>> import re
    >>> m = re.search('foo','food')
    >>> print(m)
        <_sre.SRE_Match object; span=(0, 3), match='foo'>
    >>> m = re.search('foo','seafood')
    >>> print(m)
        <_sre.SRE_Match object; span=(3, 6), match='foo'>
    

2.3 group方法

  • 使用match或search匹配成功后,返回的匹配对象可以通过group方法获得匹配内容

    >>> import re
    >>> m = re.match('foo','food')
    >>> print(m.group())
        foo
    >>> m = re.search('foo','seafood')
    >>> m.group()
        'foo'
    

2.4 findall函数

  • 在字符串中查找正则表达式模式的所有(非重复)出现;返回一个匹配对象的列表

    >>> import re
    >>> m = re.search('foo','seafood is food')
    >>> print(m.group())                        #search只匹配模式的第一次出现
        foo
    >>> m = re.findall('foo','seafood is food')    #获得全部的匹配项
    >>> print(m)
        ['foo', 'foo']
    

2.5 finditer函数

  • 和findall()函数有相同的功能,但返回的不是列表而是迭代器;对每个匹配项,该迭代器返回一个匹配对象

    >>> import re
    >>> m = re.finditer('foo','seafood is food')
    >>> for item in m:
    ...     print(item.group())
     foo
     foo
    

2.6 compile函数

  • 对正则表达式模式进行编译,返回一个正则表达式对象

  • 不是必须要用这种方式,但是在大量匹配的情况下,可以提升效率

    >>> import re
    >>> patt = re.compile('foo')
    >>> m = patt.match('food')
    >>> print(m.group())
        foo
    

2.7 split方法

  • 根据正则表达式中的分隔符把字符分隔为一个列表,并返回成功匹配的列表

  • 字符串也有类似的方法,但是正则表达式更加灵活

    >>> import re            #使用 .和- 作为字符串的分隔符
    >>> mylist = re.split('\.|-','hello-world.data')
    >>> print(mylist)
        ['hello','world','data']
    

2.8 sub方法

  • 把字符串中所有匹配正则表达式的地方替换成新的字符串

    >>> import re
    >>> m = re.sub('X','Mr.Smith','attn:X\nDear X')
    >>> print(m)
        attn:Mr.Smith
        Dear Mr.Smith
    
  • 案例:分析apache访问日志

      1.统计每个客户端访问apache服务器的次数
      2.将统计信息通过字典的方式显示出来
      3.分别统计客户端是Firefox和MSIE的访问次数
      4.分别使用函数式编程和面向对象编程的方式实现
    

 

socket模块

1.C/S架构

1.1 什么是C/S架构

  • 服务器是一个软件或硬件,用于提供客户需要的"服务"

  • 硬件上,客户端常见的就是平时所使用的PC机,服务器常见的有联想、DELL等厂商生产的各种系列服务器

  • 软件上,服务器提供的服务主要是程序的运行,数据的发送与接收、合并、升级或其它的程序或数据的操作

1.2 套接字

  • 套接字是一种具有"通讯端点"概念的计算机网络数据结构

  • 套接字起源于20世纪70年代加利福尼亚大学伯克利分校版本的Unix

  • 一种套接字是Unix套接字,其"家族名"为AF_UNIX

  • 另一种套接字是基于网络的,"家族名"为AF_INET

  • 如果把套接字比作电话的插口,那么主机与端口就像区号与电话号码的一对组合

1.3 面向连接与无连接

  • 无论你使用哪一种地址家族,套接字的类型只有两种。

  • 一种是面向连接的套接字;另一种是无连接的套接字;

  • 面向连接的主要协议就是传输控制协议TCP,套接字类型为SOCK_STREAM

  • 无连接的主要协议是用户数据报协议UDP,套接字类型为SOCK_DGRAM

  • python中使用socket模块中的socket函数实现套接字的创建

2.socket函数与方法

2.1 创建TCP服务器

  • 创建TCP服务器主要步骤:

    • 创建服务器套接字: s = socket.socket()
    • 绑定地址到套接字: s.bind()
    • 启动监听: s.listen()
    • 接受客户连接: s.accept()
    • 与客户端通信: recv()/send()
    • 关闭套接字: s.close()
  • 创建TCP时间戳服务器

      1.服务器监听在0.0.0.0的21567端口上
      2.收到客户端数据后,将其加上时间戳后回送给客户端
      3.如果客户端发过来的字符全是空白字符,则终止与客户端的连接
    

2.2 创建TCP客户端

  • 创建TCP客户端的步骤:

      1.创建客户端套接字: cs = socket.socket()
      2.尝试连接服务器: cs.connect()
      3.与服务器通信: cs.send()/cs.recv()
      4.关闭客户端套接字: cs.close()
    
  • 案例:创建TCP时间戳客户端

      1.连接服务器的21567端口
      2.接收用户从键盘上的输入
      3.发送接收到的字符串给服务器
      4.如果用户按ctrl+c则退出程序
    

2.3 创建UDP服务器

  • 创建UDP服务器的主要步骤:

      1.创建服务器套接字: s = socket.socket()
      2.绑定服务器套接字: s.bind()
      3.接收、发送数据: s.recvfrom()/ss.sendto()
      4.关闭套接字: s.close()
    
  • 案例:创建UDP时间戳服务器

      1.服务器监听0.0.0.0的21567端口上
      2.收到客户端数据后,将其加上时间戳后回送给客户端
    

2.4 创建UDP客户端

  • 创建UDP客户端的步骤:

      1.创建客户端套接字: cs = socket.socket()
      2.与服务器通信: cs.sendto()/cs.recvfrom()
      3.关闭客户端套接字: cs.close()
    
  • 案例:创建UDP的时间戳客户端

      1.连接服务器的21567端口
      2.接收用户从键盘上的输入
      3.发送接收到的字符串给服务器
      4.如果用户按ctrl+c则退出程序
    

转载于:https://my.oschina.net/xinsui1314x/blog/3071079

你可能感兴趣的:(python笔记)