【发布时间】:2021-12-02 18:53:49
【问题描述】:
我在保护我的属性(一个 numpy 数组)时遇到了问题。我想我明白为什么会出现这个问题,但我不确定如何防止它发生。特别是因为我的代码将被相对缺乏经验的程序员使用。
简而言之:,我有一个类,我想确保它的某些属性的属性。为此,我使用私有内部变量以及 getter 和 setter。然而,并非一切都如我所愿,当设置了一部分属性时,保护不起作用。
详细说明:这是 MWE 的第一部分:
# Importing modules.
import numpy as np
class OurClass(object):
"""
The class with an attribute that we want to protect.
Parameters
----------
n : int
The number of random numbers in the attribute.
Attributes
----------
our_attribute : array
The attribute that contains `n` random numbers between 0 and 1, will never be smaller than zero.
_our_attribute : array
The protected attributed that ensures that `our_attribute` is never smaller then zero.
(Normally I don't list this)
"""
def __init__(self, n):
self.our_attribute = np.random.random(n)
@property
def our_attribute(self):
return self._our_attribute
@our_attribute.setter
def our_attribute(self, value):
"""
When the attribute is set, every entry needs to be larger then zero.
Parameters
----------
value : array
The array that should replace our_attribute.
"""
print("Setter function is used")
self._our_attribute = np.clip(value, 0, np.inf)
现在,当我设置和获取 our_attribute 时,它应该受到保护,请参阅以下示例:
# Lets create our object.
print('Create object:')
num = 5
our_object = OurClass(num)
print(' our_attribute:', our_object.our_attribute, '\n')
# Lets replace the setter function te verify that it works.
print('Change object:')
our_object.our_attribute = np.linspace(-5, 20, num)
print(' our_attribute:', our_object.our_attribute, '\n')
# Now modify the attribute using basic functions.
print('Modify using numpy functionality:')
our_object.our_attribute = our_object.our_attribute - 5
print(' our_attribute:', our_object.our_attribute, '\n')
但是,当我处理属性的切片(视图)时,会发生奇怪的事情。
# Now modify a slice of the attribute, we can do this because it is a numpy array.
print('Modify a slice of the attribute.')
our_object.our_attribute[0] = -5
print(' our_attribute:', our_object.our_attribute)
发生了以下事情:
- 它调用 getter 函数两次,(一次用于
our_object.our_attribute[0],一次用于print) - 出现负数时,该属性似乎不受保护。
- 即使是私有属性似乎也没有受到保护
print(' even the private _our_attribute:', our_object._our_attribute, '\n')
也包括负数!
我的猜测:
- 属性的一部分不受保护,因为我们访问它并没有进入 setter 函数。 Numpy 允许我们直接访问切片并更改内容。 (我们从 getter 函数获得
our_attribute,现在我们直接作用于这个数组对象,它允许设置一个由 Numpy 处理的切片,而不是我们的类,因为我们正在作用的对象现在只是一个数组。 - getter 函数包括
return self._our_attribute,它不是复制操作,现在self.our_attribute和self._our_attribute都指向同一个位置。如果您更改其中任何一个,其他更改也会随之更改,因此我们最终会更改我们的私有属性,即使我们并不打算更改它。
现在我的问题:
- 我的推测是正确的,还是我犯了错误。
- 我假设我可以以不同的方式定义 setter,以确保私有属性与公共属性分开:
@property
def our_attribute(self):
return np.copy(self._our_attribute)
但现在设置切片根本不会改变任何东西。
如何正确保护我的属性,以便我可以更改属性的一部分并仍然保留保护。重要的是,这种保护从外面看不到,以免让我的学生感到困惑。
【问题讨论】:
标签: python numpy attributes private