Python进阶

目录

基础必会

文字的编码

函数定义 function

def 语句

函数的调用

return 语句

函数的调用传参

局部变量和全局变量

global 语句

lambda 表达式(又称匿名函数)

id(x) 函数

is / is not 运算符

None 对象

函数式编程

python 中的常用高阶函数

python 中常用的函数

map函数

filter 函数

sorted 函数

模块

import 语句

python 的第三方模块

random 模块

time 模块

datetime 模块

异常

try 语句

raise 语句

文件

with 语句

sys模块

os 模块

os.path 模块

shutil 模块

生成器

生成器函数

生成器表达式

面向对象编程 Object-Oriented Programming(OOP)

class 语句

实例方法(instance method)

初始化方法(也叫构造器方法)

继承(inheritance)和派生(derived)

三个魔法方法

正则表达式 (regular express)

多线程编程


基础必会

- 表达式

          - 字面值

               - 字符串 str
               - 数字
                        - 整数 int
                        - 浮点数 float
                         - 布尔类型bool
               - 容器
                      - 列表 list
                      - 元组 tuple
                      - 字典 dict
                      - 集合 set 和 固定集合 frozenset
                      - 字节串 bytes 和 字节数组bytearray(后面在学)

          - 运算符

                - 算术运算符

+ - * / // % **

                - 比较运算符

      <  >  <=   >=   ==   !=

               - 布尔运算符

 and  or   not
   L = [1, 2, 3, 4, 5, 6]
      print(L[2])
      print(L[2:5])

                - 条件表达式

  '及格' if score >= 60 else '不及格'

                 - in / not in 运算符

     '王昭君' in ['孙悟空', '赵云']

                 - 索引和切片   

  > 用于 str, list, tuple, bytes, bytearray
      L = [1, 2, 3, 4, 5, 6]
      print(L[2])
      print(L[2:5])

  - 函数

            - 构造函数(函数名和类名相同的函数)

      str()  ---> ''        int() -->  0       
      float()      bool()       list()       tuple()      dict()
      set()      frozenset()

            - 函数

 print()        input()      len(x)     max(x)     min(x)
      sum(x)        range()      type(x)


      ```

- 语句

          - 简单语句
                    - 表达式语句
                    - 赋值语句
                    - del 语句
                    - pass 语句
                    - break 语句
                    - contiue 语句
  - 复合语句
                    - if 语句
                    - while 语句
                    - for 语句

> 所有的容器类都是可迭代对象,可以用 for 语句遍历其中的全部内容

文字的编码

Python3的字符串内部存储的是文字的UNICODE编码

  • 字符串中存储的是什么?

    • 是一个图片(文字)对应的编码(code)

  • 字符相关的函数

    函数

    说明

    chr(x)

    根据x的UNICODE编码值得到对应的字符

    ord(x)

    可以返回一个 字符的 UNICODE 编码值

    英文的编码值 详见 ASCII 编码

    man ascii

    ord(x) 函数的返回值如果是0~127 则 x 是英文字符,中文字符串一个编码值一定大于128

示例

>>> chr(98)
'b'
>>> chr(20000)
'丠'
>>> chr(20001)
'両'
>>> chr(20002)
'丢'
>>> chr(20003)
'丣'
>>> chr(20004)
'两'
>>> ord('两')
20004
>>> ord('A')   # 65
>>> ord('B')   # 66    
#     英文的编码值在 0~127 之间
>>> ord('中')  # 20013
  • 在python的交互模式下打印全世界的文字
for ch in range(65536):
   print(chr(ch), end='')

函数定义 function

  • 什么是函数

    • 函数是可以重复执行的语句块,可以重复调用

  • 作用

    用于封装语句块, 提高代码的重用性。

函数是面向过程编程的最小单位

def 语句

  • 作用

    用来定义( 创建)函数

语法

def 函数名(形式参数列表):
   语句块
  • 说明
  1. 函数的名字就是语句块的名称

  2. 函数名必须是标识符

  3. 函数名是一个变量,不要轻易对其赋值

  4. 函数有自己的名字空间,在函数外部不可以访问函数内部的变量,在函数内部可以访问函数外部的变量,但不能轻易对其改变

  5. 函数的形参列表如果不需要传入参数,形式参数列表可以为空

  • 示例

    # 定义一个函数,用 say_hello 变量绑定
    def say_hello():
       print("hello world!")
       print("hello tarena!")
       print("hello everyone!")
       
    # 定义一个函数,传入两个参数,让这个函数把最大的值打印到终端
    def mymax(a, b):
       if a > b:
           print("最大值是", a)
       else:
           print("最大值是", b)

函数的调用

  • 语法

    函数名(实际调用传递参数)

  • 说明

    • 函数调用是一个表达式

    • 如果函数内没有return 语句,函数执行完毕后返回 None 对象

  • 示例

    # 调用
    say_hello()  # 调用一次
    say_hello()  # 调用第二次
    ​
    # 调用
    mymax(100, 200)
    mymax(999, 1)
    mymax('abc', 'cba')

return 语句

  • 语法

    return [表达式]

    注: [] 代表 内部的内容可以省略

  • 作用

    用于函数的内部,结束当前函数的执行,返回到调用此函数的地方,同时返回一个对象的引用关系

  • 说明

    1. return 语句后面的表达式可以省略,省略后相当于 return None

    2. 如果函数内部没有 return 语句, 则函数执行完毕后返回None, 相当于在最后一条语句后有一条return None

  • 示例

    def say_hello():
       print("hello aaa")
       print("hello bbb")
       return 1 + 2
       print("hello ccc")
    ​
    r = say_hello()
    print(r)   # 3

函数的调用传参

  • 位置传参

    实际参数传递时,实参和形参 按位置来依次对应

  • 关键字传参

    实际参数传递时,实参和形参 按名称依次对应

注: 位置传参要先于关键字传参

示例

def myfun1(a, b, c):
   print('a=', a)
   print('b=', b)
   print('c=', c)
# 位置传参
myfun1(1, 2, 3)
# 关键字传参
myfun1(c=33, a=11, b=22)
# 位置传参要先于关键字传参
myfun1(111, c=333, b=222)   # 正确

函数的形式参数定义方法

函数的缺省参数

语法

def 函数名(形参名1=默认实参1, 形参名2=默认实参2, ... ):
    语句块

说明

缺省参数必须自右向左依次存在(即,如果一个参数有缺省参数,则其右侧的所有参数都必须有缺省参数)

示例

def myadd4(a, b, c=0, d=0):
   return a + b + c + d
print(myadd4(1, 2))
print(myadd4(1, 2, 3))
print(myadd4(1, 2, 3, 4))

错误示例

>>> def myadd(a, b=0, c):   # 报错
...    pass
​

形参的定义

  • 位置形参

  • 星号元组形参(*args)

  • 命名关键字形参

  • 双星号字典形参(**kwargs)

1) 位置形参

  • 语法:

    def 函数名(形参名1, 形参名2, ...):
       pass

2) 星号元组形参

  • 语法

    def 函数名(*元组形参名):
       pass
    
    

  • 作用

    收集多余的位置实参

    元组形参名 一般命名为args

  • 示例

    def myfunc2(*args):
       print("len(args)=", len(args))
       print('args=', args)
       
    myfunc2()           # args=()
    myfunc2(1, 2, 3)    # args=(1, 2, 3)
    ​
    def myfunc3(a, b, *args):
       print(a, b, args)
    ​
    myfunc3(1, 2)        # 1-->a, 2-->b, ()--->args
    myfunc3(1, 2, 3, 4)  # # 1-->a, 2-->b, (3, 4)--->args

3)命名关键字形参

  • 语法

    def 函数名(*, 命名关键字形参1, 命名关键字形参2, ...):
       pass
    # 或者
    def 函数名(*args, 命名关键字形参1, 命名关键字形参2, ...):
       pass

  • 作用

    强制,所有的参数都必须用关键字传参

  • 示例

    def myfunc4(a, b,*args, c, d):
       print(a, b, c, d)
    ​
    myfunc4(1, 2, d=4, c=3)   # 正确,c,d 必须关键字传参
    myfunc4(1, 2, 3, 4)   # 错误

4)双星号字典形参

  • 语法

    def 函数名(**字典形参名):
       pass

  • 作用

    收集多余的关键字传参

    字典形参名 最多有一个,

    字典形参名 一般命名为 kwargs

示例

def myfunc5(**kwargs):
   print(kwargs)
​
# {'name': 'tarena', 'age': 18}-->kwargs
myfunc5(name='tarena', age=18) 

函数的形参定义方法说明

  • 位置形参,星号元组形参,命名关键字参数,双星号字典形参,缺省参数可以混合使用。

  • 函数的形参定义自左至右的顺序为:位置形参,星号元组形参,命名关键字参数,双星号字典形参

示例:

def fn(a, b, *args, c, d, **kwargs):
   pass
​
fn(100, 200, 300, 400, c='C', e='E', d='D')

局部变量和全局变量

  • 局部变量

    • 定义在函数内部的变量称为局部变量(函数的形参也是局部变量)

    • 局部变量只能在函数的内部使用

    • 局部变量在函数调用时才能够被创建,在函数调用之后会自动销毁

  • 全局变量

    • 定义在函数外部,模块内部的变量称为全局变量

    • 全局变量, 所有的函数都可以直接访问(取值,但函数内部不能直接将其赋值改变)

  • 局部变量示例

>>> def fn(a, b):
...     c= 100
...     print(a, b, c)    # a, b, c三个都是局部变量
>>> fn(1, 2)
>>> print(a, b, c)   # 报错, 因为a,b,c 在调用后就销毁了
  • 全局变量示例

a = 100  # 全局变量
def fx(b, c):   # b,c 局部变量
   d = 400     # d 局部变量
   print(a, b, c, d)
fx(200, 300)
print(a)  # 100
print(b)  # 报错, 因为此时 b 不存在了

全局变量示例2

a = 100  # 全局变量
def fx(b):
   a = 666  # 创建局部变量,不是改变全局变量
   c = 300
   print(a, b, c)  # 优先访问局部变量
   
fx(200)  # 666 200 300
print(a)  # 100
​

global 语句

  • 问题

# 如何用一个变量来记录一个函数调用的次数
count = 0
​
def hello(name):
   print('hello', name)
   count += 1  #  等同于 count = count + 1  # 如何让 此语句能改变全局变量而不是创建局部变量
​
hello('小张')
hello('小李')
​
print('您共调用hello函数', count, '次')  # 2 次
  • 作用

    告诉python 的解释执行器, global 语句声明的一个或多个变量, 这些变量是全局变量

  • 语法

    global 变量名1, 变量名2, ....

示例

# 如何用一个变量来记录一个函数调用的次数
count = 0
​
def hello(name):
   global count  # 声明 global 是全局变量
   print('hello', name)
   count += 1  #  等同于 count = count + 1
​
hello('小张')
hello('小李')
hello('小魏')
​
print('您共调用hello函数', count, '次')  # 3 次

global 说明

  • 全局变量如果要在函数内部被赋值,则必须经过全局声明 global

  • 默认全局变量在函数内部可以使用,但只能取值,不能赋值

  • 不能先声明为局部变量,再用 global 声明为全局变量,此做法不符合语法规则

  • 函数的形参已经时局部变量,不能用 global 声明为全局变量

错误示例

  a = 100
 b = 200
 def fa(a):
     b = 20  # SyntaxError: name 'b' is assigned to before global declaration
     global b
     b = 222

lambda 表达式(又称匿名函数)

  • 语法

    lambda  [函数的参数列表]: 表达式

  • 作用

    • 创建一个匿名函数对象

    • 同 def 类似,但不提供函数名

  • 说明

    lambda 表达式 的创建函数只能包含一个表达式

  • 示例

    def myadd(x, y):
       return x + y
    ​
    print('1 + 2 =', myadd(1, 2))  # 3
    ​
    # myadd 函数可以改写成
    myadd2 = lambda x, y: x + y
    print('3 + 4 =', myadd2(3, 4))  # 7
  • 示例2

    >>> mymul = lambda a, b, c: a * b + c
    >>>
    >>> mymul(3, 4, 5)
    17
    >>> def mymul2(a, b, c):
    ...     return a * b + c
    ...
    >>> mymul2(3, 4, 5)
    17
    ​

id(x) 函数

  • 作用

    返回一个对象在内存中的地址

  • 示例

>>> L = list(range(10))
>>> id(L)
140416266741832
>>> L2 = list(range(10))
>>> id(L2)
140416266741896
>>> L
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L2
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> L is L2
False

is / is not 运算符

  • is 作用

    判断两个对象的id ,如果为同一个地址,返回True, 否则返回False

    is not 返回值与 is 相反

  • 示例

>>> weimingze = "小眀"
>>> weilaoshi = weimingze    # 两个变量同时绑定同一个字符串"魏明择"
>>> 
>>> weilaoshi is weimingze  # id(weilaoshi) == id(weimingze) 返回True
True
>>> laowei = "我是" + "小明"  # 创建一个新的字符串"我是小明"
>>> 
>>> weimingze is laowei  # id(weiweimingze) == id(laowei)  # 返回False
False

None 对象

python 内部只有一个None 对象

通常判断一个变量是否绑定None,用 is 运算符(很少用 == 运算符)

函数式编程

用一系列函数来解决问题

求 1 + 2 + 3 + 4 + ..... 99 + 100 的和
# 用函数式编程
print(sum(range(1, 101)))

python 中的常用高阶函数

高阶函数是指,函数的参数可以传入函数

>>> def fb(a, b):
...      print(a)
...      print(b)
...      print(b(a))  # b([1, 2, 3, 4])  # 等用于 sum([1, 2, 3, 4])
...
>>> fb([1, 2, 3, 4], sum)
[1, 2, 3, 4]
<built-in function sum>
10

python 中常用的函数

  • map 函数

  • filter 函数

  • sorted 函数

函数说明
map(func, 可迭代对象1, ...)返回一个可迭代对象, 此可迭代对象的每个数据用函数func 处理后返回
filter(func, 可迭代对象)返回一个可迭代对象, 此可迭代对象的数据用func 函数进行筛选后过滤
sorted(可迭代对象, key=None,reverse=False)返回一个列表, 所有的可迭代对象用key 的返回值进行排序

map函数

>>> def power2(x):
...     return x ** 2
... 
>>> L = [8, 5, 1, 3]  # 求出 列表内 平方并打印
>>> for x in map(power2, L):   # 把 power2  函数和 列表 L 交给 map 函数
...     print(x)
... 
64
25
1
9

filter 函数

>>> def is_odd(x):
...      return x % 2 == 1
... 
>>> is_odd(3)
True
>>> is_odd(10)
False
>>> L = [8, 5, 2, 1, 8, 6, 9, 7]
>>> # 把列表里所有的奇数取出来
>>> L2 = list(filter(is_odd, L))
>>> L2
[5, 1, 9, 7]

sorted 函数

>>> L = [5, -2, 4, -3, 1]
>>> sorted(L)  # 默认是升序排序
[-3, -2, 1, 4, 5]
>>> sorted(L, reverse=True)  #  降序排序
[5, 4, 1, -2, -3]
>>> abs(-2)  # abs 用来返回一个 数的绝对值
2
>>> abs(2) 
2
>>> sorted(L, key=abs)  # [1, -2, -3, 4, 5]  # 用每个数据 abs 的返回值作为排序依据进行排序
[1, -2, -3, 4, 5]

模块

一个.py 文件就是一个模块

模块是含有一些列数据,函数,类等的程序

  • 作用

    把相关功能的函数等放在一起有利于管理,有利于多人合作开发

  • 模块的分类

    模块名如果要给别的程序导入,则模块名必须是 标识符

    1. 内置模块(在python3 程序内部,可以直接使用)

    2. 标准库模块(在python3 安装完后就可以使用的 )

    3. 第三方模块(需要下载安装后才能使用)

    4. 自定义模块(用户自己编写)

          模块名如果要给别的程序导入,则模块名必须是 标识符

  • 实例

# file: mymod.py
'''
小张写了一个模块,内部有两个函数,两个字符串
... 此处省略 200字
'''

name1 = 'audi'
name2 = 'tesla'

def mysum(n):
    '''
    此函数用来求和
    by weimingze
    '''
    print("正在计算, 1 + 2 + 3 + .... + n的和 ")


def get_name():
    return "tarena"

调用模块

# file: test_mod.py
# 小李写的程序,小李想调用 小张写的 mymod.py 里的两个函数和两个字符串

# 用import 语句导入模块
import mymod

print(mymod.name1)  # Audi
print(mymod.name2)    # tesla

mymod.mysum(100)  # 调用 mymod 模块里的 mysum 函数
print(mymod.get_name())   # 'tarena'

import 语句

导入

  • 语法

import 模块名  [as 模块新名字1]

导入一个模块到当前程序

from 模块名 import 模块属性名 [as 属性新名]

导入一个模块内部的部分属性到当前程序

from 模块名 import *

导入一个模块内部的全部属性到当前程序

示例

import mymod
mymod.mysum(10)   # 要加模块名
​
from mymod import get_name
print(get_name())   # 调用get_name 时不需要加 "模块名."
​
from mymod import *  
print(get_name())
print(name2)
  • 模块的内部属性
__file__  绑定 模块的路径
__name__  绑定模块的名称
      如果是主模块(首先启动的模块)则绑定 '__main__'
      如果不是主模块则 绑定 xxx.py 中的 xxx 这个模块名

python 的第三方模块

PyPI · The Python Package IndexThe Python Package Index (PyPI) is a repository of software for the Python programming language.https://pypi.org/

random 模块

生成随机数

文档位置: https://docs.python.org/zh-cn/3/library/random.html

>>> import random
>>> random.randint(1, 6)  # random.randint(a,b) 生产 a~b的随机整数
3
>>> random.randint(1, 6)
4
>>> random.random()   # random.random  生成包含0 但不包含1 的浮点数
0.5884109388439075
>>> random.choice("ABCD")    # 从一个序列中,随机返回一个元素
'C'
>>> random.choice("ABCD")
'B'
>>> L = [1, 2, 3, 6, 9]
>>> random.choice(L)
6
>>> random.shuffle(L)   # random.shuffer(x)  # 把列表X 打乱
>>> L
[1, 6, 2, 9, 3]

time 模块

time --- 时间的访问和转换 — Python 3.9.7 文档https://docs.python.org/zh-cn/3/library/time.html

时间戳:从 1970年1月1日 0:0:0 UTC 时间 开始计时到现在的秒数

UTC 时间 : 世界协调时间

struct_time 用 含有9个元素的元组来表示时间

>>> import time
>>> time.time()   # 返回当前时间的时间戳
1617117219.0382686
>>> time.ctime()    #返回当前的UTC 时间的字符串
'Tue Mar 30 23:14:48 2021'
>>> t1 = time.localtime()   # 返回当前的本地时间元组
>>> t1
time.struct_time(tm_year=2021, tm_mon=3, tm_mday=30, tm_hour=23, tm_min=18, tm_sec=22, tm_wday=1, tm_yday=89, tm_isdst=0)
>>> t1.tm_year
2021
>>> t1.tm_yday
89
>>> time.sleep(3)  # time.sleep(n)  # 让程序睡眠 n 秒
>>> time.strftime("%Y-%m-%d", t1)   # 格式化时间
'2021-03-30'
>>> time.strftime("%y-%m-%d", t1)
'21-03-30'
>>> time.strftime('%Y-%m-%d %H:%M:%S', t1)
'2021-07-21 17:37:41'
    # 用时间元组来创建一个自定义的时间
>>> t2 = time.struct_time ( (2021,1, 1, 10, 11, 20, 0, 0, 0) )

datetime 模块

datetime --- 基本日期和时间类型 — Python 3.9.7 文档https://docs.python.org/zh-cn/3/library/datetime.html

>>> import datetime
>>> d1 = datetime.datetime.now()  # 返回当前的时间
>>> d1
datetime.datetime(2021, 3, 30, 23, 32, 7, 342559)
>>> d1.year
2021
>>> d1.year, d1.month, d1.day, d1.hour, d1.minute, d1.second, d1.microsecond  # 用 datetime 的各个属性可以得到 具体的信息
(2021, 3, 30, 23, 32, 44, 757673)
>>> d1.strftime("%Y-%m-%d")
'2021-03-30'
​
# 计算时间差
>>> delta_time = datetime.timedelta(days=2, hours=1)  # 生成 2天1小时后的时间差
>>> delta_time
datetime.timedelta(2, 3600)
>>> t1 = datetime.datetime.now()  # 得到当前时间
>>> t1
datetime.datetime(2021, 3, 30, 23, 39, 26, 863109)
>>> t1 + delta_time  # 计算 未来时间

异常

  • 用作

信号通知,通知上层调用者有错误产生需要处理

try 语句

  • 语法

try:
    可能发生异常的语句块
except 错误类型1 [as 变量名1]:
    异常处理语句块1
except 错误类型2 [as 变量名2]:
    异常处理语句块2
...
except 错误类型n [as 变量名n]:
    异常处理语句块n
except:
    异常处理语句块other
else:
    未发生异常的语句
finally:
    最终的处理语句
  • 作用

    尝试捕获异常,得到异常通知,将程序由异常状态变为正常状态

  • 说明

    except 子句可以有 1个或多个

    except: 不给错误类型,可以匹配全部的错误类型

    else 子句里的语句会在 没有错误发生时执行,当处于异常时不执行

    finally 子句里的语句,无论何时都执行

  • 示例

try:
    x = int(input("请输入一个整数:"))
    print('x=', x)
except ValueError:
    print('您的输入不能转成整数')

print("程序结束")

raise 语句

问题

# 写一个函数, get_score 函数,读取用户输入的整数成绩,
# 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间
# 报 ValueError类型的错误
def get_score():
   x = int(input('请输入成绩:'))
   if 0 <= x <= 100:
       return x
   raise ValueError

   语法

raise 异常类型
或
raise 异常对象
  • 作用

    • 抛出一个错误,让程序进入异常状态

    • 发送错误通知给调用者

  • 示例:

# 写一个函数, get_score 函数,读取用户输入的整数成绩,
# 成绩的正常值是0~100 之间, 要求, 如果不在0~100 之间
# 报 ValueError类型的错误
def get_score():
    x = int(input('请输入成绩:'))
    if 0 <= x <= 100:
        return x
    # raise ValueError
    raise ValueError('用户输入的成绩不在 0~100 之间')


try:
    score = get_score()
    print(score)
except ValueError as err:
    print("成绩输入有误 err=", err)
  •  异常类型的可选种类

详见:

>>> help(__builtins__)

 字节串 bytes 和字节数组 bytearray

1 一个字节(byte)是8个二进制的位 (bit)

1个byte的取值范围是 0 ~ 255

bytes 不可变

bytearray 可变

字节串的字面值

>>> b''
>>> b""
>>> b''''''
>>> b''''''
>>> b'ABC'
>>> bytes([65, 66, 67, 68])
>>> bytes([65, 66, 67, 68, 200,255])
>>> bytes([65, 66, 67, 68, 200,255, 300])  # 300 超出了255 报错
>>> bytearray([65, 66, 67, 68, 200,255])   # 字节数组的创建必须使用bytearray函数
  • 字节串的运算

    字节串是序列,运算规则同元组一样

    +   +=    *    *=      
    >   >=   <  <=   ==  !=
    in / not in
    索引和切片

  • 示例

    >>> b = bytes([65, 66, 67, 68, 200,255])
    >>> b
    b'ABCD\xc8\xff'
    >>> b[0]
    65
    >>> b[:2]
    b'AB'
    >>> b += b'123'
    >>> b
    b'ABCD\xc8\xff123'
    >>> len(b)
    9
    
    

  • bytes 和 str 的区别

    bytes 存储的字节 (0~255 之间的数)

    str 存储的是字符的编码

  • bytes 与 str 转换 

         编码(encode)
    str -------------> bytes
        b = s.encode(encoding='utf-8')
        
    
          解码(decode)
    bytes -----------> str
        s = b.decode(encoding='utf-8')

    示例

    >>> s = 'hello 小张'
    >>>
    >>> b = s.encode()  #  将字符串编码成为字节串
    >>> b
    b'hello \xe5\xb0\x8f\xe5\xbc\xa0'  # 在utf-8 编码中,1个汉字通常用3个字节进行编码
    >>> len(b)
    12
    >>> s2 = b.decode()  # 将字节串解码成为字符串
    >>> s2
    'hello 小张'

文件

  • 什么是文件

    文件通常用来存储以字节为单位的数据

  • 文件的操作流程

    1. 打开文件

    2. 读/写文件

    3. 关闭文件

  • 打开文件用open 函数

    open(file, mode='rt')
    # open 函数返回文件流对象
    # 打开失败回收到异常通知
    # mode 的缺省值的 'rt'
    myfile = open('/etc/passwd', 'rt')
    s = myfile.read()  # 用 myfile  绑定的文件流对象的read()  方法,得到 文件内部的数据
    print(s)
    myfile.close()  # 关闭文件
    • 示例

  • 两种操作文件的模式

    1. 直接用 字节串操作文件(内部可以存储文字,也可以存储图片等信息)

              打开模式 mode = 'b' # b是binary

      1. 用字符串操作文本文件(内部存储的都是文字)

        打开模式 mode='t' # t 是text 的首字母(默认为't')

  • 示例见

    f = open('mynote.txt', 'rt')   # 'r 代表读
    ​
    s = f.read()  # 在't' 模式下 ,read 返回字符串
    print(s)
    ​
    f.close()   # 关闭
    f = open('mynote.txt', 'rb')   # 'r' 代表读 'b' 代表以二进制方式操作
    ​
    b = f.read()  # 在't' 模式下 ,read 返回字节串
    print(b)
    ​
    s = b.decode()  # 将字节串转成了字符串
    print(s)
    f.close()   # 关闭
    1. 用字符串操作文件

    2. 用字节串操作文件

  • 文件的打开模式 mode

    模式

    说明

    't'

    以文本(字符串) 的模式操作文件(默认)

    'b'

    以二进制(字节串) 的模式操作文件

  • 文件的打开方式 mode

    方式

    说明

    'r'

    读取文件(默认)

    'w'

    写和覆盖写文件(如果文件不存在则创建文件 )

    'a'

    写并且追加文件内容(如果文件不存在则创建文件)

    python 文件流对象的方法

    方法名

    说明

    F.close()

    关闭文件

    读取文件的方法

    F.read(size=-1)

    读取文件(不给出size 参数过读取全部)

    F.readline()

    读取文件中的一行,以'\n' 作为行分隔符

    F.readlines()

    读取文件中的全部,以'\n' 作为行分隔符, 返回行的列表

    写文件的方法

    F.write(x)

    写文件: 'b'模式 x 必须是字节串, 't'模式x必须是字符串, 如果文件不存在则新建文件

mynote.txt 文件中的内容

        我是小眀
        我在 tarena

读数据

>>> f = open('mynote.txt', 'rb')
>>> f.read()  # 返回全部
b'\xe6\x88\x91\xe6\x98\xaf\xe9\xad\x8f\xe7\x9c\x80\xe6\x8b\xa9\n\xe6\x88\x91\xe5\x9c\xa8 tarena\n'
>>> f.read()  # 当到达文件尾部,返回空
b''
>>> f.close()
>>> f = open('mynote.txt', 'r')
>>> f.read()
'我是小明\n我在 tarena\n'
>>> f.close()
​
>>> f = open('mynote.txt', 'r')
>>> f.readline()  # 返回一行
'我是小眀\n'
>>> f.readline()
'我在 tarena\n'
>>> f.readline()
''
>>> f.close()
​
>>> f = open('mynote.txt', 'r')
>>> f.readlines()  # 取出所有的行数据,返回列表
['我是小眀\n', '我在 tarena\n']
>>> f.close()

​写数据

>>> f = open('python.log', 'w')  # 以字符串方式写文件, 如果文件文件不存在回新建一个文件
>>> f.write('该吃饭了')
4
>>> f.write('!')
1
>>> f.write('\n')  # 写一个换行
1
>>> f.write('下课')
2
>>> f.close()
  • 移动文件的读写指针seek 方法

    F.seek(偏移量, whence=相对位置)
           偏移量(整数)
                 大于0 向文件末尾方向
                 小于0 向文件头方向
           相对位置:
                 0 代表从文件头开始偏移
                 1 代表从当前的读写位置开始偏移
                 2 代表从文件末尾开始偏移 

    • 在读写二进制模式打开的文件,在不关闭文件的情况下, 可以使用seek 方法移动文件的读写指针

  • tell() 方法,返回文件的读写指针的位置

    F.tell()      # 返回整数
  • 示例

    mynote3.txt 的内容

                1234567890ABCDE

  • 示例程序

    myfile = open('mynote2.txt', 'rb')
    ​
    print('刚打开文件时,文件指针的位置是:', myfile.tell())  # 0
    b = myfile.read(2)
    print(b)  # b'12'
    print('读取两个字节后,文件指针的位置是:', myfile.tell())  # 2
    # 读取 67890 这个5个字节
    # myfile.seek(5, 0)   # 0 开始位置,向后移动5个字节
    # myfile.seek(3, 1)    # 1 当前位置,向后移动3个字节
    myfile.seek(-10, 2)    # 2 文件末尾位置,向前移动10个字节
    print('myfile.seek()后,文件指针的位置是:', myfile.tell())  # 5
    b = myfile.read(5)   # b'67890'
    print('myfile.read(5)后,文件指针的位置是:', myfile.tell())  # 10
    print(b)
    ​
    myfile.close()

with 语句

通过with 语句打开文件,with 语句结束,则文件会自动关闭

  • 语法

    with 表达式1 as 变量1[, 表达式2 as 变量2, ...]:
       语句块

  • 示例

    # file: mynote2.txt
    # 不用with 语句
    f = open('mynote2.txt')
    s = f.read()
    print(s)
    f.close()
    ​
    # 用with 语句
    with open('mynote2.txt') as f:
       s = f.read()
       print(s)

sys模块

Shell 的位置参数 $0 $1 $2

#! /usr/bin/python3
​
# file 04_myprog.py
import sys
print(sys.argv)   # ['./04_myprog', '/root', 'hello']

# 如下是shell 中运行的内容
$ chmod +x myprog.py
$ ./myprog /root hello   # $0='./04_myprog'  $1='/root'  $2='hello'


os 模块

  • python 上获取命令行参数

    • 对操作系统的访问大多使用 python 中的os 模块

官方文档: os --- 多种操作系统接口 — Python 3.9.7 文档

>>> import os
>>> os.getcwd()  # 返回当前的工作路径,pwd
'/root/桌面/py02/day03_code'
>>> os.mkdir('/tmp/nsd21xx')   # mkdir /tmp/nsd21xx
>>> os.makedirs('/tmp/nsd21xx/a/b/c')  # mkdir -p /tmp/nsd21xx/a/b/c
>>> os.listdir()  # ls
['mygames.py', '.idea', 'mynote.txt', 'python.log', 'mynote2.txt', '03_file_seek.py', '04_myprog.py', '05_cp.py', '01_read_text_file_by_string.py', '02_read_text_file_by_bytes.py']
>>> os.listdir('/tmp')  # ls /tmp  # 列出所有的文件夹
[ 'nsd21xx', 'dir1', 'dir2']
>>> os.chdir('/tmp/nsd21xx')  # cd  /tmp/nsd21xx
>>> os.getcwd()   # pwd
'/tmp/nsd21xx'
>>> os.symlink('/etc/passwd', '/tmp/abc')  # ln -s /etc/passwd /tmp/abc
>>> os.mknod('/tmp/myfile.txt')    # touch /tmp/myfile.txt
>>> os.chmod('/tmp/myfile.txt', 0o755)  # chmod 755 /tmp/myfile.txt
>>> os.rename('/tmp/myfile.txt', '/tmp/a.txt')  # mv /tmp/myfile.txt /tmp/a.txt
>>> os.rmdir('/tmp/dir2')   # rmdir /tmp/dir2
>>> os.remove('/tmp/a.txt')  # rm /tmp/a.txt
  • 字符串用于去掉空白字符串的方法

            空白字符是指 ' ', '\n' '\r' '\t'

>>> s = '    \n  \t hello world      \n'
>>> s.strip()      # 去掉左右两侧的空白字符
'hello world'
>>> s.lstrip()   # 去掉左侧的空白字符
'hello world      \n'
>>> s.rstrip()     # 去掉右侧的空白字符
'    \n  \t hello world'

os.path 模块

用于路径的操作的模块

>>> import os
>>> os.path.isabs('/root/abc.txt')   # 判断是否为绝对路径
True
>>> os.path.isdir('/tmp/nsd21xx')    # 判断是否是文件夹
True
>>> os.mknod('/tmp/b.txt')   # touch /tmp/b.txt
>>> os.path.isfile('/tmp/b.txt')     # 判断是否是文件
True
>>> os.path.islink('/tmp/abc')      # 判断是否是软连接?
True
>>> os.path.ismount('/home')       # 存在并且是挂载点
True
>>> os.path.exists('/root')       # 判断文件或文件夹是否存在
True
>>> os.path.basename('/tmp/nsd21xx/hello.py')  # 返回文件名
'hello.py'
>>> os.path.dirname('/tmp/nsd21xx/hello.py')  # 返回路径
'/tmp/nsd21xx'
>>> os.path.split('/tmp/nsd21xx/hello.py')  # 拆分 路径和文件名
('/tmp/nsd21xx', 'hello.py')
>>> os.path.join('/tmp/nsd21xx', 'world.py')  # 拼接路径
'/tmp/nsd21xx/world.py'

os.walk() 函数

遍历文件夹

[root@localhost tmp]# tree /tmp/nsd21xx/
/tmp/nsd21xx/
├── a
│   ├── aaa.txt
│   └── b
│       ├── bbb.txt
│       └── c
└── aa
   └── bb
       └── cc
​

示例

>>> for x in os.walk('/tmp/nsd21xx'):
...    print(x)
...
#  (路径 , 路径内的所有文件夹列表 , 路径内的所有文件列表)
('/tmp/nsd21xx', ['a', 'aa'], [])
('/tmp/nsd21xx/a', ['b'], ['aaa.txt'])
('/tmp/nsd21xx/a/b', ['c'], ['bbb.txt'])
('/tmp/nsd21xx/a/b/c', [], [])
('/tmp/nsd21xx/aa', ['bb'], [])
('/tmp/nsd21xx/aa/bb', ['cc'], [])
('/tmp/nsd21xx/aa/bb/cc', [], [])

shutil 模块

官方文档: shutil --- 高阶文件操作 — Python 3.9.7 文档

>>> import shutil
>>> f1 = open('/etc/passwd', 'rb')
>>> f2 = open('/tmp/mypass.txt', 'wb')
>>> shutil.copyfileobj(f1, f2)
>>> f1.close()
>>> f2.close()
>>>
>>> shutil.copy('/etc/passwd', '/tmp/mypass2.txt')    # cp /etc/passwd /tmp/mypass2.txt
'/tmp/mypass2.txt'
>>> shutil.copytree('/root/桌面/py02/day03_code', '/tmp/mycode')  # cp -r /root/桌面/py02/day03_code /tmp/mycode
'/tmp/mycode'
>>> shutil.move('/tmp/mypass.txt', '/tmp/nsd21xx/a.txt')  # mv /tmp/mypass.txt /tmp/nsd21xx/a.txt
>>> shutil.rmtree('/tmp/mycode')  # rm -rf /tmp/mycode
>>> shutil.chown('/tmp/mypass.txt', user='xxx', group='yyy')  # 改属主属组

生成器

生成器是在程序运行时生成数据,与容器不同,它通常不会在内存中保留大量的数据,而是现用现生成。

生成器可以用算法动态的生成数据

生成器有两种

  1. 生成器函数

  2. 生成器表达式

生成器函数

含有yield 语句的函数 是生成器函数,此函数调用回返回一个生成器对象,生成器也是可迭代对象

yield 语句的语法

yield 表达式

生成器函数示例:

# 定义一个生成器函数, 有 yield 的函数调用后回返回生成器对象
def myrange(stop):
   i = 0
   while i < stop:
       yield i    # 为 遍历次生产器的for 语句提供数据
       i += 1
​
for x in myrange(5):
   print('x=', x)

生成器表达式

  • 语法:

( 表达式 for 变量 in 可迭代对象 [if 真值表达式])

        [] 内容代表可以省略

  • 作用

    用推导式的形式创建一个生成器

  • 示例

>>> [x ** 2 for x in range(1, 5)]   # 列表解析(列表推导式)
[1, 4, 9, 16]
>>>
>>> (x ** 2 for x in range(1, 5))  # 生成器表达式
<generator object <genexpr> at 0x7f41dcd30a40>
>>> for y in (x ** 2 for x in range(1, 5)):
...     print(y)
...
1
4
9
16

生成器表达式

  • 语法:

( 表达式 for 变量 in 可迭代对象 [if 真值表达式])

[] 内容代表可以省略

  • 作用

    用推导式的形式创建一个生成器

  • 示例

>>> [x ** 2 for x in range(1, 5)]   # 列表解析(列表推导式)
[1, 4, 9, 16]
>>> (x ** 2 for x in range(1, 5))  # 生成器表达式
<generator object <genexpr> at 0x7f41dcd30a40>
>>> for y in (x ** 2 for x in range(1, 5)):
...     print(y)
...
1
4
9
16
​

面向对象编程 Object-Oriented Programming(OOP)

程序 = 数据 + 算法(操作数据的方式可方法)

  • 数据

    数字

    字符串

    容器

  • 算法

    函数

  • 模块

    数据 + 函数 + 类

函数式编程, 数据和行为(函数) 是分开的

Person1 = {
  'name': 'weimingze',
  'age': 35
}
Person2 = {
  'name': 'xiaozhang',
  'age': 18
}
def update_age(person):
   person['age'] += 1
​
update_age(Person1)
update_age(Person2)
  • 对象

    是指现实世界的物体

  • 什么是面向对象

    把一切看成对象(实例), 用各个对象的关系来描述事物

  • 对象的特征

    • 对象有很多属性(名词,形容词,...), 数据

      • 姓名, 年龄,性别....

    • 对象有很多行为(动作,动词), 方法(属于某个对象的函数)

      • 学习,吃饭, 踢球,工作

  • 拥有相同属性和行为的对象分为一组,即为一个类


     /-------> BYD  E6(京A.88888)    实例(也叫对象)
车(类)
     \-------> BWM  X5(京B.66666)    实例(也叫对象)

      /-------> 100    (对象)
int(类)
      \-------> 200    (对象)
       /---> True
bool(类)
       \---> False

int  float   dict   list   tuple   

class 语句

  • 语法

    class 类名 (继承列表):
       语句

  • 作用

    创建一个类

    类用于描述对象的行为和属性

    类可以创建一个或多个对象

  • 示例

    class Car:
       pass

构造函数

  • 调用表达式

    类名(实参)

  • 作用

    创建这个类的实例对象

  • 示例

        car1 = Car()  # 创建 第一个Car 类型的对象
        car2 = Car()  # 创建 另一个Car 类型的对象
        #
        L1 = list()   创建 第一个 list 类型的列表
        L2 = list()   创建 另一个 list 类型的列表
    
    

实例属性

每个对象可以有自己的变量,称之为实例属性

属性的使用语法

        实例.属性名

遵循变量的赋值规则

  • 示例

car1.color = '红色'   # 颜色 为 car1 创建属性 color 绑定 '红色'
car1.brand = '比亚迪'  # brand 品牌
car1.plate = '京A.88888'  # 牌照
​
car2.color = '白色'
car2.brand = '宝马'
car2.plate = '京B.66666'

删除属性用 del 语句

# 如
del car1.color

实例方法(instance method)

  • 定义的语法

    class 类名[继承列表]:
       def 实例方法名(self, 形参名1, 形参名2, 形参名3, ....):
           语句块

  • 作用

    用于描述一个对象的行为,让此类型的全部对象都有相同的行为

  • 说明

    实例方法的实质是一个函数,他是定义在类内的函数

    实例方法至少有一个形参,第一个形参绑定调用这个方法的实例,一般命名为 self

  • 调用语法

    实例.实例方法名(实参列表)
    # 或
    类名.实例方法名(实例,实参列表)

  • 示例

    # 类的定义
    class Car:
       # 实例object方法
       def run(self, km):
           print(self.color, '的', self.brand, self.plate, '正在以', km, '公里/小时的速度行使')
    ​
    .... 此处省略了创建对象的和添加属性的代码
    ​
    # 调用方法
    car1.run(110)
    car2.run(180)
    # 方法2
    # Car.run(car1, 120)
    # Car.run(car2, 160)

初始化方法(也叫构造器方法)

  • 作用

    对新创建的对象添加属性

  • 语法格式

    class 类名:
       def __init__(self [,形参列表]):
           语句块
  • 说明

    1. 初始化方法名 必须为 __init__

    2. 初始化方法会在类创建实例时自动调用,且将实例对象通过第一个参数传入 __init__方法

    3. 构造函数的实参将通过__init__的参数列表传入到__init__ 方法中

    4. 初始化方法内如果需要用return 语句返回,则必须返回None

  • 练习

# 写一个小狗类
class Dog:
   def __init__(self, ...):
       pass
   
dog1 = Dog('白色', '藏獒')
dog1.eat(1, '羊肉')   # 白色 的 藏獒 吃了 1 斤 羊肉,
dog2 = Dog('灰色', '导盲犬')
dog2.eat(2, '狗粮')   # 灰色 的 导盲犬  吃了 2 斤 狗粮,
​
dog1.eat(2, '牛肉')   # 白色 的 藏獒 吃了 2 斤 牛肉,
dog1.info()   # 白色 的 藏獒 吃过 ['羊肉', '牛肉']
dog2.info()   # 灰色 的 导盲犬 吃过 ['狗粮']

答案

# 写一个小狗类
class Dog:
   def __init__(self, color, kind):
       self.color = color
       self.kind = kind
       self.foods = []  # 用来记录吃过的食物
​
   def eat(self, weight, food):
       print(self.color, '的', self.kind, '吃了', weight, '斤', food)
       self.foods.append(food)  # 追加到 foods 列表里
​
   def info(self):
       print(self.color, '的', self.kind, '吃过', self.foods)
​
​
dog1 = Dog('白色', '藏獒')
dog1.eat(1, '羊肉')  # 白色 的 藏獒 吃了 1 斤 羊肉,
dog2 = Dog('灰色', '导盲犬')
dog2.eat(2, '狗粮')  # 灰色 的 导盲犬  吃了 2 斤 狗粮,
​
dog1.eat(2, '牛肉')  # 白色 的 藏獒 吃了 2 斤 牛肉,
dog1.info()  # 白色 的 藏獒 吃过 ['羊肉', '牛肉']
dog2.info()  # 灰色 的 导盲犬 吃过 ['狗粮']
​

继承(inheritance)和派生(derived)

继承是从已经有的类中派生出新类,新类具有父类的属性和行为,并能扩展新的能力

派生是从已经有的类中衍生出新类,在新类的基础上可以添加属性和行为

  • 作用

    1. 用继承派生机制,可以将一些共有的功能加在基类(也叫父类)中,实现代码共享

    2. 在不改变基类代码的基础上,改变原有的功能。

  • 语法

    class 类名(基类名):
       语句块
  • 示例1

    ​# 继承的示例
    # Human 类派生出 Student 类
    ​
    class Human:  # 定义一个人类
       def say(self, what):
           '说'
           print("说:", what)
    ​
       def walk(self, distance):
           '走路'
           print('走了', distance, '公里')
    ​
    ​
    class Student(Human):  # 定义一个学生了
       def study(self, subject):
           print('学习', subject)
    ​
    class Teacher(Human):
       def teach(self, language):
           print('教', language)
    ​
    h1 = Human()
    h1.say('天气真好')
    h1.walk(5)
    ​
    s1 = Student()
    s1.walk(4)
    s1.say('有点累')
    s1.study('面向对象')
    ​
    t1 = Teacher()
    t1.teach('Python')
    t1.say('今天周四')
    t1.walk(6)
  • 显式调用基类的初始化方法 super 函数

    super()  # 返回父类对象

覆盖

覆盖是指在有继承关系的类中,子类中实现了与父类中同名的方法,在子类实例调用该方法时,实际调用的是子类中的覆盖版本,这种现象叫覆盖

组合

class MyList:
   def __init__(self):
       self.data = []
   def append(self, n):
       self.data.append(n)
   def insert_head(self, n):
       self.data.insert(0, n)
L1 = MyList()   # MyList 类型的对象中包含一个 list 类型的对象,这种叫组合
L1.append(100)
L1.insert_head(0)

继承

class MyList(list):
   def insert_head(self, n):
       self.insert(0, n)
​
L1 = MyList()   # MyList 类型的对象中包含一个 list 类型的对象,这种叫组合
L1.append(100)
L1.insert_head(0)
print(L1)

多继承

多继承是指一个子类由两个或两个以上的父类(基类)

  • 语法

class 类名(基类1,基类2, ...):
    语句块
  • 示例

class Plane:
   def fly(self, height):
       print("飞机以海拔", height,'米的高度飞行')
       
class Car:
   def run(self, speed):
       print("汽车以", speed, '公里/小时的速度行驶')
       
class PlaneCar(Plane, Car):
   pass
​
pc = PlaneCar()
pc.run(120)
pc.fly(10000)

多继承可能会带来程序运行的不确定性,谨慎使用

>>> class A:
...     def m(self):
...          print('A')
...
>>> class B:
...     def m(self):
...         print("B")
...
>>> class C(A, B):
...      pass
...
>>> c = C()
>>> c.m()
A
>>> class D(B, A):
...     pass
...
>>> d = D()
>>> d.m()
B
  • 常用魔法方法, 在类定义中,很多以 双下划线开头和结尾的方法被称为魔法方法,是python 定义特殊功能的方法,

    用dir函数可以查看对象的全部方法

    >>> dir(list)
    ...

三个魔法方法

class Book:
   def __init__(self, title, author):
       '''初始化方法,在实例化时自动调用'''
       self.title = title  # 标题
       self.author = author  # 作者

   def __str__(self):                                  
       '''将对象转成字符的时候会调用'''
       return "《%s》" % self.title

   def __call__(self):
       '''将实例当成函数来调用,执行此函数内的代码'''
       print('《%s》是%s 编著的' %(self.title, self.author) )

if __name__ == '__main__':
   b1 = Book('Linux 运维之道', '丁明一')
   print(b1)
   b1()

正则表达式 (regular express)

正则表达式是表示 文字的排列规则的一个字符串, 使用来匹配文字的匹配模式.

  • 作用

    用于文字的定位,搜索和内容的提取

元字符

类别

元字符

匹配字符

. [...] [^...] \d \D \w \W \s \S

匹配重复

* + ? {n} {m,n}

匹配位置

^ $ \b \B

其他

| () \

示例

# 标识符 的正则表达式
[A-Za-z_][A-Za-z_0-9]*
#
a* -> ''    'a'     'aaaaa'
a+ -> 'a'   'aaaaaa'
[ab]+  --> 'a'    'b'    'abaaabbb'
[ab]{3}  --> 'aaa'    'bbb'   'aba'
[ab]{3,5}--> 'aaa'     'aaaaa'     'aabb'
# 匹配 .mp3 文件
'\w\.mp3$'---> 'abc.mp3'
'(\w\.mp3$)|(\w\.MP3$)'    'abc.mp3'   'abc.MP3'
'\w\.[mM][pP]3$'     'abc.mP3'  'abc.mp3'   'abc.MP3'


  • 普通字符

    'ab'   # 普通字符 只匹配'ab'
    
    >>> import re  # 导入正则表表达式模块
    >>> s = 'abcdeabca'
    >>> re.findall('ab', s)
    ['ab', 'ab']
  • 或关系

    |      匹配两侧任意的正则表达式
    
    >>> import re  # 导入正则表表达式模块
    >>> s = 'abcdeabca'
    >>> re.findall('ab|de', s)
    ['ab', 'de', 'ab']
    
    
  • 匹配单个字符串

    .       匹配除换行符 以外的任意的一个字符
    
    >>> import re
    >>> re.findall('张.丰', '张三丰,张四丰,张老师')
    ['张三丰','张四丰']
  • 匹配字符集

    [字符集]   匹配其中的一个字符
    
    >>> import re
    >>> s = 'How are you!'
    >>> re.findall('[aeiou]', s)
    ['o', 'a', 'e', 'o', 'u']
    >>> re.findall('[0-9A-Za-z]', 'A$%^^%b!#$@!#$0')
    ['A', 'b','0']
    
    
    ^    匹配目标字符的开始位置
    $    匹配目标字符的结束位置
    
    >>> re.findall('^hello', 'hello world')
    ['hello']
    >>> re.findall('^hello', 'a hello world')
    []
    >>> re.findall('world$', 'hello world')
    ['world']
    
    *    匹配前面的字符出现 0 或多次
    +    匹配前面的字符出现 1 或多次
    ?    匹配前面的字符出现 0 或1次
    
    >>> re.findall('wo*', 'wooooooo~~w! woo')
    ['wooooooo', 'woo']
    >>> re.findall('[A-Z][a-z]+', 'Hello World abcd')
    ['Hello','World']
    >>> re.findall('-?[0-9]+', 'name: Jame, age: 18, money:-100')
    ['18', '-100']
    
    {n}    # 前面的字符出现n 次
    {m,n}  # 前面的字符出现m到n次
    
    >>> re.findall('[0-9]{3}', '888 9999   1000000')
    ['888', '999', '100', '000']
    >>> re.findall('[0-9]{4,10}', '888 9999   1000000')
    ['9999', '1000000']
    
    \d  匹配任意的数字  [0-9]
    \D  匹配任意的非数字
    
    >>> re.findall('\d{1,5}', 'MySql: 3306, http:80')
    ['3306', '80']
    
    \w       匹配普通字符
    \W       匹配非普通字符
            普通字符是指 数字,字母,下划线,汉字
    
    >>> re.findall('\w+', 'MySql: 3306, http:80')
    ['MySql', '3306', 'http', '80']
    
    \s      匹配空字符
    \S      匹配非空字符
       空字符是指 '\r'   '\n'   '\t'   '\v'    '\f'
    
    >>> re.findall('\w+\s+\w+', 'hello       world')
    ['hello       world']
    
    \b       表示单词的边界
    \B       表示非单词的边界
    
    >>> re.findall(r'\bis\b', 'This is a test')
    ['is']
    
    
    >>> s = '''SERVER   =   192.168.9.102
    PORT  =       80
    SERVERNAME = GAME1
    ​
    REMOTE = 188.3.69.888
    '''
    >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
    server_ip = re.findall(server_re, s)
    >>> server_re = r'SERVER\s*=\s*[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}'
    >>> server_ip = re.findall(server_re, s)
    >>> server_ip
    ['SERVER   =   192.168.9.102']
    >>> ip_list = re.findall(r'[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}', server_ip[0])
    >>> print("SERVER=", ip_list[0])
  • 模块内的 __name__ 属性

    如果 一个模块是主模块,则 __name__ 绑定 '__main__'

    如果 一个模块不是主模块,则 __name__ 绑定文件名

  • super() 函数

    • 作用

      显示的调用被覆盖的父类方法

    • 示例

      class A:
         def say_hello(self):
             print('Hello A')
      ​
      class B(A):
         def say_hello(self):
             print("hello B")
             # self.say_hello() 无限递归调用
             # 能否在此方法内调用 A类里面的 say_hello()
             # 方法1
             # A.say_hello(self)
             # 方法2  ,super() 会把self 看成是A类的对象
             super().say_hello()
      ​
      b = B()
      b.say_hello()  # hello B    Hello A    

多线程编程

一个进程可以有多个执行路径,通常可以每个执行路径分配在不同的CPU 上并行执行, 这种运行方式是多线程

文档:threading --- 基于线程的并行 — Python 3.9.7 文档

  • 问题

    如何能让下面的两个函数同时执行

import time
​
def say_hello():
   for x in range(10):
       print("hello!!!")
       time.sleep(1)
​
def say_world():
   for y in range(10):
       print('world!!!')
       time.sleep(1)
​
say_hello()
say_world()
​

使用多线程

  • 创建线程对象的方法

import threading
# 用threading 的 Thread 类来创建一个线程对象
threading.Thread(target=None, args=(), kwargs={}, *, daemon=None)

示例

import threading
import time
​
def say_hello():
   for x in range(10):
       print("hello!!!")
       time.sleep(1)
​
# 用threading 的 Thread 类来创建一个线程对象 用 t 变量绑定
t = threading.Thread(target=say_hello)
  • 启动线程

    用 Thread对象的start() 方法来启动线程,让 线程中 target 绑定的函数,异步执行

    t.start()
  • 完整示例

import threading  # 导入多线程模块
import time
​
def say_hello():
   for x in range(10):
       print("hello!!!")
       time.sleep(1)
​
def say_world():
   for y in range(10):
       print('world!!!')
       time.sleep(1)
​
if __name__ == '__main__':
   # 用多线程来并行
   # 1. 创建一个线程,绑定 say_hello 函数
   t1 = threading.Thread(target=say_hello)
   t1.start()  # 启动 t1 线程
   t2 = threading.Thread(target=say_world)
   t2.start()
​
   print("主线程运行结束")
​
   # 串行
   # say_hello()
   # say_world()


json

json 全称( Javascript Object Notation) , 是一种轻量级的数据交互格式

json 是基于 Javascript 编程语言的格式

JSON 采用完全独立于编程语言的文本格式

标准JSON的合法符号:

        {}(大括号)  

        "(双引号)

        :(冒号)

        ,(逗号)

        [ ](中括号)

Json 的数据类型

        对象 object {}

        数组 array  []

        字符串 string  ""

        数值 number (整数和浮点数)

        布尔值 bool  (true/false)

        空值: null

        字典中的两个人

[
   {
       'name': 'weimingze',
       'age': 35
   },
   {
       'name': '小王',
       'age': 18,
       'score': [90, 100, 85]
   },
]

JSON中的两个人

[    
   {
       "name": "weimingze",
       "age": 35
   },
   {
       "name": "小王",
       "age": 18,
       "score": [90, 100, 85]
   },
]

json 和 Python 的类型和值

Python    Json
dict      {}object(对象)
list, tuple    []array数组
str        "" string 字符串
int, float    number 数字
True/False    true/false
None        null

json 模块

内建模块

import json

json模块的四个常用函数

函数    说明
json.dump(obj, fw)    把python 对象编码为json 字符串并写入文件fw中
json.dumps(obj)    把python 对象编码为json 字符串并返回
json.load(fr)    从文件流对象fr中读取json数据解码后返回python对象
json.loads(json)    从json 字符串中解码Python 对象

示例见:

>>> infos = [
   {
       'name': 'weimingze',
       'age': 35,
       'gender': True,
       'score': None
   },
   {
       'name': '小王',
       'age': 18,
       'score': [90, 100, 85]
   },
]
>>> infos
[{'name': 'weimingze', 'age': 35, 'gender': True, 'score': None}, {'name': '小王', 'age': 18, 'score': [90, 100, 85]}]
>>>
>>> import json
>>> s = json.dumps(infos)  # 将infos 绑定的对象转为json 的字符串
>>> s
'[{"name": "weimingze", "age": 35, "gender": true, "score": null}, {"name": "\\u5c0f\\u738b", "age": 18, "score": [90, 100, 85]}]'
>>> objs = json.loads(s)  # 将 json 的字符串,转为 python 的对象
>>> objs
[{'name': 'weimingze', 'age': 35, 'gender': True, 'score': None}, {'name': '小王', 'age': 18, 'score': [90, 100, 85]}]
>>> type(objs)
<class 'list'>

API

Application Programming Interface 应用程序接口。在Web中,API 通常指HTTP协议的接口

示例

中国天气网查询天气情况的 API: http://www.weather.com.cn/data/sk/城市代码.html

城市代码:

http://www.weather.com.cn/data/sk/101010100.html
# 城市代码码表
https://blog.csdn.net/wangqjpp/article/details/39957091

requests 模块

作用

发送HTTP 协议的请求,得到服务器响应的数据

模拟浏览器的行为

安装方法:

pip3 install requests

HTTP  协议的请求方式:

        GET 请求

                        相当于查看 ,get请求可以获取网站的数据,请求参数通常跟在URL 的后面

        POST请求

                        原意是创建或者添加, post请求通常用于提交表单或上传文件等

https://www.baidu.com/s?ie=utf-8&f=3&rsv_bp=1&rsv_idx=1&tn=baidu&wd=%E9%AA%B0%E5%AD%90&fenlei=256&rsv_pq=854e3d6f00038104&rsv_t=920aUYsotvE%2BTTV%2B4%2Fpf%2Fv1geYxMZTZFzMYCH5Fw%2Bg%2FZaWsk5SmRve30MRQ&rqlang=cn&rsv_enter=1&rsv_dl=ih_2&rsv_sug3=1&rsv_sug1=1&rsv_sug7=001&rsv_sug2=1&rsv_btype=i&rsp=2&rsv_sug9=es_2_1&inputT=7546&rsv_sug4=8033&rsv_sug=9

示例

使用request模块获取网页数据

>>> import requests
# 向 https://www.baidu.com/s?wd=weimingze 发送GET请求得到响应
>>> r = requests.get('https://www.baidu.com/s?wd=weimingze')
>>> r.text  # 得到响应内容的文本信息
'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'
>>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg')
>>> r.content  # 响应的字节串

​​使用request模块下载文件

>>> import requests
>>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg')
>>> r.content  # 响应的字节串
# 下载图片
>>> r = requests.get('http://photo.qc188.com/upload/20197/31/24820/l_1_20190731145347532.jpg')
>>>
>>> with open('benz.jpg', 'wb') as fw:
...      fw.write(r.content)  # 将 响应的内容(bytes) 写入文件
...
155157

​用request模块获取 中国天气网的json 数据

>>> import requests
>>> url = 'http://www.weather.com.cn/data/sk/101010100.html'
>>> r = requests.get(url)
>>> r.content  # 返回字节串
b'{"weatherinfo":{"city":"\xe5\x8c\x97\xe4\xba\xac","cityid":"101010100","temp":"27.9","WD":"\xe5\x8d\x97\xe9\xa3\x8e","WS":"\xe5\xb0\x8f\xe4\xba\x8e3\xe7\xba\xa7","SD":"28%","AP":"1002hPa","njd":"\xe6\x9a\x82\xe6\x97\xa0\xe5\xae\x9e\xe5\x86\xb5","WSE":"<3","time":"17:55","sm":"2.1","isRadar":"1","Radar":"JC_RADAR_AZ9010_JB"}}'
>>> r.json()  # 将字节串,转化为python 的对象,相当于 json.loads(r.content.decode())
{'weatherinfo': {'city': 'å\x8c\x97京', 'cityid': '101010100', 'temp': '27.9', 'WD': 'å\x8d\x97é£\x8e', 'WS': 'å°\x8fäº\x8e3级', 'SD': '28%', 'AP': '1002hPa', 'njd': 'æ\x9a\x82æ\x97\xa0å®\x9eå\x86µ', 'WSE': '<3', 'time': '17:55', 'sm': '2.1', 'isRadar': '1', 'Radar': 'JC_RADAR_AZ9010_JB'}}
>>> r.encoding  # 查看当前的字符编码
'ISO-8859-1'
>>> r.encoding = 'utf8' # 将编码改为 UTF-8
>>> r.json()
{'weatherinfo': {'city': '北京', 'cityid': '101010100', 'temp': '27.9', 'WD': '南风', 'WS': '小于3级', 'SD': '28%', 'AP': '1002hPa', 'njd': '暂无实况', 'WSE': '<3', 'time': '17:55', 'sm': '2.1', 'isRadar': '1', 'Radar': 'JC_RADAR_AZ9010_JB'}}

requests.get ()为连接添加查询字符串使用params 字典完成

i

mport requests
​
url = 'https://www.sogou.com/web'
# https://www.sogou.com/web?query=linux
s = input('请输入查询的内容:')
params = {'query': s}
r = requests.get(url, params=params)  # 发出get请求,传入 ?query=s 查询字符串
    # 相当于请求:https://www.sogou.com/web?query=linux
with open('sogou_' + s + '.html', 'wb') as fw:
    fw.write(r.content)   # 把 r.content 字节串写入文件
​
​
# https://www.sogou.com/web?query=linux
s = input('请输入查询的内容:')
params = {'query': s}
r = requests.get(url, params=params)  # 发出get请求,传入 ?query=s 查询字符串
    # 相当于请求:https://www.sogou.com/web?query=linux
with open('sogou_' + s + '.html', 'wb') as fw:
    fw.write(r.content)   # 把 r.content 字节串写入文件

request 可以通过 headers 传递请求头

url = 'https://www.sogou.com/web'
params = {'query': 'linux'}
headers = {
    'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
}   # 带上 'User-Agent' 请求头,把自己伪装成浏览者
r = requests.get(url, params=params, headers=headers)
r.text  # 返回网页的内容

完整代码:

import requests
​
url = 'https://www.sogou.com/web'
# https://www.sogou.com/web?query=linux
s = input('请输入查询的内容:')
params = {'query': s}
headers = {
    'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.114 Safari/537.36'
}   # 带上 'User-Agent' 请求头,把自己伪装成浏览者
​
r = requests.get(url, params=params, headers=headers)  # 发出get请求,传入 ?query=s 查询字符串
    # 相当于请求:https://www.sogou.com/web?query=linux
with open('sogou_' + s + '.html', 'wb') as fw:
    fw.write(r.content)   # 把 r.content 字节串写入文件
​
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python进阶之路》是一本非常值得推荐的Python进阶书籍。这本书由一位经验丰富的Python大牛所著,作者拥有超过20年的Python开发经验。这本书涵盖了许多Python进阶知识点,如元编程、动态属性、属性描述符、异步处理等。书中详细列举了这些高级特性的使用方法,并讲解得非常透彻。如果你想从入门迈向进阶,这本书是必备的参考资料。 另外,《Python Cookbook》也是一本非常受欢迎的Python进阶书籍。这本书总结了大量精妙的编程技巧和实用的技术,无论你是Python新手还是老手,都会从中收获很多。豆瓣评分高达9.2分,可见其受到广大读者的认可。 除了以上两本书,《Python进阶技巧》也是一本非常值得一读的进阶书籍。这本书的作者将许多代码简化成了一行,展现了Python的高级技巧。虽然有些地方可能看起来有些夸张,但它确实帮助你了解Python的特性和一些不错的功能。而且,在关键时刻,这种技巧还可以让你轻松搞定其他人需要十几行代码才能完成的任务。对于想要进阶的同学来说,这本书的阅读是非常适合的。 总而言之,《Python进阶之路》、《Python Cookbook》和《Python进阶技巧》都是非常优秀的Python进阶书籍,适合想要深入学习Python的读者。 : 引用自《Python进阶之路》 : 引用自《Python Cookbook》 : 引用自《Python进阶技巧》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值