Python中私有名称损坏的好处是什么?

Python中私有名称损坏的好处是什么?,python,private-members,name-mangling,Python,Private Members,Name Mangling,Python提供了类方法和属性 有没有具体的情况需要这个特性,或者只是java和C++ ++的继承? 请描述一个应该使用Python名称篡改的用例,如果有的话? 另外,我对作者只是试图防止意外的外部属性访问的情况不感兴趣。我认为这个用例不符合Python编程模型。名称mangling是为了防止意外的外部属性访问。主要是为了确保没有名称冲突。部分是为了防止意外的内部属性访问。下面是一个例子: 在代码(即库)中: class YourClass: def __init__(self):

Python提供了类方法和属性

有没有具体的情况需要这个特性,或者只是java和C++ ++的继承? 请描述一个应该使用Python名称篡改的用例,如果有的话?


另外,我对作者只是试图防止意外的外部属性访问的情况不感兴趣。我认为这个用例不符合Python编程模型。

名称mangling是为了防止意外的外部属性访问。主要是为了确保没有名称冲突。

部分是为了防止意外的内部属性访问。下面是一个例子:

在代码(即库)中:

class YourClass:
    def __init__(self):
        self.__thing = 1           # Your private member, not part of your API
在我从库类继承的代码中:

class MyClass(YourClass):
    def __init__(self):
        # ...
        self.__thing = "My thing"  # My private member; the name is a coincidence
如果没有私人姓名的损坏,我无意中重复使用您的姓名将破坏您的库。

来自:

如果你的类是要被子类化的,并且你有属性,你不想使用子类,考虑用双领先下划线命名它们,没有尾随下划线。这将调用Python的名称篡改算法,其中类的名称被篡改为属性名如果子类无意中包含同名属性,这有助于避免属性名称冲突。


(增加了强调)

前面的所有答案都是正确的,但这里有一个例子说明另一个原因。python中需要名称混乱,因为这样可以避免重写属性可能导致的问题。换句话说,为了重写,Python解释器必须能够为子方法和父方法构建不同的id,并使用_uu(双下划线)使Python能够做到这一点。在下面的示例中,如果没有帮助,此代码将无法工作

class Parent:
    def __init__(self):
       self.__help("will take child to school")
    def help(self, activities):
        print("parent",activities)

    __help = help   # private copy of original help() method

class Child(Parent):
    def help(self, activities, days):   # notice this has 3 arguments and overrides the Parent.help()
        self.activities = activities
        self.days = days
        print ("child will do",self.activities, self.days)


# the goal was to extend and override the Parent class to list the child activities too
print ("list parent & child responsibilities")
c = Child()
c.help("laundry","Saturdays")

在我看来,你的类应该定义什么,而不是什么。这将允许MyClass访问它。第二,如果担心YourClass实现会发生变化,我认为在MyClass中使用“\u thing”有好处。唯一的问题是,如果有人想为MyClass创建子类,那么您就让他们更难访问“MyClass.\u thing”。这感觉就像是在牺牲未来的重用,以防止出现“想象中的”问题。否?@Casey:你说得对,有些成员变量希望子类可以看到,而这些变量的名称只有一个下划线。您可以在C++中使它们成为代码>保护< /代码>。但也有一些成员您不希望对子类可见,因为它们是类的私有实现的一部分(正如您所说,它们受到实现更改的影响)。“mangling”就是这个名字的意思。这不是一个想象中的问题;事实上,我已经完全做到了我所说的,一个库使用了一个下划线而不是一个双下划线作为私有成员。@RichieHindle:完全正确。除非这是一个外部访问。;)子类在这里被视为外部的,“私有”实现细节不是任意的吗?如果我正在创建一个基类来分发给世界,而我无法想象所有可能的使用场景,那么我如何才能可靠地选择哪些属性是“受保护的”,哪些属性是“私有的”。最后,总会有人需要访问变量来扩展/增强类的原因。使用损坏的属性名称,没有任何好处,只会迫使下一个人将其清除。我认为我们必须同意在这一点上有所不同。IMHO,一个编写良好的库类有两个api,一个用于该类的直接用户,另一个用于从该类继承的类。按照惯例,前者使用不带下划线的名称,后者可以访问单下划线名称。但该类仍然有权对这两种类型的用户隐藏它的一些实现细节——这些细节不构成任何一种API的一部分。否则,对类的内部工作进行更改几乎是不可能的,因为您不知道子类如何使用您的成员。你是说你不同意吗?我是说这就是原因。这样子类时就不会出现名称冲突。这很有趣,但您不能在
Parent.\uuu init\uuuuuuuuu
中使用
Parent.help()
,而不定义
\uuuuu help
?是的,您也可以使用
Parent.help(self,“将孩子带到学校”)
。我认为这个答案的重点是证明它实际上允许父类“选择退出”使用在子类中重写的方法(或属性)。