数据类型
Python 默认拥有以下内置数据类型:
文本类型: | str |
---|---|
数值类型: | int , float , complex |
序列类型: | list , tuple , range |
映射类型: | dict |
集合类型: | set , frozenset |
布尔类型: | bool |
二进制类型: | bytes , bytearray , memoryview |
在 Python 中,当您为变量赋值时,会设置数据类型:
示例 | 数据类型 |
---|---|
x = “Hello World” | str |
x = 29 | int |
x = 29.5 | float |
x = 1j | complex |
x = [“apple”, “banana”, “cherry”] | list |
x = (“apple”, “banana”, “cherry”) | tuple |
x = range(6) | range |
x = {“name” : “Bill”, “age” : 63} | dict |
x = {“apple”, “banana”, “cherry”} | set |
x = frozenset({“apple”, “banana”, “cherry”}) | frozenset |
x = True | bool |
x = b”Hello” | bytes |
x = bytearray(5) | bytearray |
x = memoryview(bytes(5)) | memoryview |
如果希望指定数据类型,则您可以使用以下构造函数:
示例 | 数据类型 |
---|---|
x = str(“Hello World”) | str |
x = int(29) | int |
x = float(29.5) | float |
x = complex(1j) | complex |
x = list((“apple”, “banana”, “cherry”)) | list |
x = tuple((“apple”, “banana”, “cherry”)) | tuple |
x = range(6) | range |
x = dict(name=”Bill”, age=36) | dict |
x = set((“apple”, “banana”, “cherry”)) | set |
x = frozenset((“apple”, “banana”, “cherry”)) | frozenset |
x = bool(5) | bool |
x = bytes(5) | bytes |
x = bytearray(5) | bytearray |
x = memoryview(bytes(5)) | memoryview |
文件
open函数的参数
要读写文件,首先要通过内置函数open 打开文件,获得文件对象。
函数open的参数如下
open( file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None )
其中下面这3个参数是我们常用的。
-
参数 file
file参数指定了要打开文件的路径。
可以是相对路径,比如 ‘log.txt’, 就是指当前工作目录下面的log.txt 文件, 也可以是绝对路径,比如 ’d:/project/log/log.txt',
-
参数 mode
mode参数指定了文件打开的
模式
,打开文件的模式,决定了可以怎样操作文件。常用的打开模式有
- r 只读文本模式打开,这是最常用的一种模式
- w 只写文本模式打开
- a 追加文本模式打开
如果我们要 读取文本文件内容到字符串对象中 , 就应该使用 r 模式。
我们可以发现mode参数的缺省值 就是 ‘r’ 。
就是说,调用open函数时,如果没有指定参数mode的值,那么该参数就使用缺省值 ‘r’,表示只读打开。
如果我们要 创建一个新文件写入内容,或者清空某个文本文件重新写入内容, 就应该使用 ‘w’ 模式。
如果我们要 从某个文件末尾添加内容, 就应该使用 ‘a’ 模式。
-
参数 encoding
encoding 参数指定了读写文本文件时,使用的 字符编解码 方式。
调用open函数时,如果传入了encoding参数值:
后面调用write写入字符串到文件中,open函数会使用指定encoding编码为字节串; 后面调用read从文件中读取内容,open函数会使用指定encoding解码为字符串对象
如果调用的时候没有传入encoding参数值,open函数会使用系统缺省字符编码方式。 比如在中文的Windows系统上,就是使用cp936(就是gbk编码)。
建议大家编写代码 读写文本文件时,都指定该参数的值。
if __name__ == '__main__': # 指定编码方式为 utf8 f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'w', encoding='utf8') # write方法会将字符串编码为utf8字节串写入文件 f.write('李嘉图:祝大家学有所成!') # 文件操作完毕后, 使用close 方法关闭该文件对象 f.close() # 指定编码方式为utf8 f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'r', encoding='utf8') # read 方法会在读取文件中的原始字节串后, 根据上面指定的gbk解码为字符串对象返回 content = f.read() # 文件操作完毕后, 使用close 方法关闭该文件对象 f.close() # 通过字符串的split方法获取其中用户名部分 name = content.split(':')[0] print(name)
with
if __name__ == '__main__': f = open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'w', encoding='utf8') f.write('李嘉图:祝大家学有所成!') f.close() with open('D:/Code2022/Python/pythonProjectStudy/table_contents/tmp.txt', 'r', encoding='utf8') as f: linelist = f.readlines() for line in linelist: print(line)
附加:文件和目录
自调用其他程序
Python中调用外部程序主要是通过两个方法实现的, 一个是os库的
system
函数,另外一个是subprocess
库。
os.system函数
使用os库的 system
函数 调用其它程序 是非常方便的。就把命令行内容 作为 system
函数的参数 即可
import os if __name__ == '__main__': os.system('cd D:/test && mkdir test.txt')
os.system 函数调用外部程序的时候, 必须要等被调用程序执行结束, 才会接着往下执行代码。 否则就会一直等待。
os.system 函数没法获取 被调用程序输出到终端窗口的内容。 如果需要对被调用程序的输出信息进行处理的话, 可以使用 subprocess 模块。
os.startfile 函数
如果我们想达到类似文件浏览器双击打开一个文件的效果可以使用 os.startfile
函数。
这个函数的参数可以是任何 非可执行程序 文件
os.startfile('d://统计数据.xlsx')
可以调用该xlsx对应的关联程序(Excel)来打开该文件。
subprocess 模块
Popen 是 subprocess的核心,子进程的创建和管理都靠它处理。
- https://cloud.tencent.com/developer/article/1445388
- https://docs.python.org/zh-cn/3.9/library/subprocess.html?highlight=subprocess#module-subprocess
线程和进程
创建新线程
# 从 threading 库中导入Thread类 from threading import Thread from time import sleep # 定义一个函数,作为新线程执行的入口函数 def threadFunc(arg1, arg2): print('子线程 开始') print(f'线程函数参数是:{arg1}, {arg2}') sleep(5) print('子线程 结束') if __name__ == '__main__': print('主线程执行代码') # 创建 Thread 类的实例对象 thread = Thread( # target 参数 指定 新线程要执行的函数 # 注意,这里指定的函数对象只能写一个名字,不能后面加括号, # 如果加括号就是直接在当前线程调用执行,而不是在新线程中执行了 target=threadFunc, # 如果 新线程函数需要参数,在 args里面填入参数 # 注意参数是元组, 如果只有一个参数,后面要有逗号,像这样 args=('参数1',) args=('参数1', '参数2') ) # 执行start 方法,就会创建新线程, # 并且新线程会去执行入口函数里面的代码。 # 这时候 这个进程 有两个线程了。 thread.start() # 主线程的代码执行 子线程对象的join方法, # 就会等待子线程结束,才继续执行下面的代码 thread.join() print('主线程结束')
共享数据的访问控制
from threading import Thread, Lock from time import sleep bank = { 'count': 0 } bankLock = Lock() # 定义一个函数,作为新线程执行的入口函数 def deposit(theadidx, amount): # 操作共享数据前,申请获取锁 bankLock.acquire() balance = bank['count'] # 执行一些任务,耗费了0.1秒 sleep(0.1) bank['count'] = balance + amount print(f'子线程 {theadidx} 结束') # 操作完共享数据后,申请释放锁 bankLock.release() if __name__ == '__main__': theadlist = [] for idx in range(10): thread = Thread(target=deposit, args=(idx, 1) ) thread.start() # 把线程对象都存储到 threadlist中 theadlist.append(thread) for thread in theadlist: thread.join() print('主线程结束') print(f'最后我们的账号余额为 {bank["count"]}')
deamon线程
from threading import Thread from time import sleep def threadFunc(): sleep(1) print('子线程 结束') if __name__ == '__main__': # thread = Thread(target=threadFunc) # thread.start() # print('主线程结束') thread = Thread(target=threadFunc, daemon=True # 设置新线程为daemon线程 ) thread.start() print('daemon主线程结束')
多线程
Python 官方解释器 的每个线程要获得执行权限,必须获取一个叫 GIL (全局解释器锁) 的东西。
这就导致了 Python 的多个线程 其实 并不能同时使用 多个CPU核心。
所以如果是计算密集型的任务,不能采用多线程的方式。
from threading import Thread def f(): while True: b = 53*53 if __name__ == '__main__': plist = [] # 启动10个线程 for i in range(10): p = Thread(target=f) p.start() plist.append(p) for p in plist: p.join()
多个CPU核心的运算能力,可以使用Python的多进程库。
from multiprocessing import Process def f(): while True: b = 53*53 if __name__ == '__main__': plist = [] for i in range(2): p = Process(target=f) p.start() plist.append(p) for p in plist: p.join()
from multiprocessing import Process, Manager from time import sleep def f(taskno, return_dict): sleep(1) # 存放计算结果到共享对象中 return_dict[taskno] = taskno if __name__ == '__main__': manager = Manager() # 创建 类似字典的 跨进程 共享对象 return_dict = manager.dict() plist = [] for i in range(10): p = Process(target=f, args=(i, return_dict)) p.start() plist.append(p) for p in plist: p.join() print('get result...') # 从共享对象中取出其他进程的计算结果 for k, v in return_dict.items(): print(k, v)
JSON
序列化和反序列化
Python中内置了json这个库,可以 方便的把内置的数据对象 序列化为json格式文本的字符串。
import json historyTransactions = [ { 'time': '20300101070311', # 交易时间 'amount': '3088', # 交易金额 'productid': '45454455555', # 货号 'productname': 'iphone30' # 货名 }, { 'time': '20300101050311', # 交易时间 'amount': '18', # 交易金额 'productid': '453455772955', # 货号 'productname': '饼干' # 货名 } ] if __name__ == '__main__': # dumps 方法将数据对象序列化为 json格式的字符串 jsonstr = json.dumps(historyTransactions) print(jsonstr)
import json historyTransactions = [ { 'time': '20300101070311', # 交易时间 'amount': '3088', # 交易金额 'productid': '45454455555', # 货号 'productname': 'iphone30' # 货名 }, { 'time': '20300101050311', # 交易时间 'amount': '18', # 交易金额 'productid': '453455772955', # 货号 'productname': '饼干' # 货名 } ] if __name__ == '__main__': # dumps 方法将数据对象序列化为 json格式的字符串 jsonstr = json.dumps(historyTransactions) print(jsonstr) print('================') print(json.dumps(historyTransactions, ensure_ascii=False, indent=4)) print('================') jsonstr = '[{"time": "20300101070311", "amount": "3088", "productid": "45454455555", "productname": "iphone7"}, {"time": "20300101070311", "amount": "18", "productid": "453455772955", "productname": "/u5999/u5999/u5999"}]' translist = json.loads(jsonstr) print(translist) print(type(translist))
装饰器
Python中装饰器通常用来装饰函数、或者类的方法。
通常被装饰后的函数, 会在原有的函数基础上,增加一点功能。
装饰器经常被用在库和框架中, 给别的开发者使用。
这些库的开发者预料到 使用者 开发的函数可能需要 一些增强的功能。
但是 这些库的开发者 没法去改使用者的代码, 就可以把这些增强的部分做在 装饰器函数中。
这样使用者,只需要在他们的函数前面上@xxx 就使用了这些增强的功能了。
基础示例:
import time # 定义一个装饰器函数 def sayLocal(func): def wrapper(): curTime = func() return f'当地时间: {curTime}' return wrapper @sayLocal def getXXXTime(): print() return time.strftime('%Y_%m_%d %H:%M:%S', time.localtime()) if __name__ == '__main__': # 装饰 getXXXTime # getXXXTime = sayLocal(getXXXTime) print(getXXXTime())
进阶示例-被装饰的函数有参数:
import time def sayLocal(func): def wrapper(*args, **kargs): curTime = func(*args, **kargs) return f'当地时间: {curTime}' return wrapper @sayLocal def getXXXTimeFormat1(name): curTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) return f'{curTime} ,数据采集者:{name} ' @sayLocal def getXXXTimeFormat2(name, place): curTime = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) return f'{curTime} ,数据采集者:{name} , 采集地:{place}' if __name__ == '__main__': print(getXXXTimeFormat1('张三')) print(getXXXTimeFormat2('张三', place='北京'))
进阶示例-装饰器函数自身有参数:
# 添加输出日志的功能 def logging(flag): def decorator(fn): def inner(num1, num2): if flag == "+": print("--正在努力加法计算--") elif flag == "-": print("--正在努力减法计算--") result = fn(num1, num2) return result return inner # 返回装饰器 return decorator # 使用装饰器装饰函数 @logging("+") def add(a, b): result = a + b return result @logging("-") def sub(a, b): result = a - b return result if __name__ == '__main__': result = add(1, 2) print(result) result = sub(1, 2) print(result)
加密
算法 | 计算结果长度 |
---|---|
MD5 | 16字节 |
SHA1 | 20字节 |
SHA224 | 28字节 |
SHA256 | 32字节 |
SHA384 | 48字节 |
SHA512 | 64字节 |
典型应用场景:
校验拷贝下载文件
校验信息有效性
使用 Python 内置库 hashlib 创建hash值。
示例:
import hashlib if __name__ == '__main__': # 使用 md5 算法 # m = hashlib.md5() # 如果你想使用别的哈希算法,比如, sha256 算法,只需要修改为对应的函数 sha256()即可 m = hashlib.sha256() # 要计算的源数据必须是字节串格式 # 字符串对象需要encode转化为字节串对象 m.update("ML李嘉图|mllijaitu".encode()) # 产生哈希值对应的bytes对象 resultBytes = m.digest() # 产生哈希值的十六进制表示 resultHex = m.hexdigest() print(resultHex)
SSH远程操作
Python第三方库 Paramiko 就是作为ssh客户端远程控制Linux主机 的。
exec_command 是每次执行都是 新打开一个channel的东西执行, 每个channel都是命令执行的环境,每执行命令都是一个新的执行环境,不在上次执行的环境里面, 相当于 每次都在各自的执行环境里面,和前面的执行环境没有关系。 多个命令一起执行,用分号隔开,像这样: stdin, stdout, stderr = ssh.exec_command("cd testdir;pwd")
操作单台主机:
# 单台主机操作 import paramiko #############################配置信息##################################### # 登陆参数设置 hostname = "" host_port = 22 username = "root" password = "" ######################################################################## def ssh_client_con(): """创建ssh连接,并执行shell指令""" # 1 创建ssh_client实例 ssh_client = paramiko.SSHClient() # 自动处理第一次连接的yes或者no的问题 ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy) # 2 连接服务器 ssh_client.connect( port=host_port, hostname=hostname, username=username, password=password ) # 3 执行shell命令 # 构造shell指令 shell_command = "ls" stdin, stdout, stderr = ssh_client.exec_command(shell_command) # 输出返回信息 stdout_info = stdout.read().decode('utf8') print(stdout_info) # 输出返回的错误信息 stderr_info = stderr.read().decode('utf8') print(stderr_info) def sftp_client_con(): # 1 创建transport通道 tran = paramiko.Transport((hostname, host_port)) tran.connect(username=username, password=password) # 2 创建sftp实例 sftp = paramiko.SFTPClient.from_transport(tran) # 3 执行上传功能 local_path = "" # 本地路径 remote_path = "" # 远程路径 put_info = sftp.put(local_path, remote_path, confirm=True) print(put_info) print(f"上传{local_path}完成") # 4 执行下载功能 save_path = "" # 本地保存文件路径 sftp.get(remotepath=remote_path, localpath=save_path) print(f'下载{save_path}完成') # 5 关闭通道 tran.close() if __name__ == '__main__': # 调用函数执行功能 ssh_client_con() # sftp_client_con()
Python面向对象编程
类变量与实例变量
# 创建一个学生类 class Student: # number属于类变量,不属于某个具体的学生实例 number = 0 # 定义学生属性,初始化方法 # name和score属于实例变量 def __init__(self, name, score): self.name = name self.score = score Student.number = Student.number + 1 # 定义打印学生信息的方法 def show(self): print("Name: {}. Score: {}".format(self.name, self.score)) # 实例化,创建对象 student1 = Student("John", 100) student2 = Student("Lucy", 99) print(Student.number) # 打印2 print(student1.__class__.number) # 打印2
类方法
有些变量只属于类,有些方法也只属于类,不属于具体的对象。
你有没有注意到属于对象的方法里面都有一个self参数, 比如__init__(self)
, show(self)
?
self
是指对象本身。
属于类的方法不使用self参数, 而使用参数cls
,代表类本身。
另外习惯上对类方法我们会加上@classmethod
的修饰符做说明。
class Student: # number属于类变量,不属于某个具体的学生实例 number = 0 # 定义学生属性,初始化方法 # name和score属于实例变量 def __init__(self, name, score): self.name = name self.score = score Student.number = Student.number + 1 # 定义打印学生信息的方法 def show(self): print("Name: {}. Score: {}".format(self.name, self.score)) # 定义类方法,打印学生的数量 @classmethod def total(cls): print("Total: {0}".format(cls.number)) if __name__ == '__main__': # 实例化,创建对象 student1 = Student("John", 100) student2 = Student("Lucy", 99) Student.total() # 打印 Total: 2
类的私有属性和私有方法
类里面的私有属性和私有方法以双下划线__
开头。私有属性或方法不能在类的外部被使用或直接访问。
# 创建一个学生类 class Student: # 定义学生属性,初始化方法 # name和score属于实例变量, 其中__score属于私有变量 def __init__(self, name, score): self.name = name self.__score = score # 定义打印学生信息的方法 def show(self): print("Name: {}. Score: {}".format(self.name, self.__score)) # 实例化,创建对象 student1 = Student("John", 100) student1.show() # 打印 Name: John, Score: 100 student1.__score # 打印出错,该属性不能从外部访问。
@property
# 创建一个学生类 class Student: # 定义学生属性,初始化方法 # name和score属于实例变量, 其中score属于私有变量 def __init__(self, name, score): self.name = name self.__score = score # 利用property装饰器把函数伪装成属性 @property def score(self): print("Name: {}. Score: {}".format(self.name, self.__score)) if __name__ == '__main__': # 实例化,创建对象 student1 = Student("John", 100) student1.score # 打印 Name: John. Score: 100
类的继承
# 创建父类学校成员SchoolMember class SchoolMember: def __init__(self, name, age): self.name = name self.age = age def tell(self): # 打印个人信息 print('Name:"{}" Age:"{}"'.format(self.name, self.age), end=" ") # 创建子类老师 Teacher class Teacher(SchoolMember): def __init__(self, name, age, salary): SchoolMember.__init__(self, name, age) # 利用父类进行初始化 self.salary = salary # 方法重写 def tell(self): SchoolMember.tell(self) print('Salary: {}'.format(self.salary)) # 创建子类学生Student class Student(SchoolMember): def __init__(self, name, age, score): SchoolMember.__init__(self, name, age) self.score = score def tell(self): SchoolMember.tell(self) print('score: {}'.format(self.score)) if __name__ == '__main__': teacher1 = Teacher("John", 44, "$60000") student1 = Student("Mary", 12, 99) teacher1.tell() student1.tell()
静态变量和静态方法
# 创建一个学生类 class Student: # number属于类变量,定义在方法外,不属于具体实例 number = 0 # 定义学生属性,初始化方法 # name和score属于实例变量,定义在方法里 def __init__(self, name, score): self.name = name self.score = score Student.number = self.number + 1 # 定义打印学生信息的方法 def show(self): print("Name: {}. Score: {}".format(self.name, self.score)) # 静态方法无法使用cls和self参数访问类或实例的变量 @staticmethod def func1(): print("this is static function!")