python中枚举类型个性化用法
摘要:枚举类型可以看作是一种标签或是一系列常量的集合,通常用于表示某些特定的有限集合,例如星期、月份、状态等。本文采用继承自enum模块的Enum类, 实现了一些个性化的设置, 如枚举类型的初始化。
对于enum类,接触python应该都有使用:
举个栗子:
class Week(enum.Enum): Mon = 0 Tue = 1 Wed = 2 Thr = 3 Fri = 4 Sat = 5 San = 6 Monday = Week.Mon print(Monday) print(Monday.name) print(Monday.value)
输出结果为:
Week.Mon
Mon
0
有没有想过这样一个问题, 假设现在我要创建一个Week类型的变量,但是需要接收外部参数对它初始化,怎么去实现呢?既然Week是python中的类,能否使用 像student = Student(name='Li')这样的格式 通过 _init__() 方法实例化一个变量呢?笔者进行了__init__()方法重写,但是一直报错,于是去看了 enum.py的源码, 发现 Enum中只有 构造方法__new__()但并未找到其初始化方法__init__(),源码也比较复杂,因能力有限看了半天也未想出通过 __init__ 来实现的方式。
百思不得其解之后,笔者另辟蹊径,想到通过类中的静态方法来实现这一功能, 代码如下:
class Week(enum.Enum): Mon = 0 Tue = 1 Wed = 2 Thr = 3 Fri = 4 Sat = 5 San = 6 @staticmethod def my_init(value): return [x for x in filter(lambda w: w.name == value, Week)][0] Tuesday = Week.my_init('Tue') print(Tuesday) print(Tuesday.name) print(Tuesday.value)
输出结果为:
Week.Tue
Tue
1
或许有人看到这篇文章之后会觉得这个初始化方法是不是很啰嗦或者觉得没必要, 下面笔者就将看到的面试题以及笔者自己写的代码附在此处,希望能得到交流以及改进建议。代码中编写了两个类 Tanks 和 Direction, Tanks引用了Direction中的my_init()方法实现坦克信息的厨师化。
代码如下:
面试题(大体意思):某次战役中, 我军将关键高地坐标定为(x=0, y=0)并规定, 每向东增加 100 米, x 加 1, 每向北增加 100 米, y 加 1 。我军破译了敌军向坦克发送的指挥信号(L, R, M)用于控制坦克的运动, L 和 R 表示坦克向左, 向右转向, M 表示直线开进 100 米,其他信号如 T 用于时间同步, P 用于位置校准。
一日, 侦察兵发现了敌军的一辆坦克,立即将坦克所在坐标 (P, Q) 及坦克前进方向发送给指挥部, ( W: 西, E: 东, N: 北, S: 南 ) ,同时启动信号接收器,将坦克接收到的信号实时同步发往指挥部, 指挥部根据这些信息得以实时掌控了该坦克的位置,并使用榴弹炮精准地击毁了该坦克。
编写程序, 根据坦克接收到的信号, 推断出坦克所在的位置。假设, 坦克坐标为(11,39)运行方向为W,当收到以下信号 'MTMPRPMTMLMRPRMTPLMMTLMRRMP' , 其坐标应该为(9,43),运行方向为E 。
import enum class Direction(enum.Enum): ''' 方向类 重写了 __str__ 和 __add__ 通过 + 重载, 实现方向加法 例: N + 'R' = E, N + 'L' = W ''' N = (0, 1) E = (1, 0) S = (0, -1) W = (-1, 0) def __add__(self, value): lst = [x for x in Direction] index = lst.index(self) if value == 'R': return lst[(index + 1) % 4] elif value == 'L': return lst[index - 1] else: raise 'DirectionOrderError' def __iadd__(self, value): return self + value def __str__(self): return self.name @staticmethod def my_init(d): ''' 个性初始化方法 例: my_init('N') -> <Direction.N: (0, 1)> ''' return [x for x in filter(lambda x: x.name == d, Direction)][0] class Tank(object): ''' 坦克类 坦克类实例化时支持 初始位置 和 运行方向 初始化 坦克接收信号并根据信号指示运动到新的位置 假设, 坦克坐标为(20,40)运行方向为S,当收到以下信号 'MTMMPLTPMTMLMRMPRMTPLMMTLMRRMTRMP', 其坐标应该为(24, 37),运行方向为W ''' def __init__(self, orign=[0, 0], direction='N'): self.position = orign self.orign = orign self.direction = Direction.my_init(direction) self.history_signs = '' def __str__(self): return '\nPosition: {}, Direction: {}.\n'\ .format(tuple(self.position), self.direction) def signs_handler(self, signs=''): for sig in signs: if sig in ['L', 'R']: # print('turn left' if sig == 'L' else 'turn right') self.direction += sig elif sig == 'M': self.__go() elif sig == 'T': self.__adjust_time() elif sig == 'P': self.__adjust_position() else: raise 'SignalError' self.history_signs += signs def update_position(self, new_signs): self.signs_handler(new_signs) def __go(self): self.position = [p_old + p_new for p_old, p_new in zip(self.position, self.direction.value)] def __adjust_time(self): '''预留时间校准接口''' print('adjust Time') def __adjust_position(self): '''预留位置校准接口''' print('adjust Position') def __destory_tank(self): '''预留摧毁坦克接口''' passif __name__ == '__main__': tank = Tank((20, 40), 'S') sigs = 'MTMMPLTPMTMLMRMPRMTPLMMTLMRRMTRMP' tank.update_position(sigs) print(tank)
最后,版权声明:输出结果:
Position: (24, 37), Direction: W.
本blog是笔者根据在网络上看到的某企业面试题为背景编写的代码, 谨用于关于python中enum类的学习经验交流,无作他用。如需转载请注明出处,同时本blog中涉及到的面试题严禁用于他用。