设置属性和调用就地变异方法之间的区别?

时间:2013-02-21 00:47:34

标签: python class numpy oop attributes

我主要使用numpy进行数据分析,不了解底层程序,所以这可能是显而易见的。

我不明白通过简单地分配属性来设置属性与调用在原地更改该属性的方法之间的区别。您可以同时执行这两个操作的示例是:

In [1]: import numpy as np

In [2]: a = np.array([[1, 2, 3],
   ...:               [4, 5, 6]])

In [3]: a.shape
Out[3]: (2, 3)

In [4]: a.reshape(3,2)
Out[4]: 
array([[1, 2],
       [3, 4],
       [5, 6]])

In [5]: a
Out[5]: 
array([[1, 2, 3],
       [4, 5, 6]])

In [6]: a.resize(3,2)

In [7]: a
Out[7]: 
array([[1, 2],
       [3, 4],
       [5, 6]])

In [8]: a.shape = (6,)

In [9]: a
Out[9]: array([1, 2, 3, 4, 5, 6])

In [10]: a.__setattr__('shape',(3,2))

In [11]: a
Out[11]: 
array([[1, 2],
       [3, 4],
       [5, 6]])

我不明白输入68之间的区别。显然,两者都会更改a.shape属性,而不是像4那样返回重新整形的对象。他们是否只在a.__setattr__()中拨打10?如果是这样,为什么它们都存在?

(我知道a.resize()有额外的容量可以增加或减少分配的内存,但是我在这里没有使用它 - 这种双重性是否仅存在,并且该方法增加了一些其他容量?)

2 个答案:

答案 0 :(得分:2)

8中的示例实际上称为property,python允许您访问版本2.1 +。

e.g。

@property
def shape(self):
    """I'm the 'shape' property."""
    return self._shape

@shape.setter
def shape(self, value):
    self._shape = value

__setattr__调用setter

x.__setattr__('shape', value) 

相当于(查看上面的属性设置器)。

x.shape = value

底层逻辑总是调用修饰符函数。

答案 1 :(得分:1)

我现在已多次阅读你的问题并认为我可以解决所有问题:

a.reshape(3,2)
# returns a new array

a.resize(3,2)
# returns None, operates on the same array
# (equivalent to modifying ndarray.shape here since no. of elements is unchanged)

a.shape = (6,)
# operates on the same array, uses property trick to hide detailed 
# setter logic behind normal attribute access.  
# note the parens are unnecessary here - equivalent is a.shape = 6,
# NOT equivalent to a = a.reshape(6,), which would change the id(a)

a.__setattr__('shape',(3,2))
# just an ugly way of doing a.shape = 3,2

您的主要问题似乎是关于更改阵列形状的方法的非唯一性。

  

显然两者都改变​​了a.shape属性,而不像4中那样返回重塑的对象

是。或者更确切地说,两者都改变​​了数组(并且shape“属性”返回的值被修改为结果)。

  

他们是否只在10 a.__setattr__()上打电话?

他们没有必要拨打a.__setattr__(...)。他们可以更改一些内部self._shape变量,它仍然可以改变a.shape返回的内容。

您可以通过创建自己的类来查看实际使用__setattr__的人,例如:

class my_ndarray(np.ndarray):
    def __setattr__(self, name, value):
        print '__setattr__ called with name={}, value={}'.format(name, value)
        super(my_ndarray, self).__setattr__(name, value)

a_ = my_ndarray(a.shape)
a_[:] = a

在这种情况下,答案是a_.resizea_.reshape都不使用__setattr__

  

如果是这样,为什么它们都存在?

resize可以做的不仅仅是当元素数量不同时重塑,这对我来说是足够的理由。当你需要做的就是使用reshape时,使用resize会很奇怪,但是为什么numpy(应该是高性能的)在你“可能”使用reshape时要么警告你或者人为地限制你使用resize代替?

如果您担心明显违反了#13>#13 的 zen,numpy不是寻找一致性的最佳位置。例如,只需比较np.eyenp.identity!什么是numpythonic并不总是pythonic。