Python名称修饰 [英] Python name mangling

查看:70
本文介绍了Python名称修饰的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在其他语言中,有助于产生更好代码的通用准则总是使所有内容都尽可能隐藏.如果不确定变量是私有变量还是受保护变量,最好使用私有变量.

In other languages, a general guideline that helps produce better code is always make everything as hidden as possible. If in doubt about whether a variable should be private or protected, it's better to go with private.

同样适用于Python吗?首先,我应该在所有内容上使用两个前导下划线,而仅在需要时才使它们隐藏度降低(仅一个下划线)吗?

Does the same hold true for Python? Should I use two leading underscores on everything at first, and only make them less hidden (only one underscore) as I need them?

如果约定仅使用一个下划线,我也想知道其原理.

If the convention is to use only one underscore, I'd also like to know the rationale.

这是我在 JBernardo的回答.它解释了为什么我问这个问题,以及为什么我想知道为什么Python与其他语言不同的原因:

Here's a comment I left on JBernardo's answer. It explains why I asked this question and also why I'd like to know why Python is different from the other languages:

我来自可以训练您的语言,使您认为一切都应该仅在需要时公开,而不再需要.原因是这将减少依赖关系并使代码更安全地更改.用Python反向做事的方式-从公开开始到隐藏-对我来说很奇怪.

I come from languages that train you to think everything should be only as public as needed and no more. The reasoning is that this will reduce dependencies and make the code safer to alter. The Python way of doing things in reverse -- starting from public and going towards hidden -- is odd to me.

推荐答案

如有疑问,请将其保留为公开"-我的意思是,请勿添加任何内容以掩盖您的属性名称.如果您的类具有一些内部值,请不要理会.而不是写:

When in doubt, leave it "public" - I mean, do not add anything to obscure the name of your attribute. If you have a class with some internal value, do not bother about it. Instead of writing:

class Stack(object):

    def __init__(self):
        self.__storage = [] # Too uptight

    def push(self, value):
        self.__storage.append(value)

默认情况下写成这样:

class Stack(object):

    def __init__(self):
        self.storage = [] # No mangling

    def push(self, value):
        self.storage.append(value)

这肯定是一种有争议的做事方式. Python的新手只是讨厌它,甚至一些老的Python人士都鄙视了此默认设置-但这仍然是默认设置,因此即使您感到不舒服,我也建议您遵循它.

This is for sure a controversial way of doing things. Python newbies just hate it and even some old Python guys despise this default - but it is the default anyway, so I really recommend you to follow it, even if you feel uncomfortable.

如果您真的要发送消息无法触摸!"对于您的用户,通常的方法是在变量前加上 one 下划线.这只是一个约定,但人们理解它并在处理此类内容时要格外小心:

If you really want to send the message "Can't touch this!" to your users, the usual way is to precede the variable with one underscore. This is just a convention, but people understand it and take double care when dealing with such stuff:

class Stack(object):

    def __init__(self):
        self._storage = [] # This is ok but pythonistas use it to be relaxed about it

    def push(self, value):
        self._storage.append(value)

这对于避免属性名称和属性名称之间的冲突也很有用:

This can be useful, too, for avoiding conflict between property names and attribute names:

 class Person(object):
     def __init__(self, name, age):
         self.name = name
         self._age = age if age >= 0 else 0

     @property
     def age(self):
         return self._age

     @age.setter
     def age(self, age):
         if age >= 0:
             self._age = age
         else:
             self._age  = 0

双下划线怎么办?好吧,双下划线魔术主要用于以避免意外方法的重载和名称与超类的属性发生冲突.如果您编写一个预期会扩展很多次的类,则该功能非常有用.

What about the double underscore? Well, the double underscore magic is used mainly to avoid accidental overloading of methods and name conflicts with superclasses' attributes. It can be quite useful if you write a class that is expected to be extended many times.

如果您想将其用于其他目的,可以,但是既不推荐也不推荐.

If you want to use it for other purposes, you can, but it is neither usual nor recommended.

编辑:为什么会这样?好吧,通常的Python风格并不强调将事情变成私有的-相反!造成这种情况的原因很多-其中大多数是有争议的...让我们看看其中的一些.

EDIT: Why is this so? Well, the usual Python style does not emphasize making things private - on the contrary! There are a lot of reasons for that - most of them controversial... Let us see some of them.

当今大多数OO语言使用相反的方法:不应该使用的内容应该不可见,因此属性应该是私有的.从理论上讲,这将产生更易于管理,耦合更少的类,因为没有人会不顾一切地更改对象内部的值.

Most OO languages today use the opposite approach: what should not be used should not be visible, so attributes should be private. Theoretically, this would yield more manageable, less coupled classes, because no one would change values inside the objects recklessly.

但是,这并不是那么简单.例如,Java类确实有很多属性 getter,它们只是获取值,而 setter只是 set 价值.让我们说,您需要七行代码来声明一个属性-Python程序员会说这不必要地复杂.另外,实际上,您只需编写大量代码即可获得一个公共字段,因为您可以使用getter和setter更改其值.

However, it is not so simple. For example, Java classes do have a lot attributes and getters that just get the values and setters that just set the values. You need, let us say, seven lines of code to declare a single attribute - which a Python programmer would say is needlessly complex. Also, in practice, you just write this whole lot of code to get one public field, since you can change its value using the getters and setters.

那么,为什么要遵循此默认的私有策略?默认情况下只需公开您的属性即可.当然,这在Java中是有问题的,因为如果您决定对属性添加一些验证,则将要求您全部更改

So why to follow this private-by-default policy? Just make your attributes public by default. Of course, this is problematic in Java, because if you decide to add some validation to your attribute, it would require you to change all

person.age = age;

在您的代码中,让我们说

in your code to, let us say,

person.setAge(age);

setAge()是:

public void setAge(int age) {
    if (age >= 0) {
        this.age = age;
    } else {
        this.age = 0;
    }
}

因此,在Java(和其他语言)中,默认设置是无论如何都使用getter和setter,因为它们可能很烦人,但是如果您遇到我所描述的情况,可以节省很多时间.

So in Java (and other languages), the default is to use getters and setters anyway, because they can be annoying to write but can spare you a lot of time if you find yourself in the situation I've described.

但是,由于Python具有属性,因此您不需要在Python中执行此操作.如果您有此类:

However, you do not need to do it in Python, since Python has properties. If you have this class:

 class Person(object):
     def __init__(self, name, age):
         self.name = name
         self.age = age

,然后您决定验证年龄,无需更改代码的person.age = age部分.只需添加一个属性(如下所示)

and then you decide to validate ages, you do not need to change the person.age = age pieces of your code. Just add a property (as shown below)

 class Person(object):
     def __init__(self, name, age):
         self.name = name
         self._age = age if age >= 0 else 0

     @property
     def age(self):
         return self._age

     @age.setter
     def age(self, age):
         if age >= 0:
             self._age = age
         else:
             self._age  = 0

如果您仍然可以使用person.age = age仍然可以使用它,为什么还要添加私有字段以及getter和setter呢?

If you can do it and still use person.age = age, why would you add private fields and getters and setters?

(另外,请参见 Python不是Java 有关使用getter和setter的危害的文章.).

(Also, see Python is not Java and this article about the harms of using getters and setters.).

即使在具有私有属性的语言中,您也可以通过某种反射/自省库来访问它们.人们在框架和解决紧急需求方面做了大量工作.问题在于,自省库只是完成公共属性所用的一种困难方法.

Even in languages where there are private attributes, you can access them through some kind of reflection/introspection library. And people do it a lot, in frameworks and for solving urgent needs. The problem is that introspection libraries are just a hard way of doing what you could do with public attributes.

由于Python是一种非常动态的语言,因此将这种负担添加到您的类中只会适得其反.

Since Python is a very dynamic language, it is just counterproductive to add this burden to your classes.

对于Pythonista,封装不是无法看到类的内部,而是避免查看它的可能性.我的意思是,封装是组件的属性,它使用户无需担心内部细节就可以使用它.如果您可以使用某个组件而不必担心自己的实现,那么它将被封装(在Python程序员看来).

For a Pythonista, encapsulation is not the inability of seeing the internals of classes, but the possibility of avoiding looking at it. What I mean is, encapsulation is the property of a component which allows it to be used without the user being concerned about the internal details. If you can use a component without bothering yourself about its implementation, then it is encapsulated (in the opinion of a Python programmer).

现在,如果您以这种方式编写类,而无需考虑实现细节,就可以使用它,如果您出于某些原因想要查看,就没有问题了.关键是:您的API应该不错,其余的就是细节.

Now, if you wrote your class in such a way you can use it without having to think about implementation details, there is no problem if you want to look inside the class for some reason. The point is: your API should be good and the rest is details.

嗯,这没有争议:他是这样说的,实际上 . (寻找开放式和服".)

Well, this is not controversial: he said so, actually. (Look for "open kimono.")

是的,有一些原因,但没有关键原因.这主要是Python编程的文化方面.坦白说,也可能是另一种方式,但事实并非如此.同样,您也可以轻松地反过来问:为什么某些语言默认情况下使用私有属性?出于与Python练习相同的主要原因:因为这是这些语言的文化,每种选择都有其优点和缺点.

Yes, there are some reasons, but no critical reason. This is mostly a cultural aspect of programming in Python. Frankly, it could be the other way, too - but it is not. Also, you could just as easily ask the other way around: why do some languages use private attributes by default? For the same main reason as for the Python practice: because it is the culture of these languages, and each choice has advantages and disadvantages.

由于已经存在这种文化,因此建议您遵循它.否则,当您在Stack Overflow中提出问题时,Python程序员会告诉您从代码中删除__,您会感到恼火:

Since there already is this culture, you are well advised to follow it. Otherwise, you will get annoyed by Python programmers telling you to remove the __ from your code when you ask a question in Stack Overflow :)

这篇关于Python名称修饰的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆