python从入门到精通合集(二)面向对象,文件IO、线程、进程

所有示例基于python3.7.4版本

提示:以下是本篇文章正文内容,下面案例可供参考

1.下划线的含义

类型 含义
_var 一个约定,表明这个名称供内部使用,约定只有类对象和子类对象自己能访问
var_ 一个约定,用来避免与Python关键字产生命名冲突
__var 私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。
_var_ python语言定义的特殊方法,避免你自己的属性中使用这种命名方案
_ 可用作临时或无意义变量的名称

2.面向对象

python是面向对象语言,无疑会包括面向对象的三大特点封装、继承、多态

类、实例、属性、方法

(一)所有类的父类------->object类

class Student(object): 
        pass

(二)类的实例:

ojb1=Student()
print(ojb1)  #类的实例
print(Student)

在这里插入图片描述
(三)类绑定属性

ojb1.name='刘恒'  #给实例变量绑定属性
print(ojb1.name)

(四)类的有参构造

class Student(object):
#self表示实例本身,给对象绑定属性 __init__方法第一个参数永远是self
    def __init__(self, name, score):
        self.name = name
        self.score = score
        
    def print_score(self):
        print('%s: %s' % (self.name, self.score))

有参构造会覆盖无参构造,不能传入空的参数,必须传入与__init__方法匹配的参数,但self不需要传,Python解释器自己会把实例变量传进去
测试:

obj1=Student('刘恒',10)
print(obj1.name)
print(obj1.score)
print(obj1.print_score())
#print函数中所放的函数没有返回值,那么print将会return None
obj2=Student('刘恒',10)
print(obj2==obj1)
obj2.name='张三'
print(obj2.name)  #外部仍可以访问

在这里插入图片描述
通过测试可以发现,两个实例对象即使参数相同,但也是不一样的,所存储的地址是不同的,同时发现实例对象依然可以外部更改属性

封装:隐藏内部,对外提供公共接口

  只需要在属性名前加上两个下划线,内部才可访问,外部不能访问
class Student(object):
    def __init__(self, name, score):
        self.__name = name
        self.__score = score
    def get_name(self):
        return self.__name
    def get_score(self):
        return self.__score
    def set_score(self, score):
        self.__score = score

测试:

obj3=Student("张三",13)
#print(obj3.__name)  #权限不足访问不到
print(obj3.get_name())
print(obj3.get_score())
obj3.set_score(20)
print(obj3.get_score())

在这里插入图片描述
其实实例变量也可以从外部访问,不能直接访问__name是因为Python解释器对外把__name变量改成了_Student__name,所以,仍然可以通过_Student__name来访问__name变量

print(obj3._Student__name)
#错误写法
obj4=Student("王麻子",35)
print(obj4.get_name())
obj4.__name='李四'
print(obj4.__name)
print(obj4.get_name())  #结果仍是王麻子

在这里插入图片描述
外部代码“成功”地设置了__name变量,但实际上这个__name变量和class内部的__name变量不是一个变量!内部的__name变量已经被Python解释器自动改成了_Student__name,而外部代码给bart新增了一个__name变量

继承

 只需要更改类中括号的内容
 Animal-----父类-->object
 Dog--父类--Animal--父类->object
class Animal(object):
    def run(self):
        print('动物园开业了')
class Dog(Animal):
   pass
Dog().run()  #子类调用父类方法

在这里插入图片描述

  • 方法重写
class Animal(object):
    def run(self):
        print('动物园开业了')
class Dog(Animal):
   def run(self):
       print('我是dog')
Dog().run()  #方法重写,子类的方法覆盖了父类的方法

在这里插入图片描述

多态

python中支持多态,但是是有限的的支持多态性,
主要是因为python中变量的使用不用声明,所以不存在父类引用指向子类对象的多态
Python中多态的特点:
       只关心对象的实例方法是否同名,不关心对象所属的类型;
       对象所属的类之间,继承关系可有可无;
class Animal(object):
    def run(self):
        print('动物园开业了')

class Dog(Animal):

    def run(self):
        print('Dog is running...')

class Cat(Animal):

    def run(self):
        print('Cat is running...')

def run_twice(animal):
    animal.run()
run_twice(Animal())
run_twice(Dog())
run_twice(Cat())
class Timer(object):
    def run(self):
        print('Start...')
run_twice(Timer())

在这里插入图片描述

``

实例属性和类属性

class Student1(object):
    name='王麻子'
ojb6=Student1()
print(ojb6.name) ## 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
print(Student1.name)  ## 打印类的name属性
ojb6.name='张三'
print(ojb6.name) ## 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
del ojb6.name
print(ojb6.name)

在这里插入图片描述

3.面向对象编程

使用__slots__

		__slots__变量,用来限制该class实例能添加的属性
class Student(object):
    __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
stu3=Student()
stu3.name='liuheng'
stu3.city='xian'  

当给实例变量添加city属性时报错: AttributeError: 'Student' object has no attribute 'city'
我们试着给其子类增加未绑定的属性:

class SmartStudent(Student):
    pass
stu4=SmartStudent()
stu4.name='zhangsan'
stu4.city='西安'
print(stu4.name)
print(stu4.city)

在这里插入图片描述
通过结果我们可以发现:__slots__定义的属性仅对当前类实例起作用,对继承的子类是不起作用的

使用__str__

 定制返回对象的描述信息
 一般对象的信息:<__main__.Student object at 0x000002E429741AC8> 不好看
class Student1():
   def __str__(self):
         return 'Student object'
print(Student1())

输出为:Student object

使用__repr__

在__str__使用的前提下,当我们将对象的实例赋值给变量时,输出变量,
结果依然是:<__main__.Student object at 0x000002E25B19F9C8>

这是因为:变量调用的不是__str__(),而是__repr__()。 __str__()返回用户看到的字符串,而__repr__()返回程序开发者看到的字符串
通常用: _repr_ = _str_

使用@property

Python内置的@property装饰器就是负责把一个方法变成属性调用的
class Student2(object):
    @property
    def score(self):
        return self._score
    @score.setter
    def score(self, value):
        if not isinstance(value, int):
            raise ValueError('score must be an integer!')
        if value < 0 or value > 100:
            raise ValueError('score must between 0 ~ 100!')
        self._score = value
s1=Student2()
s1.score=10
print(s1.score)

输出:10
注意:属性的方法名不要和实例变量重名

class Student3(object):
    # 方法名称和实例变量均为birth:
    @property
    def birth(self):
        return self.birth
s2=Student3()
print(s2.birth)  #陷入循环

这是因为调用s.birth时,首先转换为方法调用,在执行return self.birth时,又视为访问self的属性,于是又转换为方法调用,造成无限递归,最终导致栈溢出报错RecursionError。

给实例绑定方法与类绑定方法的区别

给实例绑定方法:

class Student(object):
    pass
stu1=Student()
def set_age(self, age): # 定义一个函数作为实例方法
     self.age = age
from types import MethodType
stu1.set_age=MethodType(set_age,stu1)
stu1.set_age(20)
print(stu1.age)
stu2=Student()
stu2.set_age(20)  #报错 

AttributeError: 'Student' object has no attribute 给一个实例绑定的方法,对另一个实例是不起作用的
给类绑定方法:

Student.set_age=set_age
stu2.set_age(10)
print(stu2.age)  #10

class绑定方法 所有的实例均可调用

多继承:子类可以同时获得多个父类的所有功能

    python支持多继承
    java只支持单继承,但接口支持多继承       
    MixIn混入的意思:为了更好地看出继承关系,把Flyable改为FlyableMixIn。
class Animal(object):
    pass
# 大类:
class Mammal(Animal):
    pass
class Bird(Animal):
    pass
#行为类
class Runnable(object):
    def run(self):
        print('Running...')

class FlyableMixIn(object):
    def fly(self):
        print('Flying...')
#动物
class Dog(Mammal,Runnable):
    pass
class Ostrich(Bird,FlyableMixIn):  #为了更好地看出继承关系,后面加MixIn
    pass
dog1=Dog()
dog1.run()
Ostrich1= Ostrich()
Ostrich1.fly()

在这里插入图片描述

自定义枚举类

from enum import Enum, unique
#@unique装饰器可以帮助我们检查保证没有重复值。
@unique
class Weekday(Enum):
    Sun = 0 # Sun的value被设定为0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6
print(Weekday.Sun,':',Weekday.Sun.value)

Weekday.Sun : 0

4. 错误处理机制

try…except…finally

try:
    print('try...')
    r = 10 / 0
    print('后续代码不会执行')
    print('result:', r)
except ZeroDivisionError as e:
    print('except:', e)
finally:
    print('finally...')
print('END')

在这里插入图片描述
没有错误发生,except语句块不会被执行,但是finally如果有,则一定会被执行

错误捕捉不到的问题

except ValueError as e:
    print('ValueError')
except UnicodeError as e:
    print('UnicodeError')

第二个except永远也捕获不到UnicodeError,因为UnicodeError是ValueError的子类,如果有,也被第一个except给捕获了。

记录错误信息

import logging

def foo(s):
    return 10 / int(s)

def bar(s):
    return foo(s) * 2

def main():
    try:
        bar('0')
    except Exception as e:
        logging.exception(e)

main()

在这里插入图片描述
出错,但程序打印完错误信息后会继续执行,并正常退出:

raise抛出错误

def bar(s):
    n = int(s)
    if n==0:
        raise ValueError('invalid value: %s' % s)
    return 10 / n
bar()

在这里插入图片描述

自定义错误

常见的错误类型和继承关系:https://docs.python.org/3/library/exceptions.html#exception-hierarchy
在这里插入图片描述

Python所有的错误都是从BaseException类派生的
自定义错误类我们只需要继承Exception类

class FooError(Exception):
    pass

def foo(s):
    n = int(s)
    if n==0:
        raise FooError('invalid value: %s' % s)
    return 10 / n
foo('0')

5.IO编程

文件的读写

获取file对象主要用open()方法去打开文件,返回一个file对象
open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
mode符号 意义
r 以只读方式打开文件
w 打开一个文件只用于写入,会把原有的内容覆盖
x 写模式,新建一个文件,如果该文件已存在则会报错。
a 打开一个文件用于追加
b 二进制模式
t 文本模式 (默认)
+ 打开文件进行更新(可读可写)

测试:

try:
    file1= open('C:/Users/文帝/Desktop/test01.txt', 'r',encoding='utf-8') #没有文件则会显示FileNotFoundError
    print(file1.read())
finally:
     file1.close()

在这里插入图片描述
由于文件读写时都有可能产生IOError,所以要对错误进行抓取
文件使用完毕后必须关闭,因为文件对象会占用操作系统的资源,并且操作系统同一时间能打开的文件数量也是有限的
Python引入了with语句来自动帮我们调用close()方法:

with open('C:/Users/文帝/Desktop/test02.txt', 'r',encoding='utf-8') as f:
    print(f.read())  #读取文件的全部内容

常用方法:

with open('C:/Users/文帝/Desktop/test02.txt', 'r',encoding='utf-8') as f:
   print(f.readline())   #读取一行
with open('C:/Users/文帝/Desktop/test02.txt', 'r',encoding='utf-8') as f:
   print(f.readlines())  #一次性把内容按照行返回list类型
file1= open('C:/Users/文帝/Desktop/test02.txt', 'r',encoding='utf-8')
for line in file1.readlines():
    print(line.strip()) # 把末尾的'\n'删掉
file1.close()  
with open('C:/Users/文帝/Desktop/电科1801-刘恒-西安邮电大学.jpg', 'rb') as f:
   print(f.readline())   #读二进制文件

StringIO 在内存中读写 str

from io import StringIO
file3=StringIO()
file3.write('hello')
file3.write(' ')
file3.write('world')   
print(file3.getvalue())   #读取写入的str
print('----------通过循环读取-------------')
file4=StringIO('Hello!\nHi!\nGoodbye!')
while True:
     s = file4.readline()
     if s == '':
         break
     print(s.strip())

在这里插入图片描述

BytesIO内存中读写bytes

from io import BytesIO
f = BytesIO()
f.write('刘恒'.encode('utf-8'))    
print(f.getvalue())
print('----------按文件读取-------------')
file5=BytesIO(b'\xe4\xb8\xad\xe6\x96\x87')
s = file5.read()
print(s)

在这里插入图片描述

操作文件和目录

import os
print(os.name)  #操作系统类型
#如果是posix,说明系统是Linux、Unix或Mac OS X,如果是nt,就是Windows系统。
# print(os.uname())  #获取详细的系统信息  
os.uname()是linux的方法 ,windows不可用
print(os.environ)  #查看操作系统中定义的环境变量
print('-----------------------------------------------------')
print(os.environ.get('PATH'))     #查取某个环境变量的值
print(os.environ.get('x', 'default'))     #给x环境变量设值
print(os.path.abspath('.'))  ## 查看当前目录的绝对路径
s=os.path.join('D:\PythonCode\PythonStudy\Study01', 'testdir')  #路径合并
print(s)   #在Linux/Unix/Mac下是 part-1/part-2
#os.mkdir('/testdir')  #创建一个目录
print(os.path.abspath('/testdir')) 
#os.rmdir('/testdir')  #删除一个目录
 #路径拆分为两部分,后一部分总是最后级别的目录或文件名
r=os.path.split('D:\PythonCode\PythonStudy\Study01') 
#这些合并、拆分路径的函数并不要求目录和文件要真实存在,它们只对字符串进行操作。
print(r)
print(os.path.splitext('C:/Users/文帝/Desktop/test01.txt'))  #获取文件的扩展名
#os.rename('C:/Users/文帝/Desktop/test01.txt', 'C:/Users/文帝/Desktop/test02.txt') #文件重命名
#注意:文件必须是同一个路径
#OSError: [WinError 17] 系统无法将文件移到不同的磁盘驱动器。: 
#'C:/Users/文帝/Desktop/test01.txt' -> 'test02.txt'
#os.remove('test.txt')  #删除文件
print('-------------------')
#列出当前目录下的所有目录
a=[x for x in os.listdir('.') if os.path.isdir(x)]
print(a)
#列出所有的.py
b= [x for x in os.listdir('.') if os.path.isfile(x) and os.path.splitext(x)[1]=='.py']
print(b)

在这里插入图片描述

序列化与反序列化

在程序运行的过程中,所有的变量都是在内存中,可以随时修改变量,但一旦程序结束,变量所占用的内存就会被操作系统回收
把变量从内存中变成可存储或传输的过程称之为序列化
把变量内容从序列化的对象重新读到内存里称之为反序列化
import pickle
d = dict(name='Bob', age=20, score=88)  #定义一个dict
print(d)
a=pickle.dumps(d)  #将对象系列化成bytes
print(a)
f = open('D:\\PythonCode\\PythonStudy\\Study01\\test01.txt', 'wb')
pickle.dump(d, f)   #将对象序列化写入文件
f.close()
f = open('D:\\PythonCode\\PythonStudy\\Study01\\test01.txt', 'rb')
d = pickle.load(f)
f.close()
print(d)

在这里插入图片描述

如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。

JSON和Python内置的数据类型对应如下:

JSON类型 Python类型
{} dict
[] list
“string” str
1234.56 int或float
true/false True/False
null None

Python内置的json模块提供了非常完善的Python对象到JSON格式的转换
python对象--------->Json对象

import json
d={
    
    'name':'Bob', 'age':20, 'score':88}
f=json.dumps(d)  #装换为json格式  ,返回一个str类型
print(f)
f1 = open('D:\\PythonCode\\PythonStudy\\Study01\\test01.txt', 'w')
f2=json.dump(d,f1)  #直接把JSON写入一个file中
f1.close()

在这里插入图片描述
Json对象--------->python对象

f3=json.loads(f)
print(f3)
f4 = open('D:\\PythonCode\\PythonStudy\\Study01\\test01.txt', 'r')
f5=json.load(f4)      #读取文件中的字符串并反序列化python对象
print(f5)

在这里插入图片描述
自定义对象--------->Json对象

 默认情况下,dumps()方法不知道如何将Student实例变为一个JSON的{}对象。
 json模块的dumps()和loads()函数,通过传入参数定制序列化或反序列化的规则
class Student(object):
    def __init__(self, name, age, score):
        self.name = name
        self.age = age
        self.score = score
stu1=Student('刘恒',20,100)
print('-------------我们需要告诉它如何进行转换成json----------------')
def studentdict(std):
    return {
    
    
        'name': std.name,
        'age': std.age,
        'score': std.score
    }
d=json.dumps(stu1,default=studentdict)
print(d)
#class的实例都有一个__dict__属性,它就是一个dict,用来存储实例变量,但定义了__slots__的class不行。
print(json.dumps(stu1, default=lambda obj: obj.__dict__))

在这里插入图片描述
Json对象--------->自定义对象

print('-------------我们需要告诉它如何进行转换成python对象----------------')
def dictstudent(d):
    return Student(d['name'], d['age'], d['score'])
print(json.loads(d, object_hook=dictstudent))

在这里插入图片描述

6.多进程

进程:是并发执行的程序在执行过程中分配和管理资源的基本单位,是一个动态概念,竞争计算机系统资源的基本单位。

Process类的使用

multiprocessing模块就是跨平台版本的多进程模块。
multiprocessing模块提供了一个Process类来代表一个进程对象
os.getpid可以获取当前进程的PID,
os.getppid 可以获取当前进程的主进程的PPID
start()方法用于子进程的启动
join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步
from multiprocessing import Process
import os
# 子进程要执行的代码
def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))
if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',))
    print('Child process will start.')
    p.start()
    p.join()
    print('Child process end.')

spyder输出:
在这里插入图片描述
子进程方法并没有执行
但在cmd和pycharm里面运行,是可以有输出结果的
在这里插入图片描述

用进程池的方式批量创建子进程

from multiprocessing import Pool
import os, time, random
def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print('Waiting for all subprocesses done...')
    p.close()
    p.join()
    print('All subprocesses done.')    

在这里插入图片描述
调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process
注意输出的结果,task 0,1,2,3是立刻执行的,而task 4要等待前面某个task完成后才执行,这是因为Pool设置的参数是4,因此,最多同时执行4个进程。
Pool的默认大小是CPU的核数

进程间通信


from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
    print('Process to write: %s' % os.getpid())
    for value in ['A', 'B', 'C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
    print('Process to read: %s' % os.getpid())
    while True:
        value = q.get(True)
        print('Get %s from queue.' % value)

if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    pr.terminate()

在这里插入图片描述

7.多线程

线程:线程是处理器调度的基本单位,是进程的一个执行单元,是进程内科调度实体。比进程更小的独立运行的基本单位。线程也被称为轻量级进程。

 Python的标准库提供了两个模块:_thread和threading,
 _thread是低级模块,threading是高级模块,对_thread进行了封装。
 绝大多数情况下,我们只需要使用threading这个高级模块。

使用threading模块

import time, threading

# 新线程执行的代码:
def loop():
    print('thread %s is running...' % threading.current_thread().name)
    n = 0
    while n < 5:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name, n))
        time.sleep(1)
    print('thread %s ended.' % threading.current_thread().name)

print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop)
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)

在这里插入图片描述
多线程中,所有变量都由所有线程共享,多线程会引发并发问题(死锁等)
如下测试:

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(2000000):
        change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

在这里插入图片描述

Lock线程锁

balance = 0
lock = threading.Lock()
def change_it(n):
    # 先存后取,结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(2000000):
        lock.acquire()   #获取锁
        try:
            change_it(n)
        finally:
            lock.release() #释放锁

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)

在这里插入图片描述

Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。

ThreadLocal

一个ThreadLocal变量虽然是全局变量,但每个线程都只能读写自己线程的独立副本,互不干扰。ThreadLocal解决了参数在一个线程中各个函数之间互相传递的问题。
 ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等
import threading
    
# 创建全局ThreadLocal对象:
local_school = threading.local()

def process_student():
    # 获取当前线程关联的student:
    std = local_school.student
    print('Hello, %s (in %s)' % (std, threading.current_thread().name))

def process_thread(stu):
    # 绑定ThreadLocal的student:
    local_school.student = stu
    process_student()

t1 = threading.Thread(target= process_thread, args=('Alice',), name='Thread-A')
t2 = threading.Thread(target= process_thread, args=('Bob',), name='Thread-B')
t1.start()
t2.start()
t1.join()
t2.join()

在这里插入图片描述

进程与线程的区别

地址空间:

 线程共享本进程的地址空间,而进程之间是独立的地址空间。

资源:

线程共享本进程的资源如内存、I/O、cpu等,不利于资源的管理和保护,而进程之间的资源是独立的,能很好的进行资源管理和保护。

健壮性:

多进程要比多线程健壮,一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。

执行过程:

每个独立的进程有一个程序运行的入口、顺序执行序列和程序入口,执行开销大。
但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制,执行开销小。

切换时:

进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。
同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程。

8.datetime模块

datetime处理日期和时间的标准库
datetime模块包含一个datetime类,通过from datetime import datetime导入的就是datetime这个类。
datetime转换为timestamp(时间戳)

在计算机中,时间实际上是用数字表示的。我们把1970年1月1日 00:00:00 UTC+00:00时区的时刻称为epoch time,记为0
当前时间就是相对于epoch time的秒数,称为timestamp
timestamp是一个浮点数,它没有时区的概念,而datetime是有时区的
from datetime import datetime
now = datetime.now()  #获取当前的时间
print(now)
print(type(now))  
d=datetime(2020,1,11,12,00)
print(d)  #指定某个日期和时间
t=d.timestamp()
print(t)   #将指定的datatime转换为时间戳
f=datetime.fromtimestamp(t)  #将时间戳转换为datetime本地时间
print(f)
print(datetime.utcfromtimestamp(t)) #UTC时间 UTC+0:00
print('--------------str转换为datetime--------------')
cday = datetime.strptime('2015-6-1 18:19:59', '%Y-%m-%d %H:%M:%S')
print(cday)
print(type(cday))
print('--------------str转换为datetime--------------')
day=cday.strftime('%Y-%m-%d %H:%M:%S')
print(day)
print(type(day))
print('--------------datetime加减-----------------')
from datetime import datetime, timedelta
now = datetime.now() 
print(now)
day1=now + timedelta(hours=10)
print(day1)
day2= now - timedelta(days=1)
print(day2)
day3= now - timedelta(days=2,hours=5,minutes=10)
print(day3)
print('--------------本地时间转换为UTC时间-----------------')
from datetime import datetime, timedelta, timezone
tz_utc_8 = timezone(timedelta(hours=8)) # 创建时区UTC+8:00
now = datetime.now()
dt = now.replace(tzinfo=tz_utc_8) # 强制设置为UTC+8:00
print(dt)
print('------------拿到UTC时间,并强制设置时区为UTC+0:0----------')
utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc)
print(utc_dt)
print('-------------换时区为北京时间:-----------------------')
bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)))
print(bj_dt)
print('-------------转换时区为东京时间:-----------------------')
tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)))
print(tokyo_dt2)

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_45637894/article/details/125836699
今日推荐