time模块、装饰器、类的装饰器、类装饰器
python time模块
导入模块: import time #time模块是python中最基本的模块之一
输出时间戳:time.time() #可以用变量接收,要打印出来要用print(),如 a = time.time(),print(a)
输出为:1516330026.4591534(1970年1月1日00:00:00后经过的浮点秒数)
时间元组: time.localtime() #可以用变量接收,用print()打印,默认是当前的时间;也可以传入一个时间戳,
如:time.localtime(1316331844.899376),它将返回时间戳对应的时间元组。
返回值:time.struct_time(tm_year=2011, tm_mon=9, tm_mday=18, tm_hour=15,
tm_min=44,tm_sec=4, tm_wday=6, tm_yday=261, tm_isdst=0)
上面的红字部分是一个时间元组,那么时间元组的含义是什么呢?返回元组的内容如下:
索引 | 属性(attribute) | 值(value) |
0 | tm_year(年) | 2018 |
1 | tm_mon(月) | 1~12 |
2 | tm_mday(日) | 1~31 |
3 | tm_hour(时) | 0~23 |
4 | tm_min(分) | 0~59 |
5 | tm_sec(秒) | 0~60 |
6 | tm_wday(星期几) | 0~6 |
7 | tm_yday(一年中的第几天) | 1~366 |
8 | tm_isdst(是否为夏令时) | 0,1,-1(-1:夏令时) |
我们经常需要格式化输出时间,那么如何才能做到呢?time模块提供了非常方便的函数供可以调用,首先我们先了解
一些需要认识的格式化符号:
%y | 两位数的年份表示(00-99) |
%Y | 四位数的年份表示(000-9999) |
%m | 月份(01-12) |
%d | 月内中的一天(0-31) |
%H | 24小时制小时数(0-23) |
%I | 12小时制小时数(01-12) |
%M | 分钟数(00=59) |
%S | 秒(00-59) |
%a | 本地简化星期名称 |
%A | 本地完整星期名称 |
%b | 本地简化的月份名称 |
%B | 本地完整的月份名称 |
%c | 本地相应的日期表示和时间表示 |
%j | 年内的一天(001-366) |
%p | 本地A.M.或P.M.的等价符 |
%U | 一年中的星期数(00-53)星期天为星期的开始 |
%w | 星期(0-6),星期天为星期的开始 |
%W | 一年中的星期数(00-53)星期一为星期的开始 |
%x | 本地相应的日期表示 |
%X | 本地相应的时间表示 |
%Z | 当前时区的名称 |
%% | %号本身 |
time模块主要要熟悉time.time( )、time.localtime([secs])、time.asctime([tupletime])、time.strftime(fmt[,tupletime])
time.strptime(str,fmt='%a %b %d %H:%M:%S %Y')、time.mktime(tupletime)、time.sleep()
前两个我们已经熟悉了,下面介绍其他五个:
time.asctime([tupletime]) :接受时间元组并返回一个可读的形式为"Fri Jan 19 13:37:39 2018"(2018年01月19日 周五
13时37分39秒)的24个字符的字符串。
time.strftime(fmt,[tupletime]) :接收以时间元组,并返回以可读字符串表示的当地时间,格式由fmt决定。
如: print(time.strftime('%Y-%m-%d %H:%M:%S %w', time.localtime()))
输出: 2018-01-19 13:43:44 5 它的数据类型是str
time.strptime(str, '%Y-%m-%d %H:%M:%S %w') :根据fmt的格式,把一个时间字符串,解析为时间元组。利用上面
返回的字符串,使用time.strptime()将它转化为时间元组:print(time.strptime(st, '%Y-%m-%d %H:%M:%S %w')),其中st
为接收time.strftime()的变量。返回结果:time.struct_time(tm_year=2018, tm_mon=1, tm_mday=19, tm_hour=13,
tm_min=50,tm_sec=24, tm_wday=4, tm_yday=19, tm_isdst=-1),这是一个时间元组。
time.mktime(tupletime) :接受时间元组并返回时间辍(1970纪元后经过的浮点秒数)。
如:
这里的b是一个时间元组,记住在传时间元组时,如果是自己写元组,就必须去掉哪些英文简写,不然会报错,如果
是变量接收再传入,则不用考虑这个问题!
返回:1516341024.0
time.sleep() :推迟线程的执行。
函数装饰器
装饰器(deco):
装饰函数的参数是被装饰的函数对象,返回原函数对象,装饰器本质上是一个Python函数,它可以让其他函数在不需要
做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。
概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。
函数的装饰器本身接收一个闭包:
函数装饰器就是在函数之前加一个:@+‘函数名’ ;如@f1
加上@符合的时候,就将函数传入闭包,返回一个函数体,加括号传入参数就可以执行返回的函数。
类的装饰器:类里面一定要写__call__方法,调用函数时实际上是调用__call__方法:
三个常用的类装饰器
@property 把方法变成属性
装饰过的函数返回的不再是一个函数,而是一个property对象
装饰过后的方法不再是可调用的对象,可以看做数据属性直接访问。
@staticmethod #(静态方法)
把没有参数的函数装饰过后变成可被实例调用的函数,
函数定义时是没有参数的,可以不接收参数
变成静态方法后,类名和实例都看看有调用;
也可以在静态方法里传入参数,如果有参数,则调用的时候就一定要传参:
@classmethod (类方法) 有self,类名也可以调用!
把装饰过的方法变成一个classmethod类对象,既能能被类调用又能被实例调用。
注意参数是cls代表这个类本身。
一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法。
而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用。
类装饰器
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 ''' 4 @File : class_decorator.py 5 @Time : 2024/06/19 22:41:23 6 @Author : firstElfin 7 @Version : 1.0 8 @Desc : None 9 ''' 10 11 import inspect 12 from abc import ABC, abstractmethod 13 from threading import Lock 14 15 components = {} 16 17 class Component: 18 def __call__(self, cls): 19 if components.get(cls) is None: components[cls] = cls 20 return components[cls] 21 22 Service = Repository = Resource = Component 23 24 25 class Inject(ABC): 26 name = "Inject" 27 28 def __init__(self, **kwargs): 29 self.kwargs = kwargs 30 31 def __call__(self, obj): 32 cls_init = obj.__init__ 33 34 def __sub_init(_self, *args, **kwargs): 35 cls_init(_self, *args, **kwargs) 36 self.inject_members(_self) 37 38 obj.__init__ = __sub_init 39 return obj 40 41 def inject_members(self, obj): 42 for name, clazz in self.kwargs.items(): 43 instance = self.get_instance(clazz) 44 if instance: setattr(obj, name, instance) 45 46 @abstractmethod 47 def get_instance(self, cls): ... 48 49 50 class InjectPrototype(Inject): 51 name = "InjectPrototype" 52 53 def get_instance(self, cls): 54 clazz = components.get(cls) 55 if clazz: return clazz() 56 raise KeyError(f"不存在类型{cls!r}") 57 58 59 class InjectSingleton(Inject): 60 _instances = {} 61 _lock = Lock() 62 _class_lock = {} 63 64 def get_instance(self, cls): 65 instance = self._instances.get(cls) 66 if not instance: 67 class_lock = self._class_lock.get(cls) 68 if not class_lock: 69 with self._lock: 70 class_lock = Lock() 71 self._class_lock[cls] = class_lock 72 with class_lock: 73 instance = self._instances.get(cls) 74 if not instance: 75 clazz = components.get(cls) 76 instance = clazz() 77 self._instances[cls] = instance 78 79 return instance 80 81 82 @Repository() 83 class UserRepository: 84 def get(self, key): 85 return f"User - {key!r}" 86 87 88 @Repository() 89 class ProductRepository: 90 def get(self, key): 91 return f"Product - {key!r}" 92 93 94 #类装饰器可以使用InjectPrototype替换, InjectSingleton是单例模式 95 InjectReplace = InjectSingleton 96 97 98 @InjectReplace(product_repository=ProductRepository) 99 @InjectReplace(user_repository=UserRepository) 100 @Service() 101 class EventService: 102 def update_info(self): 103 user = self.user_repository.get("Steven") 104 product = self.product_repository.get("Apple") 105 print(f"更新信息 {user} <> {product}") 106 # return f"更新信息 {user} <> {product}" 107 108 109 @InjectReplace(event_service=EventService) 110 class Client: 111 def execute(self): 112 self.event_service.update_info() 113 114 115 client = Client() 116 client2 = Client() 117 118 client.execute() 119 client2.execute() 120 121 print(id(client), id(client2)) 122 print(id(client.event_service), id(client2.event_service)) 123 print(id(client.event_service.user_repository), id(client2.event_service.user_repository)) 124 print(id(client.event_service.product_repository), id(client2.event_service.product_repository))
类装饰器参考: