在 python 中是否可以强制为包含 -5 到 256 之间整数的变量设置唯一 ID?
Possible to force unique IDs to variables containing integers between -5 and 256 in python?
我有一个 class 有几个命名属性。我希望能够将 classes 属性之一传递给自身,并能够具体确定传递了哪个属性。
下面是我如何做的一个简单示例(使用 "is" 运算符),直到我发现特殊的缓存变量 ID 用于 -5 到 256 之间的整数值。
class AClass:
def __init__(self, one, two, three):
self.one = one
self.two = two
self.three = three
def getIndex(self, attribute):
if attribute is self.one:
return 1
elif attribute is self.two:
return 2
elif attribute is self.three:
return 3
def setByIndex(self, i, value):
if i == 1:
self.one = value
elif i == 2:
self.two = value
elif i == 3:
self.three = value
def setByAttrib(self, attribute, value):
i = self.getIndex(attribute)
self.setByIndex(i, value)
object = AClass(0, 0, 0)
object.setByAttrib(object.three, 10)
在上面的例子中,意图是将object.three设置为10。但是,由于所有属性都指向整数 0 的缓存位置,getIndex 函数将对其中任何一个求值为真,而 object.one(最先出现的)将设置为 10.如果使用值 257、257、257 初始化对象,功能大概会如预期的那样。
所以问题是,有没有办法:
a) 强制系统为这些属性分配非缓存的唯一内存位置(即使它们设置在 -5 和 256 之间),或
b) 使用其他方法检查作为参数传递的属性本身是否唯一?
编辑:
因为它被问过几次,我使用这个范例的原因之一是 python 中缺少指针。在上面的例子中,setByIndex 函数可能会对属性做一些复杂的工作。与其为每个变量编写多个相同的函数(例如 setOne、setTwo、setThree),我可以编写一个通过索引检索和设置的通用函数(索引基本上就像一个指针)。是的,我可以将属性值作为参数和 return 新设置值传递,并在已知特定属性的范围内进行赋值,但我已经 return 了一个值。是的,我可以 return 一个列表,但它增加了更多的复杂性。
我确实意识到有更好的方法来实现我需要的东西(例如,属性和索引号的键值对),但是实现起来需要做很多工作(数以千计的更改)。如果有办法使用可变 ID 作为我的唯一标识符并继续使用 "is" 运算符(或类似的),我就不需要做太多更改。虽然看起来不太可能。欣赏 comments/responses.
我不会担心内存位置,它们只是这里的一个实现细节。这实际上是关于函数设计的,所以如果你想设置 object.three
,那么就这样做,否则,如果你想的话,你可以创建一个到索引的映射:
class MyClass:
def __init__(self, *args):
self.one, self.two, self.three, *_ = args
# get an object by it's index
def get_by_index(self, index):
# here's how you could create such a mapping
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
return getattr(self, opts[index])
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# if you want to set by an index, then do that this way
def set_by_index(self, index, val):
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
setattr(self, opts[index], val)
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# otherwise, just set the attribute by the name
a = MyClass(0, 0, 0)
a.three = 55
事实是,你是对的,is
将以相同的方式查看三个 0
,因为它从一开始就没有复制该数据。 one, two, three
指向相同的数据,因为它们被分配了相同的数据。再次分配该属性后,您实际上将该属性重新绑定到 新 值,而不是更新现有值。
重要的是,不用担心哪里内存用于此实现,只需针对属性明确设置
我有一个 class 有几个命名属性。我希望能够将 classes 属性之一传递给自身,并能够具体确定传递了哪个属性。
下面是我如何做的一个简单示例(使用 "is" 运算符),直到我发现特殊的缓存变量 ID 用于 -5 到 256 之间的整数值。
class AClass:
def __init__(self, one, two, three):
self.one = one
self.two = two
self.three = three
def getIndex(self, attribute):
if attribute is self.one:
return 1
elif attribute is self.two:
return 2
elif attribute is self.three:
return 3
def setByIndex(self, i, value):
if i == 1:
self.one = value
elif i == 2:
self.two = value
elif i == 3:
self.three = value
def setByAttrib(self, attribute, value):
i = self.getIndex(attribute)
self.setByIndex(i, value)
object = AClass(0, 0, 0)
object.setByAttrib(object.three, 10)
在上面的例子中,意图是将object.three设置为10。但是,由于所有属性都指向整数 0 的缓存位置,getIndex 函数将对其中任何一个求值为真,而 object.one(最先出现的)将设置为 10.如果使用值 257、257、257 初始化对象,功能大概会如预期的那样。
所以问题是,有没有办法:
a) 强制系统为这些属性分配非缓存的唯一内存位置(即使它们设置在 -5 和 256 之间),或
b) 使用其他方法检查作为参数传递的属性本身是否唯一?
编辑:
因为它被问过几次,我使用这个范例的原因之一是 python 中缺少指针。在上面的例子中,setByIndex 函数可能会对属性做一些复杂的工作。与其为每个变量编写多个相同的函数(例如 setOne、setTwo、setThree),我可以编写一个通过索引检索和设置的通用函数(索引基本上就像一个指针)。是的,我可以将属性值作为参数和 return 新设置值传递,并在已知特定属性的范围内进行赋值,但我已经 return 了一个值。是的,我可以 return 一个列表,但它增加了更多的复杂性。
我确实意识到有更好的方法来实现我需要的东西(例如,属性和索引号的键值对),但是实现起来需要做很多工作(数以千计的更改)。如果有办法使用可变 ID 作为我的唯一标识符并继续使用 "is" 运算符(或类似的),我就不需要做太多更改。虽然看起来不太可能。欣赏 comments/responses.
我不会担心内存位置,它们只是这里的一个实现细节。这实际上是关于函数设计的,所以如果你想设置 object.three
,那么就这样做,否则,如果你想的话,你可以创建一个到索引的映射:
class MyClass:
def __init__(self, *args):
self.one, self.two, self.three, *_ = args
# get an object by it's index
def get_by_index(self, index):
# here's how you could create such a mapping
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
return getattr(self, opts[index])
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# if you want to set by an index, then do that this way
def set_by_index(self, index, val):
opts = dict(zip((1, 2, 3), ('one', 'two', 'three')))
try:
setattr(self, opts[index], val)
except KeyError as e:
raise ValueError(f"Improper alias for attribute, select one of {', '.join(opts)}") from e
# otherwise, just set the attribute by the name
a = MyClass(0, 0, 0)
a.three = 55
事实是,你是对的,is
将以相同的方式查看三个 0
,因为它从一开始就没有复制该数据。 one, two, three
指向相同的数据,因为它们被分配了相同的数据。再次分配该属性后,您实际上将该属性重新绑定到 新 值,而不是更新现有值。
重要的是,不用担心哪里内存用于此实现,只需针对属性明确设置