我有一个基本上是具有一些额外属性的 int 的对象。当它用作列表索引时,我可以将它强制转换为 int 吗?
I've got an object that is basically an int with some extra properties. Can I coerce it into an int when it's used as a list index?
上下文:我正在制作一款发生在方形方块迷宫中的游戏,从移动到攻击,几乎所有内容都涉及方向,这些方向主要用于索引列表。减去或添加方向是左转或右转的简单方法,但我总是必须检查它们是否仍在范围内,我想通过自定义 class.
来自动执行此操作
这是我目前的做法:
global UP
UP = 0
global RIGHT
RIGHT = 1
global DOWN
DOWN = 2
global LEFT
LEFT = 3
这是我想做的事情:
class Direction:
number_of_directions=4
def __init__(self,direction):
self.direction = direction
def __int__(self):
return self.direction
def __add__(self,other): #Here other is supposed to be an int
return (self.direction + other)%number_of_directions
def __sub__(self,other): #Here other is supposed to be an int
return (self.direction - other)%number_of_directions
global UP
UP = Direction(0)
global LEFT
LEFT = Direction(1)
global DOWN
DOWN = Direction(2)
global RIGHT
RIGHT = Direction(3)
唯一的问题是我使用 UP
、RIGHT
等作为索引,就像我有一个 Tile
的列表,其中包含四个 [=15] =] 并且我经常调用 Tile.walls[direction]
,方向是我的四个常量之一,我不想每次都指定 Tile.walls[int(direction)]
。
有没有办法让 direction
在用于索引时自动强制转换为 int?
你可以使用 IntEnum
:
from enum import IntEnum
from numbers import Integral
class Direction(IntEnum):
UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3
_NB_DIRECTIONS = 4
def __add__(self, other):
if isinstance(other, Integral):
return Direction((self.value + other) % Direction._NB_DIRECTIONS)
return NotImplemented
def __sub__(self, other):
if isinstance(other, Integral):
return Direction((self.value - other) % Direction._NB_DIRECTIONS)
return NotImplemented
那些是 int
的子类,可用于例如作为列表的索引:
lst = list(range(4))
print(lst[Direction.LEFT]) # -> 3
你举的例子是这样的:
print(Direction.UP) # Direction.UP
print(Direction.UP + 1) # Direction.RIGHT
print(Direction.UP - 1) # Direction.LEFT
print(Direction.UP + 10) # Direction.DOWN
a = Direction.UP
a += 1
print(a) # Direction.RIGHT
print(Direction.UP) # Direction.UP
print(type(a)) # <enum 'Direction'>
b = 1
print(type(b)) # <class 'int'>
b += Direction.UP
print(b) # 1
print(type(b)) # <class 'int'>
print(Direction.DOWN - 1 == Direction.UP + 1) # True
lst = ["zero", "one", "two", "three"]
print(lst[Direction.DOWN]) # 'two'
print(lst[Direction.UP + 3]) # 'three'
print(lst[Direction.LEFT - 2]) # 'one'
我通过将 Direction
设为 int
的子 class 来让我的代码工作。
这是我当前的代码:
global NB_DIRECTIONS
NB_DIRECTIONS = 4
(这部分有点多余,以防万一我以后想用六边形或三角形而不是正方形来改编游戏。真正的代码现在开始。)
class Direction(int):
directions = NB_DIRECTIONS
def __init__(self,direction):
self.direction = direction
def __add__(self,other):
if isinstance(other,int):
return Direction((self.direction+other)%self.directions)
return NotImplemented
def __radd__(self,other):
if isinstance(other,int):
return Direction((other+self.direction)%self.directions)
return NotImplemented
def __sub__(self,other):
if isinstance(other,int):
return Direction((self.direction-other)%self.directions)
return NotImplemented
def __rsub__(self,other):
return NotImplemented
def __eq__(self, other):
if isinstance(other,Direction):
return self.direction == other.direction
return NotImplemented
global UP
UP=Direction(0)
global RIGHT
RIGHT=Direction(1)
global DOWN
DOWN=Direction(2)
global LEFT
LEFT=Direction(3)
(我在一个 Direction
对象和一个 int
对象之间做了添加,而不是在两个 Direction
对象之间添加,因为它对我正在做的事情更有意义,但是这与我试图解决的索引问题无关。)
让我们看看我的 Direction
的行为:
>>> UP
0
>>> UP+1
1
>>> UP-1
3
>>> UP+10
2
>>> a=UP
>>> a+=1
>>> a
1
>>> UP
0
>>> type(a)
<class '__main__.Direction'>
>>> b=1
>>> type(b)
<class 'int'>
>>> b+=UP
>>> b
1
>>> UP
0
>>> type(b)
<class '__main__.Direction'>
>>> DOWN-1==UP+1
True
>>> lst=["zero","one","two","three"]
>>> lst[DOWN]
'two'
>>> lst[UP+3]
'three'
>>> lst[LEFT-2]
'one'
>>> type(RIGHT)
<class '__main__.Direction'>
长话短说;博士:
我让我的 class 继承自 int
,现在它可以用作索引。
是的,简单定义__index__()
。例如:
class Direction:
def __init__(self, direction):
self.direction = direction
def __index__(self):
return self.direction
UP = Direction(0)
cardinals = ['north', 'east', 'south', 'west']
print(cardinals[UP]) # -> north
这也使得 __int__
变得不必要,因为 __index__
被用作后备。
print(int(UP)) # -> 0
P.S。对于这个答案,我忽略了任何设计考虑。使用 IntEnum
可能是更好的解决方案,我不确定。
上下文:我正在制作一款发生在方形方块迷宫中的游戏,从移动到攻击,几乎所有内容都涉及方向,这些方向主要用于索引列表。减去或添加方向是左转或右转的简单方法,但我总是必须检查它们是否仍在范围内,我想通过自定义 class.
来自动执行此操作这是我目前的做法:
global UP
UP = 0
global RIGHT
RIGHT = 1
global DOWN
DOWN = 2
global LEFT
LEFT = 3
这是我想做的事情:
class Direction:
number_of_directions=4
def __init__(self,direction):
self.direction = direction
def __int__(self):
return self.direction
def __add__(self,other): #Here other is supposed to be an int
return (self.direction + other)%number_of_directions
def __sub__(self,other): #Here other is supposed to be an int
return (self.direction - other)%number_of_directions
global UP
UP = Direction(0)
global LEFT
LEFT = Direction(1)
global DOWN
DOWN = Direction(2)
global RIGHT
RIGHT = Direction(3)
唯一的问题是我使用 UP
、RIGHT
等作为索引,就像我有一个 Tile
的列表,其中包含四个 [=15] =] 并且我经常调用 Tile.walls[direction]
,方向是我的四个常量之一,我不想每次都指定 Tile.walls[int(direction)]
。
有没有办法让 direction
在用于索引时自动强制转换为 int?
你可以使用 IntEnum
:
from enum import IntEnum
from numbers import Integral
class Direction(IntEnum):
UP = 0
RIGHT = 1
DOWN = 2
LEFT = 3
_NB_DIRECTIONS = 4
def __add__(self, other):
if isinstance(other, Integral):
return Direction((self.value + other) % Direction._NB_DIRECTIONS)
return NotImplemented
def __sub__(self, other):
if isinstance(other, Integral):
return Direction((self.value - other) % Direction._NB_DIRECTIONS)
return NotImplemented
那些是 int
的子类,可用于例如作为列表的索引:
lst = list(range(4))
print(lst[Direction.LEFT]) # -> 3
你举的例子是这样的:
print(Direction.UP) # Direction.UP
print(Direction.UP + 1) # Direction.RIGHT
print(Direction.UP - 1) # Direction.LEFT
print(Direction.UP + 10) # Direction.DOWN
a = Direction.UP
a += 1
print(a) # Direction.RIGHT
print(Direction.UP) # Direction.UP
print(type(a)) # <enum 'Direction'>
b = 1
print(type(b)) # <class 'int'>
b += Direction.UP
print(b) # 1
print(type(b)) # <class 'int'>
print(Direction.DOWN - 1 == Direction.UP + 1) # True
lst = ["zero", "one", "two", "three"]
print(lst[Direction.DOWN]) # 'two'
print(lst[Direction.UP + 3]) # 'three'
print(lst[Direction.LEFT - 2]) # 'one'
我通过将 Direction
设为 int
的子 class 来让我的代码工作。
这是我当前的代码:
global NB_DIRECTIONS
NB_DIRECTIONS = 4
(这部分有点多余,以防万一我以后想用六边形或三角形而不是正方形来改编游戏。真正的代码现在开始。)
class Direction(int):
directions = NB_DIRECTIONS
def __init__(self,direction):
self.direction = direction
def __add__(self,other):
if isinstance(other,int):
return Direction((self.direction+other)%self.directions)
return NotImplemented
def __radd__(self,other):
if isinstance(other,int):
return Direction((other+self.direction)%self.directions)
return NotImplemented
def __sub__(self,other):
if isinstance(other,int):
return Direction((self.direction-other)%self.directions)
return NotImplemented
def __rsub__(self,other):
return NotImplemented
def __eq__(self, other):
if isinstance(other,Direction):
return self.direction == other.direction
return NotImplemented
global UP
UP=Direction(0)
global RIGHT
RIGHT=Direction(1)
global DOWN
DOWN=Direction(2)
global LEFT
LEFT=Direction(3)
(我在一个 Direction
对象和一个 int
对象之间做了添加,而不是在两个 Direction
对象之间添加,因为它对我正在做的事情更有意义,但是这与我试图解决的索引问题无关。)
让我们看看我的 Direction
的行为:
>>> UP
0
>>> UP+1
1
>>> UP-1
3
>>> UP+10
2
>>> a=UP
>>> a+=1
>>> a
1
>>> UP
0
>>> type(a)
<class '__main__.Direction'>
>>> b=1
>>> type(b)
<class 'int'>
>>> b+=UP
>>> b
1
>>> UP
0
>>> type(b)
<class '__main__.Direction'>
>>> DOWN-1==UP+1
True
>>> lst=["zero","one","two","three"]
>>> lst[DOWN]
'two'
>>> lst[UP+3]
'three'
>>> lst[LEFT-2]
'one'
>>> type(RIGHT)
<class '__main__.Direction'>
长话短说;博士:
我让我的 class 继承自 int
,现在它可以用作索引。
是的,简单定义__index__()
。例如:
class Direction:
def __init__(self, direction):
self.direction = direction
def __index__(self):
return self.direction
UP = Direction(0)
cardinals = ['north', 'east', 'south', 'west']
print(cardinals[UP]) # -> north
这也使得 __int__
变得不必要,因为 __index__
被用作后备。
print(int(UP)) # -> 0
P.S。对于这个答案,我忽略了任何设计考虑。使用 IntEnum
可能是更好的解决方案,我不确定。