简体   繁体   English

指向相同阵列的实例

[英]Instances pointing to the same array

here is my problem. 这是我的问题。 I want to create a class which with static array visible for every instance of my class and created only once. 我想创建一个类,该类的静态数组对于我的类的每个实例可见,并且只能创建一次。 The problem is this array does not have constant dimension but instead it will be created with given size by instance of class. 问题是此数组没有恒定的维数,而是由类的实例以给定的大小创建它。

Here is an example 这是一个例子

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)]

The problem is every Instance will have a copy of the array. 问题在于每个实例都将拥有该阵列的副本。 I would like to create let's say two instances 我想创建两个实例

p1 = My(5)
p2 = My(5)

But the array should be created once and stored somewhere in a memory. 但是该数组应创建一次并存储在内存中的某个位置。 When I specify different dimension it should create another array which would be visible for the same dimension instances. 当我指定不同的维度时,应创建另一个数组,该数组对于相同的维度实例将是可见的。

Something like this might work, but I must say it's a very peculiar design pattern: 这样的事情可能会起作用,但是我必须说这是一个非常特殊的设计模式:

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]

In this class, each time an instance is created, the _arr method is called. 在此类中,每次创建实例时, _arr调用_arr方法。 It will create and store a new array of the correct length in the dictionary _arrays , which is a class member. 它将创建正确长度的新数组并将其存储在字典_arrays ,该数组是类成员。 The correct array for the current instance is looked up when the property a is accessed or changed. 当访问或更改属性a时,将查找当前实例的正确数组。

You could also set self.a = self._arrays[self._dimension] but it won't work if you try to assign a new array like aa = [1, 2, 3] and you might also end up with an array of the wrong length. 您也可以设置self.a = self._arrays[self._dimension]但是如果您尝试分配一个新的数组,例如aa = [1, 2, 3] self.a = self._arrays[self._dimension] ,则此方法将不起作用aa = [1, 2, 3]并且可能还会得到一个错误的长度。 The setter takes care of checking that. 设置器负责检查。

The output looks like this: 输出看起来像这样:

# 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

Here's another way to do it: 这是另一种方法:

#!/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)

typical output 典型输出

[0, 1, 2, 3, 4] 3074609804
[0, 1, 2, 30, 4] 3074609804
[0, 1, 2, 3, 4, 5, 6] 3074604812

You could do it like this: 您可以这样做:

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM