Python从入门到进阶(十一)——进阶语法(二)

1 字符串方法

在 Python 中,用引号来表示字符串,例如 双引号 “,单引号 ',还有一个奇葩的三引号 “””,对应的三单引号 ‘’'。

所以下述代码都是在 声明 一个字符串。

name="橡皮擦"
name='橡皮擦'
name='''橡皮擦'''
  • 引号都是成对出现的,前面一个后面一个;
  • 单引号对应单引号,双引号对应双引号,三引号对应三引号;
  • 所有引号都是在英文模式下输入的,不能用中文的引号。

1.1 怎么用

tang_hu_lu = "都说冰糖葫芦儿酸" # 声明字符串
print(tang_hu_lu) # 打印输出字符串
print(tang_hu_lu[0]) # 打印字符串的第一个字符
tang_hu_lu = "都说冰糖葫芦儿酸" # 声明字符串
print(tang_hu_lu) # 打印输出字符串
print(tang_hu_lu[-1]) # 打印字符串的最后一个字符
print(tang_hu_lu[7]) # 打印字符串的最后一个字符
# 取中间的字符串
tang_hu_lu = "都说冰糖葫芦儿酸" # 声明字符串
print(tang_hu_lu) # 打印输出字符串
print(tang_hu_lu[2:4]) # 输出冰糖
print(tang_hu_lu[3:5]) # 输出糖葫

注意中括号扩展了,变成了 2 个数字,中间还有一个英文的冒号,此时一定要对比着原字符串进行学习。

- 都说冰糖葫芦儿酸
- 0 1 2 3 4 5 6 7

看好各个的位置

  • [2:4] 输出冰糖,分别对应索引 2,索引 3 位置的字符;
  • [3:5] 输出糖葫,分别对应索引 3,索引 4 位置的字符;

1.2 字符串扩展方法

my_str = "都说冰糖葫芦儿酸"
a = my_str.find("糖")
print(a) # 输出内容为 3
  1. find()方法
    查找 “糖” 这个小字符串在大字符串中的索引值。
my_str="AaBbCcDd"
new_my_str=my_str.title()
print(new_my_str) # Aabbccdd
  1. title()方法
    .title()方法表示将字符串首字母大写
my_str="AaBbCcDd"
new_my_str=my_str.upper()
print(new_my_str) # AABBCCDD

upper()方法和lower()方法
.upper()方法表示将字符串全部大写,全部小写是.lower()
字符串去除左右两端的空格

my_str="AaBbCcDd"
new_my_str=my_str.strip()
print(new_my_str)

1.3 子串搜索相关方法

  1. count()方法
    语法格式如下所示:
my_str.count(sub_str[,start[,end]])

返回字符串my_str中子串sub_str出现的次数,可以指定从开始(start)计算到结束(end)

print('abcaaabbbcccdddd').count('a')
  1. endswith()和startswith()
my_str.endswith(suffix[,start[,end]])
my_str.startswith(prefix[,start[,end]])

endswith()检查字符串my_str是否以suffix(可以是一个元组)结尾,返回布尔值的True和False.
startswith()用来判断字符串my_str是否是以prefix开头.
find(),rfind()和index(),rindex()
函数原型如下:

my_str.find(sub[,start[,end]])
my_str.rfind(sub[,start[,end]])
my_str.index(sub[,start[,end]])
my_str.rindex(sub[,start[,end]])

find()搜索字符串my_str中是否包含子串sub,包含返回sub的索引位置,否则返回“-1”
index()和find()不同点在于当找不到字串时,抛出ValueError错误.

1.4 替换相关方法

replace()

my_str.replace(old,new[,count])

将字符串中的old替换为new字符串,如果给定count,则表示只替换前count个old子串

1.5 分割和合并

split(),rsplit()和splitilines()

my_str.split(sep=None,maxsplit=-1)
my_str.rsplit(seq=None,maxsplit=-1)
my_str.splitlines([keepends=True])

split()根据sep对my_str进行分割,maxsplit用于指定分割次数
splitlines()用来分割换行符
join()

my_str.join(iterable)

将可迭代对象的元素使用字符my_str连接起来.

1.6 修剪

strip(),lstrip()和rstrip()

my_str.strip([chars])
my_str.lstrip([chars])
my_str.rstrip([chars])

分别是移除左右两边,左边,右边的字符char.默认移除空白(空格,制表符,换行符)

1.7 内置函数

my_str = " AaBbCcDd "
len_my_str = len(my_str)
print(len_my_str) # 统计到了 10个

上述代码中的 len() 就是一个 Python 内置函数,它表示统计长度,
注意看内置函数和刚才学到的方法之间的差异,len() 函数,前面并没有对象去调用它,
调用 其实也是一个编程概念,就是那个 . 符号。

统计过程,你也会注意到 " AaBbCcDd " 算上空格,恰好是 10 个 字符,所以得出空格也是字符,这个基本认知。

后续我们还会学习更多的内置函数,接下来在学习 2 个,这两个有助于提高编程效率。

第一个是 help(),该函数用来查看编程对象的帮助手册,例如下述代码

my_str=" AaBbCcDd "
help(my_str)

dir(),使用该函数可以直接把对象支持的方法全部输出

my_str=" AaBbCcDd "
print(dir(my_str))

1.8 字符串格式化

在Python中,字符串格式化有三种方式,分别为%占位符格式化,format()方法格式化,以及f-string,重点学习的是第二种和第三种方式进行格式化

answer_str = "今天的天气是: {}".format("晴")
print(answer_str)

第二个字符串中出现了一个大括号 {},然后通过 format() 函数对其进行了填充,
同理,大括号可以出现多个,也可以有名称,例如下述代码:

# 多个大括号,format() 方法中需要多个值进行填充
my_str = "小爱同学,今天天气"
answer_str = "今天上午的天气是: {},下午的天气是:{}".format("晴","多云")
print(answer_str)
# 大括号中有占位符
my_str = "小爱同学,今天天气"
answer_str = "今天上午的天气是: {shangwu},下午的天气是:{xiawu}".format(shangwu="晴",xiawu="多云")
print(answer_str)

在使用占位符的时候注意下,前后要一致,否则会出错的。

1.9 Python字符串方法

Python的字符串处理,一个朴实无华的四则运算计算器

import re
def naive_calc(code):
        # TODO(You):请在此实现简易四则运算
        code_lines = [l for l in code.split('\n') if l.strip() != '']
        for line in code_lines:
            ret = re.match("\s*(\d+)([\+\-\*\/])(\d+)\s*", line)
            left = ret.group(1)
            op = ret.group(2)
            right = ret.group(3)
            if op == '+':
                print('{}+{}={}'.format(left, right, int(left)+int(right)))
            elif op == '-':
                print('{}-{}={}'.format(left, right, int(left)-int(right)))
            elif op == '*':
                print('{}*{}={}'.format(left, right, int(left)*int(right)))
            elif op == '/' and right != '0':
                print('{}/{}={}'.format(left, right, int(left)/int(right)))
def test():
	code = '''
    1+2
    3+4
    5-3
    4*3
    10/2
    '''
    naive_calc(code)

if __name__ == '__main__':
    test()

2 lambda表达式

lambda表达式也叫做匿名函数,在定义它的时候,没有具体的名称,一般用来快速定义单行函数

fun=lambda x:x+1
print(fun(1))

查看上面的代码就会发现,使用 lambda 表达式定义了一行函数,没有函数名,后面是是函数的功能,对 x 进行 +1 操作。
稍微整理一下语法格式:

lambda [参数列表]:表达式
# 英文语法格式
lambda [arg1,[,arg2,arg3....argN]]:expression

语法格式中有一些注意事项:

  1. lambda表达式必须使用lambda关键字定义
  2. lambda关键字后面,冒号前面是参数列表,参数数量可以从0到任意个数.多个参数用逗号分隔,冒号右边是lambda表达式的返回值
    本文开始的代码,如果你希望进行改写成一般函数形式,对应如下:
fun=lambda x:x+1
# 改写为函数形式如下:
def fun(x):return x+1

当然,如果你决定上述 fun() 也多余,匿名函数就不该出现这些多余的内容,你也可以写成下面这个样子,
不过代码的可读性就变低了。

print((lambda x:x+1)(1))

lambda表达式一般用于无需多次使用的函数,并且该函数使用完毕就释放了所占用的空间

2.1 怎么用

  1. lambda表达式与def定义函数的区别
    第一点:一个有函数名,另一个没有函数名
    第二点:lambda表达式:后面只能有一个表达式,多个会出现错误,也就是下面的代码是不会出现的
# 都是错误的
lambda x:x+1 x+2

由于这个原因的存在,很多人也会把lambda表达式称为单表达式函数
第三点:for语句不能用在lambda中
有的地方写成了if语句和print语句不能应用在lambda表达式中,该描述不准确,例如,下述代码就是正确的.

lambda a:1 if a>10 else 0

基本结论就是:lambda表达式只允许包含一个表达式,不能包含复杂语句,该表达式的运算结果就是函数的返回值
第四点:lambda表达式不能共享给别的程序调用
第五点:;lambda表达式能作为其他数据类型的值
例如下述代码,用lambda表达式是没有问题的.

my_list=[lambda a:a**2,lambda b:b**2]
fun=my_list[0]
print(fun(2))

2.2 lambda表达式应用场景

在具体的编码场景中,lambda表达式常见的应用如下:

  1. 将lambda表达式赋值给一个变量,然后调用这个变量
    上文涉及的写法多是改用法
fun=lambda a:a**2
print(fun(2))
  1. 将lambda表达式赋值给其他函数,从而替换其他函数功能.
    一般这种情况是为了屏蔽某些功能,例如,可以屏蔽sorted函数
sorted=lambda *args:None
x=sorted([3,2,1])
print(x)
  1. 将lambda表达式作为参数传递给其他函数
    在某些函数中,函数设置中是可以接受匿名函数的,例如下述排序代码:
my_list=[(1,2),(3,1),(4,0),(11,4)]
my_list.sort(key=lambda x:x[1])
print(my_list)

my_list变量调用sort函数,参数key赋值了一个lambda表达式,该式子表示依据列表中每个元素的第二项进行排序.

  1. 将lambda表达式应用在filter,map,reduce高阶函数中
  2. 将lambda表达式应用在函数的返回值里面
    这种技巧导致的结论就是函数的返回值也是一个函数,具体测试代码如下:
def fun(n):
	return lambda x:x+n
new_fun=fun(2)
print(new_fun)
# 输出内容:<function fun.<locals>.<lambda> at 0x00000000028A42F0>

上述代码中,lambda表达式实际是定义在某个函数内部的函数,称之为嵌套函数,或者内部函数.
对应的将包含嵌套函数的函数称之为外部函数.
内部函数能够访问外部函数的局部变量,这个特性是闭包(Closure)编程的基础

2.3 扩展知识

lambda 表达式虽然有优点,但不应过度使用 lambda,最新的官方 Python 风格指南 PEP8 建议永远不要编写下述代码:

normalize_case = lambda s: s.casefold()

因此你想创建一个函数并存储到变量中, 请使用 def 来定义。
不必要的封装

my_list=[-1,2,0,-3,1,1,2,5]
sorted_list=sorted(my_list,key=lambda n:abs(n))
print(sorted_list)

上述貌似用到了lambda表达式,但是却忘记了,在Python中所有的函数都可以当做参数传递.

my_list=[-1,2,0,-3,1,1,2,5]
sorted_list=sorted(my_list,key=abs)
print(sorted_list)

也就是当我们有一个满足要求的函数的时候,没有必要在额外的去使用lambda表达式了.

2.4 匿名表达式的使用

Python 高阶函数编程,使用 lambda 表达式获取key,将list转成dict

Python 高阶函数编程,使用 lambda 表达式获取key,将list转成dict

# -*- coding: UTF-8 -*-
def list_to_dict(list, key_func):
    d = {}
    for item in list:
        k = key_func(item)
        v = item
        list = d.get(k)
        if list is None:
            d[k] = [v]
        else:
            d[k].append(v)

    return d

if __name__ == '__main__':
    list = [
        {"name": "alice", "age": 100},
        {"name": "middle", "age": 100},
        {"name": "bob", "age": 200}
    ]
    # TODO(You): 请在此调用 list_to_dict 方法,将 list 转成dict
    print(ret)

请选出下列实现错误的选项。
# A.
ret = list_to_dict(list, lambda item: item['age'])
# B.
def get_key(item):
    return item['age']

ret = list_to_dict(list, get_key)
# C.
ret = list_to_dict(list, lambda item: 
    item['age']
)
# D.
get_key = lambda item: item['age']
ret = list_to_dict(list, get_key)
# C 错误

3 文件

3.1 绝对路径和相对路径

标题的这两个概念很有意思,在第一次学习的时候很容易就弄迷糊了。
先记住绝对路径吧,绝对就是绝对不变的意思。

例如上述文件 abc.png 它的绝对路径就是硬盘上的一个不会变的地址,即 C:\Users\Administrator\Desktop\书籍封面 就是它的绝对路径。

一般情况下理解为绝对路径是从根目录开始描述的路径。

相对路径,关键词是相对,相对就是相对与当前目录,这个需要结合案例进行学习,稍后补充。

还有两个知识点需要补充一下。. 没错,就是一个点,表示的是当前文件夹;… 两个点表示的是上一层文件夹。

3.2 怎么用

  1. os模块与os.path模块
    在Python中操作文件路径,使用os模块,os.path模块是os模块内部的一个子模块,首先导入该模块
import os
  1. 获取当前Python文件的目录
    getcwd方法可以获取当前Python文件所在的工作目录.就是当前文件在那个文件夹中,获取到的是绝对地址,例如下述代码.
import os 
print(os.getcwd())

** 获取绝对路径 os.path.abspath **
os.path模块中的abspath方法可以返回绝对路径,可以先通过help函数,查看该方法使用方式.

import os
help(os.path.abspath)

注意学习返回结果,学编程对英语要求不高,但是常见的单词还是要认识一些的。

Help on function abspath in module ntpath:

abspath(path)
    Return the absolute version of a path.

abspath 方法需要一个参数 path,即一个路径,基于该路径在返回绝对路径。

例如通过该代码返回 demo4.py 文件的绝对路径

import os
ret=os.path.abspath("demo4.py")
print(ret)

**获取相对路径 os.path.relpath **
绝对路径返回的是一个从根目录开始的路径值,但是相对路径不一样,该方法既然叫做相对,那需要有一个相对对象,所以该方法的语法格式如下:

os.path.relpath(path,start)
  • path就是要获取绝对路径的地址值,描述起来比较绕,一会看代码;
  • start相对的对象值
import os
ret=os.path.relpath("D:\\")
print(ret)

获取D:\该目录的相对地址,相对于谁的地址,没写start参数就相对于当前工作目录,即Python文件所在的目录,
先认为的推断一下 D:\ 相对于 D:/gun/2 怎么获取,应该是父级目录的父级目录,那用代码怎么表示,已经学习了父级(上一层文件夹)目录表示方式 …,所以写作 … ,整理完逻辑之后,发现跟代码得到的效果一致。

..\..

将path参数修改为跟Python文件目录一致的值,看一下是不是得到相对路径是一个.,表示当前目录

import os

ret = os.path.relpath("d:\\gun\\2")
# 或者写成下面这个样子
# ret = os.path.relpath("d:/gun/2")
print(ret)

结果输出为 . ,没错是期望值。

3.3 路径检查方法

检查路径主要是为了检查文件或者文件夹是否存在,或者判断一个路径对应的是一个文件夹还是一个文件

  • exists(path) 如果path文件或文件夹存在返回True,否则返回False.
  • isabs(path) path是绝对路径返回True,否则返回False
  • isdir(path) path是文件夹返回True
  • isfile(path) path是文件返回True
    以上四个方法都在os.path模块下,具体代码比较简单,可以尝试一下

3.4 目录操作

以下几个方法在os模块中,执行如下操作建议先通过os.path.exists判断目录是否存在

  • mkdir(path) 创建目录
  • rmdir(path) 删除目录
  • chdir(path) 切换当前工作目录到path
  • remove(path) 删除文件,注意如果path是一个目录,删除会报错,权限不足,删除目录请使用rmdir.

3.5 获取文件大小

该内容只需要调用getsize方法即可.

import os
print(os.path.getsize("demo4.py"))

注意得到的是字节大小

3.6 获取指定目录下面的所有内容

通过os.listdir方法可以获取指定目录下的所有内容,包括文件与文件夹

import os
print(os.listdir("."))

输出的内容:

['.vs', 'B', 'Jinjieyufa', 'Kzjg', 'Nxwc.py', 'PythonApplication1.py', 'PythonApplication1.pyproj', 'PythonApplication1.pyproj.user', 'PythonApplication1.sln', 'test1.py', '__pycache__']

3.7 os.walk

该方法可以遍历目录树,通过循环就可以获取到指定目录下面所有的文件与文件夹了

3.8 Python读取文件

Python 在读写文件的时候首先要做的是打开文件,然后可以一次性读取文件或者一行行的读取,打开文件使用 open 函数。

  1. 读取文件所有内容
    使用open函数打开文件之后,可以通过read读取文件内容,该方法相当于将文件的内容一次性的读取到了程序中的一个字符串中,非常强大
    OsPath.py文件内容
class OsPath(object):
    """description of class"""
    def testos(self):
        import os 
        # 获取当前Python文件所在的工作目录
        print(os.getcwd())
        # 绝对路径
        help(os.path.abspath)
        ret=os.path.abspath("Lbtds3_1.py")
        print(ret)
        # 相对路径
        ret=os.path.relpath("G:\\")
        print(ret)
        ret=os.path.relpath("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Jinjieyufa\OsPath.py")
        print(ret)
        print(os.path.exists("G:\BaiduNetdiskDownload\VS2019Space"))
        print(os.path.isabs("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Lbtds3_1.py"))
        print(os.path.isdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Lbtds3_1.py"))
        if os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo")==False:
            os.mkdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo") 
        if os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo"):
            os.rmdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo")
        print(os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo"))
        print(os.path.getsize("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Jinjieyufa\OsPath.py"))
        print(os.listdir("."))
        
        pass

if __name__=='__main__':
    ostest=OsPath()
    ostest.testos()

读取代码如下:

# 文件地址
file = "Jinjieyufa\OsPath.py"
# 打开文件
f = open(file, encoding="utf-8")
# 读取文件全部内容
read_str = f.read()
# 关闭文件
f.close()
print(read_str)

第一点需要注意的是使用 open 打开文件时,必须在文件使用完毕之后通过 close 关闭文件。
第二点需要注意,上述代码中 file = “OsPath.py” 该文件名并不是一个完整的路径,这种情况下表示该文件和当前的 Python 文件在一个目录,如果在不同目录,需要用到前文讲到的路径相关知识了。

例如,在上一级目录 …/OsPath.py

上述代码如果运行出现编码 BUG,注意修改以下 open 函数部分代码,通过 encoding = “utf-8” 设置文件打开时的编码。

# 打开文件
f = open(file, encoding="utf-8")
  1. 逐行读取文件内容
    通过循环调用文件对象,可以逐行输出文件内容
# 文件名
file="Jinjieyufa\OsPath.py"
# 打开文件
f=open(file,encoding="utf-8")
# 循环逐行读取
for line in f:
	print(line)
# 关闭文件
f.close()
class OsPath(object):

    """description of class"""

    def testos(self):

        import os

        # 获取当前Python文件所在的工作目录

        print(os.getcwd())

        # 绝对路径

        help(os.path.abspath)

        ret=os.path.abspath("OsPath.py")

        print(ret)

        # 相对路径

        ret=os.path.relpath("G:\\")

        print(ret)

        ret=os.path.relpath("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Jinjieyufa\OsPath.py")

        print(ret)

        print(os.path.exists("G:\BaiduNetdiskDownload\VS2019Space"))

        print(os.path.isabs("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Lbtds3_1.py"))

        print(os.path.isdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Lbtds3_1.py"))

        if os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo")==False:

            os.mkdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo")

        if os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo"):

            os.rmdir("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo")

        print(os.path.exists("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\WenjianCaozuo"))

        print(os.path.getsize("G:\BaiduNetdiskDownload\VS2019Space\PythonApplication1\Jinjieyufa\OsPath.py"))

        print(os.listdir("."))

        # 读取文件所有内容

        file="Jinjieyufa\OsPath.py"

        f=open(file,encoding="utf-8")

        read_str=f.read()

        f.close()

        print(read_str)

        # 逐行读取文件内容

        file="Jinjieyufa\OsPath.py"

        f=open(file,encoding="utf-8")

        # 循环逐行读取

        for line in f:

            print(line)

        # 关闭文件

        f.close()

        pass



if __name__=='__main__':

    ostest=OsPath()

    ostest.testos()

在这里逐行读取多了一个换行,原因是在文件中,每行的末尾默认有一个换行,print 函数输出也会带一个换行,所以出现 2 个回车符,解决办法,可以使用 print 函数的第二个参数。

# 文件名
file = "Jinjieyufa\OsPath.py"
# 打开文件
f = open(file, encoding="utf-8")
# 循环逐行读取
for line in f:
	print(line,end="")
# 关闭文件
f.close()
  1. 逐行读取方法readlines
    使用 readlines 方法可以将数据一次性读取到一个列表中,例如下述代码。
# 文件名
file="Jinjieyufa\OsPath.py"
# 打开文件
f=open(file,encoding="utf-8")
# 逐行读取
data=f.readlines()
# 关闭文件
f.close()
print(data)

输出内容中,可以看到每行读取到的字符串都带一个 \n 换行符。

  1. with上下文
    在Python中为了防止忘记打开文件之后,在进行关闭,提供了一个with关键词解决该问题,语法格式如下:
with open(待打开文件) as 文件对象:
	文件操作代码块

有了该语法之后,前文的代码可以修改为:

file="Jinjieyufa\OsPath.py"
# 打开文件
with open(file,encoding="utf-8") as f:
	# 读取文件全部内容
	read_str=f.read()
	print(read_str)

读取文件还包含其他的几个方法,可以自行尝试.

3.9 写入文件

写入文件,泛指写入到本地硬盘上.
在学习写入文件之前,需要扩展一下open函数,该函数目前已经掌握2个参数,第一个是操作的文件,第二个是文件的编码encoding,在补充一个文件打开模式mode参数,open函数中该参数的默认值是r,代码写作open(“Jinjieyufa\OsPath.py”,mode=“r”,encoding=“utf-8”)表示以只读的方式打开文件,如果想要向文件中写入内容,需要将mode参数设置为w.
文件写内容的语法格式为:

文件对象.write(待写入内容)

具体案例代码:

# 文件地址
file="Jinjieyufa\OsPath.py"
# 打开文件
with open(file,mode="w",encoding="utf-8") as f:
	# 写入文件内容
	f.write(我是即将被写入的内容)

注意,待写入的内容需为字符串类型,其他类型写入会报错.该种方式写入内容之后,原内容会被覆盖,如果想要在文件中追加数据,用到的是mode=a

  1. 写入多行数据
    通过 write 方法可以写入单行数据,如果想要写入多行数据,可以在 with 代码块中,写上多个 write 方法即可。注意 write 方法默认在行尾不添加换行符,如果希望加上换行符,需手动添加。

例如下述代码:

file="test.txt"
# 打开文件
with open(file,mode="w",encoding="utf-8") as f:
	# 写入文件内容
	f.write("让我看看\n")
	f.write("是哪个萌新在提问\n")
	f.write("wc\n")
	f.write("是大氵怪")

4 文件复制

使用该模块中shutil对象的copy方法可以对文件进行复制操作.

shutil.copy(旧文件,新文件)

书写成真实代码如下:

import shutil
shutil.copy("test.txt","aaa.txt")
shutil.copy("test.txt","../aaa.txt") # 不同目录拷贝

5 目录复制

copytree方法格式与copy一致,只不过该方法是用来复制目录的,如果目录下面有子目录或文件一起复制

import shutil
# 第一个参数是旧目录,第二个参数是新目录
shutil.copytree("../1","a4")

执行代码时,需要确定新目录不存在,如果存在会报错

6 多用的move方法

使用move方法可以移动文件

shutil.move(旧文件,新文件)

移动文件一定要确保旧文件存在,移动之后旧文件将移动到新文件位置
使用move方法可以修改文件名,在移动文件的过程中,如果新旧文件名称不一致,可实现移动文件并重命名的效果.
使用move方法还可以移动目录,移动目录时会将该目录下的所有文件一起移动,当然如果新旧目录名称不一致,还可以实现移动目录并重命名的效果

7 删除有数据的目录

使用rmtree可以删除有数据的目录,相当于直接清空该目录下的所有目录和文件,再顺便把该目录也删除了.具体内容自行测试即可.

8 Python文件读写

  1. 基本文件读写,写入“test”到“/tmp/test.txt”,再次打开读取
    请选出下列能正确实现这一功能的选项.
    请在以下选项中选择
# A.
if __name__ == '__main__':
    f = open('/tmp/test.txt', 'w'):
    f.write("test")
        
    f = open('/tmp/test.txt', 'r'):
    print(f.read())
# B.
if __name__ == '__main__':
    with open('/tmp/test.txt', 'r') as f:
        f.write("test")

    with open('/tmp/test.txt', 'w') as f:
        print(f.read())
# C.
if __name__ == '__main__':
    with open('/tmp/test.txt', 'w') as f:
        f.write("test")
    with open('/tmp/test.txt', 'r') as f:
        print(f.read())
# D.
if __name__ == '__main__':
    with open('/tmp/test.txt', 'r') as f:
        f.write("test")

    with open('/tmp/test.txt', 'r') as f:
        print(f.read())
# C 正确
  1. 一种基于sha256的文件分片hash计算方式
一种基于 sha256 的文件分片 hash 计算方式

# -*- coding: UTF-8 -*-
import hashlib

def file_piece_sha256(in_file_path, piece_size):
    sha256 = hashlib.sha256()
    with open(in_file_path, "rb") as in_file:
        # TODO(You): 请在此实现 hash 计算
    return sha256.digest().hex()

if __name__ == '__main__':
    ret = file_piece_sha256('file_piece_sha256.py', 128)
    print("file hash is: ", ret)

# 请选出下列能正确实现TODO功能的选项。
# A.
while True:
    piece = in_file.readline(piece_size)
    if piece:
        sha256.update(piece.hex().encode('utf-8'))
    else:
        continue
# B.
while True:
    piece = in_file.read(piece_size)
    if piece:
        sha256.append(piece.encode('utf-8'))
    else:
        continue
# C.
while True:
    piece = in_file.read(piece_size)
    if piece:
        sha256.update(piece.hex().encode('utf-8'))
    else:
        continue
# D.
while True:
    piece = in_file.read(piece_size)
    if piece:
        sha256.update(piece.hex().encode('utf-8'))
    else:
        break
# D ✔

4 Python标准库

常用标准库清单如下:

  1. sys
  2. os
  3. math
  4. random
  5. pikie
  6. subbprocess
  7. queue
  8. StringIO
  9. logging
  10. json
  11. time
  12. datetiem
  13. re
  14. csv
  15. threading
  16. asyncio

4.1 怎么用

  1. sys
    用于处理Python解析器相关的变量和方法,例如获取命令行参数,退出Python程序,获取输入输出相关内容
  2. os
    系统模块,提供用于访问操作系统的相关功能,os模块中的接口有些是特定平台使用的
  • 系统相关API
  • 目录和文件操作
  • 执行命令
  • 管理进程
  1. math
    数学函数,常用的有ceil(),floor(),abs(),sin()等方法.
  2. random
    用于生成伪随机数
  3. pikle
    用于数据持久化,该模块持久化的数据无法直接读取,并且仅能在Python代码中读取
  4. subprocess
    主要用于进程操作,可以使用它执行操作系统级别的命令,优先掌握run()方法,使用其创建子进程,操作系统命令.
  5. queue
    队列模块,用于将数据存放在内存中,并进行数据交换.
  6. StringIO
    可以将字符串存储在内存中,然后像操作文件一样操作
  7. logging
    日志模块
  8. json
    操作JSON格式数据的模块
    我们可以使用json模块来进行JSON的序列化和反序列化。

序列化后的JSON字符串和Python字符串对比:

Python
import json
data={'name':'Alice','age':25,'gender':'female'}
json_str=json.dumps(data)
print(json_str)

在上述示例中,使用json.dumps()函数将Python字典对象data序列化为JSON字符串。序列化后的JSON字符串将包含字典的键值对,如下所示:

json
{'name':'Alice','age':25,'gender':'female'}

JSON反序列化为Python

Python

import json
json_str='{'name':'Alice','age':25,'gender':'female'}'
data=json.loads(json_str)
print(data)

在上述示例中,使用json.loads()函数将JSON字符串json_str反序列化为Python对象。反序列化后的Python对象将包含与JSON字符串相同的键值对,如下所示:

Python
{'name':'Alice','age':25,'gender':'female'}
# dumps、dump 用于把Python转为JSON的序列化,
json.dumps #用于字符串
json.dump #用于文件流
 
# loads、load 用于把JSON转为Python的反序列化
json.loads #用于字符串
json.load #用于文件流
  1. time和datetime
    时间模块,目前支持到2038年,超过这个时间,使用datetime模块
  2. re
    正则表达式处理模块
  3. csv
    csv文件操作模块
  4. threading
    多线程模块
  5. asyncio
    异步I/O模块
  6. time,datetime时间模块,calendar日历模块,实战举例
    在Python中是没有原生数据类型支持时间的,日期与时间的操作需要借助三个模块,分别是time,datetime,calendar
    time模块可以操作C语言库中的时间相关函数,时钟时间与处理器运行时间都可以获取
    datetime模块提供了日期与时间的高级接口
    calendar模块为通用日历相关函数,用于创建数周,数月,数年的周期性事件
    epoch(纪元)是时间开始的点,其值取决于平台
    对于Unix,epoch(纪元)是1970年1月1日00:00:00(UTC),要找出给定平台上的epoch,请使用time.gmtime(0)进行查看
    纪元秒数是指纪元时间点以来经过的总秒数,称为时间戳
  7. get_clock_info函数
    该函数获取时钟的基本信息,得到的值因不同系统存在差异,函数原型比较简单:
time.get_clock_info(name)

其中name可以取下述值:

  • monotonic:time.monotonic()
  • perf_counter:time.perf_counter()
  • process_time:time.process_time()
  • thread_time:time.thread_time()
  • time:time.time()

该函数的返回值具有以下属性:

  • adjustable:返回True或者False,如果时钟可以自动更改(例如通过NTP守护程序)或由系统管理员手动更改,则为True,否则为False
  • implementation:用于获取时钟值得基础C函数得名称,就是调用底层C的函数
  • monotonic: 如果时钟不能倒退,则为True,否则为False
  • resolution: 以秒为单位的时钟分辨率(float)
def testget_clock_info(self):
        

        available_clocks=[
            ('monotonic',time.monotonic()),
            ('perf_counter',time.perf_counter()),
            ('process_time',time.process_time()),
            ('time',time.time())
            ]
        for clock_name,func in available_clocks:
            print('''
            {name}:
                adjustable:{info.adjustable}
                implementation:{info.implementation}
                monotonic:{info.monotonic}
                resolution:{info.resolution}
                current:{current}
            '''.format(name=clock_name,
                       info=time.get_clock_info(clock_name),
                       current=func))
        pass
  1. 获取时间戳
    在Python中通过time.time()函数获取纪元秒数,它可以把epoch开始之后的秒数以浮点数格式返回
import time
print(time.time)
# 输出结果是:1695197312.6042597

时间戳大量用于计算时间相关程序,属于必须掌握内容
19. 获取可读时间
时间戳主要用于时间上的计算方便,对于人们阅读是比较难以理解的,如果希望获取可读时间,使用ctime()函数获取

import time
print(time.ctime())
# 输出内容: Tue Mar 9 10:35:51 2021

如何将时间戳转换为可读时间,使用localtime函数即可

localtime=time.localtime(time.time())
print("本地时间为:",localtime)

输出结果为<class ‘time.struct_time’>类型数据,后文将对其进行格式化处理:

time.struct_time(tm_year=2023, tm_mon=9, tm_mday=20, tm_hour=16, tm_min=18, tm_sec=39, tm_wday=2, tm_yday=263, tm_isdst=0)
  1. 单调时间 montonic time
    monotonic time 从系统启动开始计时,从 0 开始单调递增。

操作系统的时间可能不是从 0 开始,而且会因为时间出错而回调。

该函数原型如下,不需要任何参数,返回一个浮点数,表示小数秒内的单调时钟的值:

time.monotonic()

测试代码如下:

print("单调时间",time.monotonic())
# 输出:单调时间 12279.244
  1. 处理器时钟时间
    time()函数返回的是纪元秒数(时间戳),clock()函数返回的是处理器时钟时间.
    该函数的返回值:
  • 在第一次调用的时候,返回的是程序运行的实际时间
  • 在第二次之后的调用,返回的是自第一次调用后到这次调用的时间间隔
    需要注意的是Python3.8已移除clock()函数,用time.perf_counter()或time.process_time()方法替代.
t0 = time.clock()
# 运行一段代码
print(time.clock() - t0, "程序运行时间")

版本较高会提示异常

  1. 性能计数器 time.perf_counter
    perf_counter()函数的epoch(纪元)是未定义的.一般使用该函数都是为了比较和计算,不是为了用作绝对时间,该点需要注意下
    该函数用于测量较短持续时间的具有最高有效精度的时钟,包括睡眠状态消耗的时间,使用两次调用才会有效
    测试代码如下
t0=time.perf_counter()
for i in range(100000):
	pass
print("程序运行时间",time.perf_counter()-t0)

与其类似的函数有perf_counter_ns(),process_time(),process_time_ns()

  1. 时间组件
    上文已经涉及了时间组件相关的知识,通过 localtime 得到的 struct_time 类型的数据。

这里涉及到的函数有 gmtime() 返回 UTC 中的当前时间,localtime() 返回当前时区对应的时间,mktime() 接收 struce_time 类型数据并将其转换成浮点型数值,即时间戳。

print("*"*10)
print(time.gmtime())
print("*"*10)
print(time.localtime())
print("*"*10)
print(time.mktime(time.localtime()))

struct_time类型包含的内容
上述返回数据格式为:

time.struct_time(tm_year=2023, tm_mon=9, tm_mday=20, tm_hour=8, tm_min=48, tm_sec=58, tm_wday=2, tm_yday=263, tm_isdst=0)

其中各值可以根据英文含义进行理解:
tm_year 年份(range[1,12]),tm_mon 月份(range[1,12]),tm_mday 天数(range[1,31]),tm_hour 天数(range[0,23]),tm_min 分钟 (range[0,59]), tm_sec 秒数 (range[0,61]), tm_wday 星期 (range[0,6],0 是星期日), tm_yday 一年中的一天(range[1,366] ),tm_isdst 在夏令时生效时设置为 1,而在夏令时不生效时设置为 0,值-1 表示这是未知的。

  1. 解析和格式化时间

strptime()和strfttime()函数可以使时间值在struct_time表示和字符串表示之间相互转换
对于strptime函数:

x=time.strftime("%Y-%m_%d %H:%M:%S",time.localtime())
        print(x)

strptime函数的应用

x=time.strptime("%Y-%m_%d %H:%M:%S",time.localtime())
        print(x)

        struct_time=time.strptime(x,"%Y-%m-%d %H:%M:%S")
        print(struct_time)
  1. datetime模块
  • datetime:允许同时操作时间和日期

  • date:只操作日期

  • time:只操作时间

  • timedelta:用于操作日期以及测量时间跨度

  • tzinfo:处理时区

    1. date类
    • min,max:date对象表示的最大,最小日期
    • resolution: date对象表示日期的最小单位,返回天
    • today():返回表示当前本地日期的dat对象
    • fromtimestamp(timestamp):根据时间戳,返回一个date对象
      测试代码如下:
from datetime import date
import time
print('date.min:', date.min)
print('date.max:', date.max)
print('date.resolution:', date.resolution)
print('date.today():', date.today())
print('date.fromtimestamp():', date.fromtimestamp(time.time()))

输出结果:

date.min0001-01-01
date.max: 9999-12-31
date.resolution: 1 day, 0:00:00
date.today(): 2023-09-21
date.fromtimestamp(): 2023-09-21

date对象的属性和方法
通过下述代码创建一个date对象

d=date(year=2023,month=9,day=20)
print(d)

该对象具备下述属性和方法:

  • d.year:返回年;
  • d.month:返回月;
  • d.day:返回日;
  • d.weekday():返回 weekday,如果是星期一,返回 0;如果是星期 2,返回 1,以此类推;
  • d.isoweekday():返回 weekday,如果是星期一,返回 1;如果是星期 2,返回 2,以此类推;
  • d.isocalendar():返回格式如(year, wk num, wk day);
  • d.isoformat():返回格式如’YYYY-MM-DD’的字符串;
  • d.strftime(fmt):自定义格式化字符串,与 time 模块中的 strftime 类似。
  1. time类
    time类定义的类属性
  • min,max:time类所能表示的最小,最大时间.其中,time.min=time(0,0,0,0),time.max=time(23,59,59,999999);
  • resolution: 时间的最小单位,这里是1微秒
  • 通过其构造函数可以创建一个time对象
t=time(hour=20,minute=20,second=40)
print(t)

time 类提供的实例方法和属性:

  • t.hour、t.minute、t.second、t.microsecond:时、分、秒、微秒;
  • t.tzinfo:时区信息;
  • t.isoformat():返回型如”HH:MM:SS”格式的字符串时间表示;
  • t.strftime(fmt):返回自定义格式化字符串。
  1. datetime类
    该类是date与time类的结合体,很多属性和方法前文已经介绍,再补充一些比较常用的属性和方法。

获取当前的日期与时间:

from datetime import datetime
dt=datetime.now()
print(dt)

获取时间戳:

dt=datetime.now()
# 使用datetime的内置函数timestamp()
stamp=datetime.timestamp(dt)
print(stamp)
  1. timedelta类
    通过timedelta函数返回一个timedelta时间间隔对象,该函数没有必填参数,如果写入一个整数就是间隔多少天的意思
# 间隔10天
timedelta(10)
# 跨度为1周
timedelta(weeks=1)

两个时间间隔对象可以彼此之间相加或
两个时间间隔对象可以彼此之间相加或相减,返回的仍是一个时间间隔对象。
一个 datetime 对象如果减去一个时间间隔对象,那么返回的对应减去之后的 datetime 对象,然后两个 datetime 对象如果相减,返回的是一个时间间隔对象。

  1. canlendar模块(日历)
    此模块的函数都是日历相关的,例如打印某月的字符月历。

calendar 模块定义了 Calendar 类,它封装了值的计算, 例如给定月份或年份中周的日期。通过 TextCalendar 和 HTMLCalendar 类可以生成预格式化的输出。

import calendar
c=calendar.TextCalendar(calendar.SUNDAY)
c.prmonth(2023,9)

   September 2023
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

5 random随机函数模块

5.1 seed与random函数

seed函数初始化一个随机种子,默认是当前系统时间
random函数生成一个[0.0,1.0]之间的随机小数
具体代码如下:

import random
random.seed(10)
x=random.random()
print(x)

random.seed(10)
y=random.random()
print(y)

0.5714025946899135
0.5714025946899135

在不同的代码上获取到的值是不同的,但是 x 与 y 是相同的。

5.2 getstate()和setstate(state)

getstate函数用来记录随机数生成器的状态,setstate函数用来将生成器恢复到上次记录的状态.

# 记录生成器的状态
state_tuple = random.getstate()
for i in range(4):
    print(random.random())
print("*"*10)
# 传入参数后恢复之前状态
random.setstate(state_tuple)
for j in range(4):
    print(random.random())
0.4288890546751146
0.5780913011344704
0.20609823213950174
0.81332125135732
**********
0.4288890546751146
0.5780913011344704
0.20609823213950174
0.81332125135732

输出的随机数两次一致

5.3 randint和randrange

randint生成一个[x,y]区间之内的整数
randrange生成一个[m,n)区间之内以k为步长的随机整数

x = random.randint(1,10)
print(x)

y = random.randrange(1,10,2)
print(y)

这两个函数比较简单,randint 函数原型如下:

random.randint(start,stop)
参数 start 表示最小值,参数 stop 表示最大值,两头都是闭区间,也就是 start 和 stop 都能被获取到。

randrange 函数原型如下:

random.randrange(start,stop,step)
如果函数调用时只有一个参数,默认是从 0 到该参数值,该函数与 randint 区别在于,函数是左闭右开,最后一个参数是步长。
查阅效果,可以复制下述代码运行:

for i in range(3):
    print("*"*20)
    print(random.randrange(10))
    print(random.randrange(5,10))
    print(random.randrange(5,100,5))

5.4 getrandbits(k)和choice(seq)

getrandbits生成一个k比特长的随机整数,实际输出的是k位二进制数转换成的十进制数
choice从序列中随机选择一个元素

x=random.getrandbits(5)
print(x)
# 生成的长度是00000-11111

getrandbits(k) 函数可以简单描述如下:输出一个 [ 0 , 2 k − 1 ] [0,2^k-1] [0,2k−1] 范围内一个随机整数,k 表示的是 2 进制的位数。

choice 就比较简单了,从列表中返回一个随机元素。

import random
my_list=["a","b","c"]
print(random.choice(my_list))

5.5 shuffle(seq)和sample(pop,k)

shuffle函数用于将序列中的元素随机排序,并且原序列被修改
sample函数用于从序列或者集合中随机选择k个选择,原序列不变

my_list=[1,2,3,4,5,6,7,8,9]
random.shuffle(my_list)

print(my_list)

shuffle函数只能用于可变序列,不可变序列(如元组)会出现错误

my_list = ["梦想", "橡皮擦", 1, 2, [3, 4]]
print(my_list)
ls = random.sample(my_list, 4)
print(ls)

5.6 uniform(a,b),betavariate和triangular函数

uniform 生成一个 [a,b] 之间的随机小数,采用等概率分布。
betavariate 生成一个 [0,1] 之间的随机小数,采用 beta 分布。
triangular 生成一个 [low,high] 之间的随机小数,采用三角分布。

在使用 uniform 时候需要注意,如果 a>b,那么生成一个 b-a 之间的小数。

for i in range(3):
	print(random.uniform(4,1))

5.7 其他分布随机函数

以下都是生成随机数的方法,只是底层核心算法不同。

  1. expovariate:生成一个 (0,∞) 之间的随机整数,指数分布;
  2. gammavariate:采用 gamma 分布;
  3. gauss:采用高斯(正太)分布;
  4. lognormvariate:对数正太分布;
  5. normalvariate:正太分布;
  6. vonmisesvariate:冯米赛斯分布;
  7. paretovariate:帕累托分布;
  8. weibullvariate:韦伯分布

6 os库

在 Python 中 os 库提供了基本的操作系统交互功能,该库下包含大量与文件系统、操作系统相关的函数,通过 dir 函数可以查看。

['DirEntry', 'F_OK', 'MutableMapping', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'PathLike', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'W_OK', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_execvpe', '_exists', '_exit', '_fspath', '_get_exports_list', '_putenv', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'cpu_count', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fsync', 'ftruncate', 'get_exec_path', 'get_handle_inheritable', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getenv', 'getlogin', 'getpid', 'getppid', 'isatty', 'kill', 'linesep', 'link', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'putenv', 'read', 'readlink', 'remove', 'removedirs', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sep', 'set_handle_inheritable', 'set_inheritable', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'st', 'startfile', 'stat', 'stat_result', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sys', 'system', 'terminal_size', 'times', 'times_result', 'truncate', 'umask', 'uname_result', 'unlink', 'urandom', 'utime', 'waitpid', 'walk', 'write']

这些函数主要分为几类。

  1. 路径操作:os.path 子库,处理文件路径及信息;
  2. 进程管理:启动系统中其它程序;
  3. 环境参数:获得系统软硬件信息等环境参数。

6.1 os库路径操作

os.path 在 os 库中用于提供操作和处理文件路径相关函数,常见的函数清单如下:
os.path.abspath(path) 返回绝对路径
os.path.normpath(path) 规范 path 字符串形式
os.path.realpath(path) 返回 path 的真实路径
os.path.dirname(path) 返回文件路径
os.path.basename(path) 返回文件名
os.path.join(path1[, path2[, …]]) 把目录和文件名合成一个路径
os.path.exists(path) 如果路径 path 存在,返回 True;如果路径 path 不存在,返回 False。
os.path.isfile(path) 判断路径是否为文件
os.path.isdir(path) 判断路径是否为目录
os.path.getatime(path) 返回最近访问时间(浮点型秒数)
os.path.getmtime(path) 返回最近文件修改时间
os.path.getsize(path) 返回文件大小,如果文件不存在就返回错误

以上函数的使用过程比较容易理解,导入模块后,调用即可.
模块导入使用下述方式:

import os.path
variate=os.path.abspath(__file__)
print(variate)

函数的参数都是 path,在传入的时候,特备要注意原生字符串的应用,还有要区分绝对路径和相对路径的问题。

6.2 os库进程管理

改内容主要用于在Python中执行程序或命令Command,函数原型为:

os.system(command)

例如,在Python中唤醒画板程序

os.system("c:\windows/system32/mspaint.exe")

除了system函数以外,还有一个os.exec函数相关知识.具体可以查看下述函数的用法

os.execl(path, arg0, arg1,)
os.execle(path, arg0, arg1,, env)
os.execlp(file, arg0, arg1,)
os.execlpe(file, arg0, arg1,, env)
os.execv(path, args)
os.execve(path, args, env)
os.execvp(file, args)
os.execvpe(file, args, env)

这些函数都将执行一个新程序,以替换当前进程

6.3 os库运行环境相关参数

环境参数顾名思义就是改变系统环境变量,或者理解为Python运行环境相关信息
通过下述属性,可以获取环境变量:

os.environ

如果希望获取操作系统类型,使用os.name,目前只有三个值:分别是posix,nt,java
函数部分,主要掌握的函数有:

  • os.chdir(path):修改当前程序操作的路径;
  • os.getcwd();返回程序运行的路径
  • os.getlogin():获取当前登录用户名称
  • os.cpu_count():获得当前系统的CPU数量
  • os.urandom(n):返回一个有n个byte长的一个随机字符串,用于加密运算

7 sys库

该库主要维护一些与python解释器相关的参数变量和方法
常见属性如下:

  1. sys.argv
    获取命令行参数列表,第一个元素是程序本身
import sys
print(sys.argv)

接下来通过控制台运行 python 程序时,需要携带参数,下述代码 312.py 是 python 文件名,1、2、3 是后缀的参数。

python 312.py 1 2 3
执行程序之后,得到的结果为:

['312.py', '1', '2', '3']
第一个是文件名,后面依次是传递进来的参数。
  1. sys.platform
    获取Python运行平台的信息,结果比os.name要准确
  2. sys.path
    获取Pythonpath环境变量的值,一般用作模块搜索路径
  3. sys.modules
    以字典的形式获取所有当前 Python 环境中已经导入的模块。
  4. sys.stdin,sys.stdout,sys.stderr
    sys.stdin , sys.stdout ,sys.stderr 变量包含与标准 I/O 流对应的流对象。
import sys

# 标准输出, sys.stdout.write() 的形式就是 print() 不加'\n' 的形式。
sys.stdout.write("hello")
sys.stdout.write("world")

sys.stdin标准输入,等价于input

  1. sys.ps1和sys.ps2
    指定解释器的首要和次要提示符,仅当解释器处于交互模式,它们才有意义
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1="***"
***print("hello")
hello
***

  1. 常见方法如下
    **sys.exit(n) **
    退出 Python 程序,exit(0)表示正常退出。
    当参数非 0 时,会引发一个 SystemExit 异常,可以在程序中捕获该异常。参数也可以称为状态码。

sys.getdefaultencoding()、sys.setdefaultencoding() 、sys.getfilesystemencoding()

  • sys.getdefaultencoding():获取系统当前编码,有的博客中写默认为 ascii,但是我本地默认为 utf-8;
  • sys.setdefaultencoding():设置系统的默认编码;
  • sys.getfilesystemencoding():获取文件系统使用编码方式,默认 utf-8。

sys.getrecursionlimit() 、 sys.setrecursionlimit()
获取 Python 的最大递归数目和设置最大递归数目

sys.getswitchinterval()、sys.setswitchinterval(interval)
获取和设置解释器的线程切换间隔时间(单位为秒)

8 Python字符编码与解码

8.1 Python 字符编码与解码是什么

在 Python3 中字符默认编码是 Unicode 字符,而编码指的是将字符转换成字节流,解码是相反的操作。

在正式开始前,我们还需要梳理一些基本概念
Python 中的字符串

计算机中 8 比特(bit)等于一个字节(byte),8 比特就是 8 位,即一个字节能表示的最大整数是 255(1111 1111)。

如果希望扩大整数范围,需要用到更多的字节,例如 2 个字节就可以表示 65535,4 个字节就能表示 4294967295。

基于上述原理出现了各种编码格式,例如 ASCII 可以表示 256 个字符,但仅支持英文字母,数字和少部分符号,中文的范围要大很多,所以出现了 GB2312 编码(后来升级到了 GBK 编码),可以容纳 6763 个汉字,但放眼世界还不够,还需要更多的字符。

此时 Unicode 字符集就出现了,它将所有的语言都容纳在一起,后续为了在存储和传输数据时节省空间,出现了 UTF8 编码。

8.2 怎么用

通过ord()函数获取字符的整数表示,通过chr()将整数表示为字符,例如如下代码

print(ord('爬')) # 29228
print(chr(29228))

既然知道数字可以转换为数字,那十进制和十六进制的数字都可以。

例如 29228 = 722c,所以 \u722c

print(chr(int('722c', 16)))

也可以使用 Unicode 转码工具进行转换。

8.3 Python编码和解码函数

my_b = '技能树'.encode('utf-8')
print('编码后',my_b) # 编码后 b'\xe6\x8a\x80\xe8\x83\xbd\xe6\xa0\x91'

解码操作如下所示:

my_b = '技能树'.encode('utf-8')
print('编码后', my_b)  # 编码后 b'\xe6\x8a\x80\xe8\x83\xbd\xe6\xa0\x91'

my_str = my_b.decode('utf-8')
print("解码后", my_str)

需要注意编码后输出的内容与字符串类似,就是前面有一个前缀 b。

8.4 乱码

如果编码和解码方法不一致,就会出现乱码问题,例如下述代码

my_b = '技能树'.encode('gbk')
print('编码后', my_b)  # 编码后 b'\xbc\xbc\xc4\xdc\xca\xf7'

my_str = my_b.decode('utf-8')
print("解码后", my_str)

出错信息如下:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbc in position 0: invalid start byte

当出现上述类型的错误时,需要做的就是寻找到正确的原编码,然后进行处理。

8.5 Python字符串编解码的使用

二进制只是二进制,取决于怎么编码和解码,unicode 转 utf8

if __name__ == '__main__':
    unicode_str = u'二进制只是二进制,取决于怎么编码和解码'
    print(unicode_str)

    utf8_str = unicode_str.encode('utf-8')
    print(utf8_str)

    # TODO(You):请在此实现代码
    unicode_str_again = ...
    assert unicode_str_again == unicode_str
    # 请选出下列能正确实现这一功能的选项。
    # A.
    unicode_str_again = utf8_str.decode('utf-8')
    # B.
    unicode_str_again = utf8_str.encode('unicode')
    # C.
    unicode_str_again = utf8_str.decode()
    # D.
    unicode_str_again = utf8_str.decode('unicode')
   	# A 正确
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值