我知道在Python中没有正式的方法来引入类的私有属性,通常你只是通过在前面添加下划线来表示私有属性
_
。
我有一个如下所示的课程:
class my_class:
def __init__(self):
self._attr1 = # some initialization
def method_that_merges_another_class_instance(self, other):
# I want to access other's _attr1 attribute in here even though it's private.
可以从
_attr1
内的其他人直接访问method_that_merges_another_class_instance
吗?
在Python中,有私有属性(即双前导下划线)和半私有属性(即单前导下划线),但仅限于约定(即私有属性在功能上是
_ClassName.__private_attribute
并且可以通过instance.__private_attribute
以外的方式访问)会引发错误,并且仍然可以通过 instance.__dict__
访问)。
实例属性(即带有
self
前缀的属性)对于每个实例都是唯一的,因此这里实例 a
和 b
(属于 Class
A
和 Class
B
)都具有 foo
作为实例属性:
class A:
def __init__(self, **kwargs):
self.__dict__.update(**kwargs)
class B:
def __init__(self, **kwargs):
self.__dict__.update(**kwargs)
a = A(foo=0)
b = B(foo=1000)
但是我们可以看到
foo
的值对于每个实例都是唯一的(即 a
和 b
):
print(a.__dict__)
print(b.__dict__)
输出:
{'foo': 0}
{'foo': 1000}
如果您想从
other
实例访问实例属性,我们可以像您一样简单地传递实例(例如,将实例 a
传递给 some_function
Class
和实例 B
的方法 b
) :
class A:
def __init__(self, **kwargs):
self.__dict__.update(**kwargs)
class B:
def __init__(self, **kwargs):
self.__dict__.update(**kwargs)
def some_function(self, other=None):
if other is None:
return self.__dict__
return other.__dict__
a = A(foo=0)
b = B(foo=1000)
print(b.some_function(other=a))
输出:
{'foo': 0}
这可以接受吗?当然。在这个(非常简单)的背景下它可以接受吗?也许,我们可以使用属性所属的实例来访问该属性,但在我们的示例中,
foo
在各个实例中具有不同的值。使用预期的私有属性是否可以接受?当然,因为该属性在其他类的实例上是该类的私有属性,并且变量名称(例如 __foo
)与其类(例如 _B.__foo
)一起定义,因此它不会与定义的另一个 __foo
混淆在另一个班级。这些名称修改规则是为了避免派生类或类外部定义的实例变量发生冲突。结论是,在 Python 中,私有属性并不是真正的私有,它只是为了避免变量命名冲突。
在面向对象编程中,私有成员和受保护成员分别是。为类而不是实例私有和受保护。这意味着它们只能从该类的方法(对于私有成员)或从该类和子类(对于受保护的成员)使用。
因此,使用它们来访问不同实例的私有属性(在Python中是
self
以外的实例)是完全可以的。这甚至是比较或其他操作等特殊方法的标准方法。
在示例代码中明确说明:
class my_class:
def __init__(self):
self._attr1 = # some initialization
def method_that_merges_another_class_instance(self, other):
# other is expected to be a my_class instance: we may use its _attr1 member.
self._attr1 = other._attr1 # standard way to copy a private attribute