gpt4 book ai didi

Python:从内部类访问外部私有(private)函数

转载 作者:行者123 更新时间:2023-11-28 20:04:28 25 4
gpt4 key购买 nike

我是不是遗漏了什么,或者像这样的东西是不可能的?

class Outer:
def __init__(self, val):
self.__val = val

def __getVal(self):
return self.__val

def getInner(self):
return self.Inner(self)

class Inner:
def __init__(self, outer):
self.__outer = outer

def getVal(self):
return self.__outer.__getVal()


foo = Outer('foo')
inner = foo.getInner()
val = inner.getVal()
print val

我收到此错误消息:

    return self.__outer.__getVal()
AttributeError: Outer instance has no attribute '_Inner__getVal'

最佳答案

您正在尝试将 Java 技术应用于 Python 类。不。 Python 没有像 Java 那样的隐私模型。类及其实例的所有属性总是可访问,即使在类中使用__name双下划线名称(它们只是重命名为添加命名空间)。

因此,您也不需要内部类,因为此类没有特权访问权限。您可以将该类放在外面 Outer 并具有完全相同的访问级别。

您遇到错误是因为 Python 重命名 类上下文中具有初始双下划线名称的属性,以避免与子类冲突。这些被称为 class private 因为重命名将类名添加为命名空间;这适用于它们的定义和使用。查看Reserved classes of identifiers section引用文档:

__*
Class-private names. Names in this category, when used within the context of a class definition, are re-written to use a mangled form to help avoid name clashes between “private” attributes of base and derived classes.

Outer 中所有带有双下划线的名称都被重命名为 _Outer 前缀,因此 __getVal 被重命名为 _Outer__getVal . Inner 中的任何此类名称都会发生同样的情况,因此您的 Inner.getVal() 方法将查找 _Inner__getVal 属性。由于 Outer 没有 _Inner__getVal 属性,因此您会收到错误消息。

您可以手动将相同的转换应用于 Inner.getVal() 以“修复”此错误:

def getVal(self):
return self.__outer._Outer__getVal()

但无论如何您都没有按预期使用双下划线名称,因此改用单下划线,并且不要使用嵌套类:

class Outer:
def __init__(self, val):
self._val = val

def _getVal(self):
return self._val

def getInner(self):
return _Inner(self)

class _Inner:
def __init__(self, outer):
self._outer = outer

def getVal(self):
return self._outer._getVal()

我将 Inner 重命名为 _Inner 以记录类型是内部实现细节。

虽然我们在讨论这个主题,但实际上也没有必要使用访问器。在 Python 中,您可以在 property objects 之间切换和普通属性随时。无需像在 Java 中那样进行防御性编码,在 Java 中,属性和访问器之间的切换会带来巨大的切换成本。在 Python 中,不要使用obj.getAttribute()obj.setAttribute(val) 方法。只需使用 obj.attributeobj.attribute = val,如果您需要做更多工作来生成或设置值,请使用 property。在您的开发周期中随意切换到或远离 property 对象。

因此,您可以将上面的内容进一步简化为:

class Outer(object):
def __init__(self, val):
self._val = val

@property
def inner(self):
return _Inner(self)

class _Inner(object):
def __init__(self, outer):
self._outer = outer

@property
def val(self):
return self._outer._val

此处 outer.inner 根据需要生成一个新的 _Inner() 实例,Inner.val 属性代理存储的 self._outer 引用。实例的用户永远不需要知道任何一个属性都由 property 对象处理:

>>> outer = Outer(42)
>>> print outer.inner.val
42

请注意,要使 property 在 Python 2 中正常工作,您必须使用新式类;从 object 继承来做到这一点;在 property 的旧式类上支持 getter(这意味着设置也不会被阻止!)。这是 Python 3 中的默认设置。

关于Python:从内部类访问外部私有(private)函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36601006/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com