这是我的问题。我想创建一个类,其中静态数组对于我的类的每个实例都是可见的,并且只创建一次。问题是这个数组没有常量维度,而是通过类的实例创建给定大小。
这是一个例子
class My(object):
def __init__(self, N):
self.a = My.arr(N)
@classmethod
def arr(cls, N):
return [i for i in range(0,N)]
问题是每个Instance都会有一个数组的副本。我想创建两个实例
p1 = My(5)
p2 = My(5)
但是应该创建一次数组并将其存储在内存中。当我指定不同的维度时,它应该创建另一个对于相同维度实例可见的数组。
答案 0 :(得分:0)
这样的事情可能有用,但我必须说它是一种非常奇特的设计模式:
class My(object):
_arrays = {}
def __init__(self, N):
self._dimension = N
self._arr(N)
def _arr(self, N):
if N not in self._arrays:
arr = [i for i in range(0,N)]
self._arrays[N] = arr
return self._arrays
@property
def a(self):
return self._arrays[self._dimension]
@a.setter
def a(self, new):
if len(new) != self._dimension:
raise ValueError('Wrong length, should be %d but was %d' %
(self._dimension, len(new)))
self._arrays[self._dimension] = new
if __name__ == '__main__':
a = My(5)
b = My(5)
c = My(10)
print "# Instances of the same size get the same array:"
print "a.a and b.a same instance: %r" % (a.a is b.a)
print "a.a and c.a same instance: %r" % (a.a is c.a)
a.a[0] = 'five'
c.a[0] = 'ten'
print "# Updating the arrays work:"
print "a array contents: %r" % a.a
print "b array contents: %r" % b.a
print "c array contents: %r" % c.a
a.a = list('abcde') # new array
print "# Changing the reference to a new array works:"
print "a array contents: %r" % a.a
print "b array contents: %r" % b.a
print "# Size is protected:"
a.a = [1, 2, 3]
在此类中,每次创建实例时,都会调用_arr
方法。它将在字典_arrays
中创建并存储一个正确长度的新数组,该字典是一个类成员。当访问或更改属性a
时,将查找当前实例的正确数组。
你也可以设置self.a = self._arrays[self._dimension]
,但是如果你试图分配一个像a.a = [1, 2, 3]
这样的新数组,那么它就不会工作,你也可能最终得到一个错误长度的数组。设定者负责检查。
输出如下:
# Instances of the same size get the same array:
a.a and b.a same instance: True
a.a and c.a same instance: False
# Updating the arrays work:
a array contents: ['five', 1, 2, 3, 4]
b array contents: ['five', 1, 2, 3, 4]
c array contents: ['ten', 1, 2, 3, 4, 5, 6, 7, 8, 9]
# Changing the reference to a new array works:
a array contents: ['a', 'b', 'c', 'd', 'e']
b array contents: ['a', 'b', 'c', 'd', 'e']
# Size is protected:
Traceback (most recent call last):
File "arrays.py", line 47, in <module>
a.a = [1, 2, 3]
File "arrays.py", line 22, in a
(self._dimension, len(new)))
ValueError: Wrong length, should be 5 but was 3
答案 1 :(得分:0)
这是另一种方法:
#!/usr/bin/env python
class My(object):
arraystore = {}
def __init__(self, n):
if not n in My.arraystore:
My.arraystore[n] = range(n)
self.a = My.arraystore[n]
a5 = My(5)
print a5.a, id(a5.a)
a5.a[3] *= 10
b5 = My(5)
print b5.a, id(b5.a)
c = My(7)
print c.a, id(c.a)
典型输出
[0, 1, 2, 3, 4] 3074609804
[0, 1, 2, 30, 4] 3074609804
[0, 1, 2, 3, 4, 5, 6] 3074604812
答案 2 :(得分:0)
你可以这样做:
class My(object):
a = None # shared class attribute
def __init__(self, N):
My.arr(N)
@classmethod
def arr(cls, N):
if cls.a is None:
cls.a = list(range(N))
elif len(cls.a) != N:
raise ValueError('attempt to change dimension of "a"')
p1 = My(5)
p2 = My(5)
p1.a[0] = 42
print(p1.a) # --> [42, 1, 2, 3, 4]
print(p2.a) # --> [42, 1, 2, 3, 4]