标签归档:naming-conventions

为什么pylint反对单字符变量名?

问题:为什么pylint反对单字符变量名?

我仍然习惯于使用python约定并使用pylint使我的代码更具pythonic风格,但是我对pylint不喜欢单字符变量名感到困惑。我有几个这样的循环:

for x in x_values:
   my_list.append(x)

当我运行时pylint,我得到Invalid name "x" for type variable (should match [a-z_][a-z0-9_]{2,30}-这表明一个有效的变量名长度必须在3到31个字符之间,但是我浏览了PEP8命名约定,但没有看到任何有关单个小写字母的明确信息,我确实看到了很多使用它们的示例。

在PEP8中我缺少什么还是这是pylint特有的标准?

I’m still getting used to python conventions and using pylint to make my code more pythonic, but I’m puzzled by the fact that pylint doesn’t like single character variable names. I have a few loops like this:

for x in x_values:
   my_list.append(x)

and when I run pylint, I’m getting Invalid name "x" for type variable (should match [a-z_][a-z0-9_]{2,30} — that suggests that a valid variable name must be between 3 and 31 characters long, but I’ve looked through the PEP8 naming conventions and I don’t see anything explicit regarding single lower case letters, and I do see a lot of examples that use them.

Is there something I’m missing in PEP8 or is this a standard that is unique to pylint?


回答 0

PyLint不仅检查PEP8建议。它也有自己的建议,其中之一就是变量名应具有描述性且不能太短。

您可以使用它来避免这样的短名称:

my_list.extend(x_values)

或调整PyLint的配置,以告诉PyLint什么变量名是好的。

PyLint checks not only PEP8 recommendations. It has also its own recommendations, one of which is that a variable name should be descriptive and not too short.

You can use this to avoid such short names:

my_list.extend(x_values)

Or tweak PyLint’s configuration to tell PyLint what variable name are good.


回答 1

关于格尼alex所指出的内容的更多详细信息:您可以告诉PyLint为变量名(即使您少于三个字符)清楚地将变量名(您发誓发誓)作exceptions。在标题下找到或添加到您的pylintrc文件中[FORMAT]

# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,pk,x,y

这里pk(用于主键),x和y是我添加的变量名。

A little more detail on what gurney alex noted: you can tell PyLint to make exceptions for variable names which (you pinky swear) are perfectly clear even though less than three characters. Find in or add to your pylintrc file, under the [FORMAT] header:

# Good variable names which should always be accepted, separated by a comma
good-names=i,j,k,ex,Run,_,pk,x,y

Here pk (for primary key), x, and y are variable names i’ve added.


回答 2

在强类型语言中,1个字母的名称变量可能没问题,因为通常会在变量的声明中或函数/方法原型中获得名称旁边的类型:

bool check_modality(string a, Mode b, OptionList c) {
    ModalityChecker v = build_checker(a, b);
    return v.check_option(c);
}

在Python中,您不会获得此信息,因此,如果您编写:

def check_modality(a, b, c):
    v = build_checker(a, b)
    return v.check_option(c)

对于该功能可以做什么,如何调用以及返回什么,您绝对不会给维护团队提供任何线索。因此,在Python中,您倾向于使用描述性名称:

def check_modality(name, mode, option_list):
    checker = build_checker(name, mode)
    return checker.check_option(option_list)

您甚至可以添加一个文档字符串来说明这些东西的作用以及期望的类型。

In strongly typed languages, 1 letter name variables can be ok-ish, because you generally get the type next to the name in the declaration of the variable or in the function / method prototype:

bool check_modality(string a, Mode b, OptionList c) {
    ModalityChecker v = build_checker(a, b);
    return v.check_option(c);
}

In Python, you don’t get this information, so if you write:

def check_modality(a, b, c):
    v = build_checker(a, b)
    return v.check_option(c)

you’re leaving absolutely no clue for the maintenance team as to what the function could be doing, and how it is called, and what it returns. So in Python, you tend to use descriptive names:

def check_modality(name, mode, option_list):
    checker = build_checker(name, mode)
    return checker.check_option(option_list)

and you even add a docstring explaining what the stuff does and what types are expected.


回答 3

如今,还有一个选项可以覆盖正则表达式。即,如果您想允许单个字符作为变量:

pylint --variable-rgx="[a-z0-9_]{1,30}$" <filename>

因此,pylint将与PEP8相匹配,并且不会带来其他违规行为。您也可以将其添加到中.pylintrc

Nowadays there is also a option to override regexp. I.e. if you want to allow single characters as variables:

pylint --variable-rgx="[a-z0-9_]{1,30}$" <filename>

So, pylint will match PEP8 and will not bring additional violations on top. Also you can add it to .pylintrc.


回答 4

更深层次的原因是,你可能还记得你的原意abcxy,和z是指当你写你的代码,但是当别人读它,甚至当你回到你的代码,代码变得更加可读当你给它是一个语义名称。我们不会在黑板上写东西然后再擦除它。我们正在编写的代码可能会存在十年或更长时间,并且会被阅读很多次。

使用语义名称。我使用语义的名称一直喜欢ratiodenominatorobj_generatorpath,等这可能需要额外的两秒钟他们打出来,但是你节省试图找出你所写的,甚至一半,然后一小时的时间是值得的。

The deeper reason is that you may remember what you intended a, b, c, x, y, and z to mean when you wrote your code, but when others read it, or even when you come back to your code, the code becomes much more readable when you give it a semantic name. We’re not writing stuff once on a chalkboard and then erasing it. We’re writing code that might stick around for a decade or more, and be read many, many times.

Use semantic names. Semantic names I’ve used have been like ratio, denominator, obj_generator, path, etc. It may take an extra second or two to type them out, but the time you save trying to figure out what you wrote even half an hour from then is well worth it.


Python名称修饰

问题:Python名称修饰

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

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

如果约定只使用一个下划线,我也想知道其基本原理。

这是我对JBernardo的回答所留下的评论。它解释了为什么我问这个问题,以及为什么我想知道为什么Python与其他语言不同的原因:

我来自可以训练您的语言,使您认为一切都应该仅在需要时公开,而不能再公开了。原因是这将减少依赖关系并使代码更安全地更改。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.

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.

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:

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.


回答 0

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

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人士都鄙视了此默认设置-但这仍然是默认设置,因此即使您感到不舒服,我也建议您遵循它。

如果您确实要发送消息“无法触摸此!” 对于您的用户,通常的方法是在变量前加一个下划线。这只是一个约定,但是人们理解它并且在处理这些东西时要格外小心:

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)

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

 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

那双下划线呢?好吧,双下划线魔术主要用于避免方法的意外重载和名称与超类的属性的冲突。。如果您编写一个预期会扩展很多次的类,这将非常有用。

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

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

Python具有属性

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

但是,它并不是那么简单。例如,Java类确实有很多的属性 getter方法,只是得到的值刚刚制定者设定的值。让我们说,您需要七行代码来声明一个属性-Python程序员会说这不必要地复杂。另外,实际上,您只需编写全部代码即可获得一个公共字段,因为您可以使用getter和setter更改其值。

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

person.age = age;

在您的代码中,让我们说,

person.setAge(age);

setAge() 存在:

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

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

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

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

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

 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?

(此外,请参阅Python并非Java本文将介绍使用getter和setter的危害。)

一切都是可见的-试图隐藏只会使您的工作复杂化

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

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

无法看到问题-这是必需的看到

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

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

圭多这样说

好吧,这没有争议:实际上他是这么说的。(寻找“开放和服”。)

这是文化

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

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

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)

write this by default:

class Stack(object):

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

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

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.

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.

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.

Python has properties

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.

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.

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() being:

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

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.

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

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

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

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

Everything is visible anyway – and trying to hide just complicates your work

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.

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

The problem is not being possible to see – it is being required to see

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).

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.

Guido said so

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

This is culture

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.

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 :)


回答 1

首先-什么是名称修改?

当您在类定义中并使用__any_name或时__any_name_(即两个(或多个)前导下划线和最多一个尾随下划线),将调用名称修饰。

class Demo:
    __any_name = "__any_name"
    __any_other_name_ = "__any_other_name_"

现在:

>>> [n for n in dir(Demo) if 'any' in n]
['_Demo__any_name', '_Demo__any_other_name_']
>>> Demo._Demo__any_name
'__any_name'
>>> Demo._Demo__any_other_name_
'__any_other_name_'

如有疑问,该怎么办?

表面上的用途是防止子类使用类使用的属性。

一个潜在的价值是避免与想要重写行为的子类产生名称冲突,以使父类功能保持按预期运行。但是,Python文档中的示例不能替代Liskov,并且在我发现此有用的地方都没有想到的示例。

缺点是它增加了阅读和理解代码库的认知负担,尤其是在调试时,您在源中看到双下划线名称,而在调试器中看到错误的名称。

我个人的方法是有意避免它。我在非常大的代码库上工作。它的罕见用法像拇指酸痛一样伸出来,似乎没有道理。

您确实需要意识到它,以便在看到它时就知道它。

PEP 8

PEP 8(Python标准库样式指南)目前说(删节):

关于使用的方法存在一些争议 __names

如果您的类打算被子类化,并且您具有不希望使用子类的属性,请考虑使用双引号和下划线来命名它们。

  1. 请注意,整齐的名称中仅使用了简单的类名,因此,如果子类同时选择了相同的类名和属性名,则仍然会发生名称冲突。

  2. 名称修饰可以使某些用途(如调试和__getattr__())变得不太方便。但是,名称修饰算法已被详细记录,并且易于手动执行。

  3. 并非每个人都喜欢名字修饰。尝试在避免意外名称冲突与高级调用方法潜在使用之间进行权衡。

它是如何工作的?

如果在类定义中添加两个下划线(不带双下划线),则该名称将被修饰,并且该对象后将带有下划线和类名:

>>> class Foo(object):
...     __foobar = None
...     _foobaz = None
...     __fooquux__ = None
... 
>>> [name for name in dir(Foo) if 'foo' in name]
['_Foo__foobar', '__fooquux__', '_foobaz']

请注意,只有在解析类定义时,名称才会被篡改:

>>> Foo.__test = None
>>> Foo.__test
>>> Foo._Foo__test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '_Foo__test'

另外,Python的新手有时在无法手动访问在类定义中看到的名称时,难以理解发生了什么。这不是反对它的有力理由,但是如果您有一个学习的听众,这是要考虑的事情。

一个下划线?

如果约定只使用一个下划线,我也想知道其基本原理。

当我打算让用户不要使用某个属性时,我倾向于只使用一个下划线,但这是因为在我的思维模型中,子类可以访问该名称(他们一直拥有该名称,因为他们可以轻松地找到该名称)。无论如何,名称都乱码)。

如果我正在审查使用该__前缀的代码,我会问为什么他们要进行名称修饰,并且如果使用单个下划线不能做到那么好,请记住,如果子类为该类选择相同的名称,并且尽管如此,class属性还是会发生名称冲突。

First – What is name mangling?

Name mangling is invoked when you are in a class definition and use __any_name or __any_name_, that is, two (or more) leading underscores and at most one trailing underscore.

class Demo:
    __any_name = "__any_name"
    __any_other_name_ = "__any_other_name_"

And now:

>>> [n for n in dir(Demo) if 'any' in n]
['_Demo__any_name', '_Demo__any_other_name_']
>>> Demo._Demo__any_name
'__any_name'
>>> Demo._Demo__any_other_name_
'__any_other_name_'

When in doubt, do what?

The ostensible use is to prevent subclassers from using an attribute that the class uses.

A potential value is in avoiding name collisions with subclassers who want to override behavior, so that the parent class functionality keeps working as expected. However, the example in the Python documentation is not Liskov substitutable, and no examples come to mind where I have found this useful.

The downsides are that it increases cognitive load for reading and understanding a code base, and especially so when debugging where you see the double underscore name in the source and a mangled name in the debugger.

My personal approach is to intentionally avoid it. I work on a very large code base. The rare uses of it stick out like a sore thumb and do not seem justified.

You do need to be aware of it so you know it when you see it.

PEP 8

PEP 8, the Python standard library style guide, currently says (abridged):

There is some controversy about the use of __names.

If your class is intended to be subclassed, and you have attributes that you do not want subclasses to use, consider naming them with double leading underscores and no trailing underscores.

  1. Note that only the simple class name is used in the mangled name, so if a subclass chooses both the same class name and attribute name, you can still get name collisions.

  2. Name mangling can make certain uses, such as debugging and __getattr__() , less convenient. However the name mangling algorithm is well documented and easy to perform manually.

  3. Not everyone likes name mangling. Try to balance the need to avoid accidental name clashes with potential use by advanced callers.

How does it work?

If you prepend two underscores (without ending double-underscores) in a class definition, the name will be mangled, and an underscore followed by the class name will be prepended on the object:

>>> class Foo(object):
...     __foobar = None
...     _foobaz = None
...     __fooquux__ = None
... 
>>> [name for name in dir(Foo) if 'foo' in name]
['_Foo__foobar', '__fooquux__', '_foobaz']

Note that names will only get mangled when the class definition is parsed:

>>> Foo.__test = None
>>> Foo.__test
>>> Foo._Foo__test
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'Foo' has no attribute '_Foo__test'

Also, those new to Python sometimes have trouble understanding what’s going on when they can’t manually access a name they see defined in a class definition. This is not a strong reason against it, but it’s something to consider if you have a learning audience.

One Underscore?

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

When my intention is for users to keep their hands off an attribute, I tend to only use the one underscore, but that’s because in my mental model, subclassers would have access to the name (which they always have, as they can easily spot the mangled name anyways).

If I were reviewing code that uses the __ prefix, I would ask why they’re invoking name mangling, and if they couldn’t do just as well with a single underscore, keeping in mind that if subclassers choose the same names for the class and class attribute there will be a name collision in spite of this.


回答 2

我不会说实践会产生更好的代码。可见性修改器只会分散您的注意力,而副作用是会强制您按预期使用界面。一般来说,增强可见性可以防止程序员在没有正确阅读文档的情况下搞乱事情。

一个更好的解决方案是Python鼓励的方法:应该很好地记录您的类和变量,并明确其行为。源应该可用。这是编写代码的更可扩展和可靠的方式。

我在Python中的策略是:

  1. 只需写下该死的东西,就无需假设如何保护您的数据。假定您编写用于创建问题的理想接口。
  2. 使用前导下划线表示可能不会在外部使用且不属于常规“客户端代码”界面的。
  3. 仅在课堂上纯粹方便的事情上使用双下划线,否则,如果不慎将其暴露在外会造成相当大的损害。

最重要的是,应该清楚一切都在做什么。如果其他人会使用它,请记录下来。如果希望一年之内有用,请记录下来。

附带说明,您实际上应该使用其他语言的保护:您永远都不知道您的类以后可能会继承以及它的用途。最好只保护您确定不能或不应被外来代码使用的那些变量。

I wouldn’t say that practice produces better code. Visibility modifiers only distract you from the task at hand, and as a side effect force your interface to be used as you intended. Generally speaking, enforcing visibility prevents programmers from messing things up if they haven’t read the documentation properly.

A far better solution is the route that Python encourages: Your classes and variables should be well documented, and their behaviour clear. The source should be available. This is far more extensible and reliable way to write code.

My strategy in Python is this:

  1. Just write the damn thing, make no assumptions about how your data should be protected. This assumes that you write to create the ideal interfaces for your problems.
  2. Use a leading underscore for stuff that probably won’t be used externally, and isn’t part of the normal “client code” interface.
  3. Use double underscore only for things that are purely convenience inside the class, or will cause considerable damage if accidentally exposed.

Above all, it should be clear what everything does. Document it if someone else will be using it. Document it if you want it to be useful in a year’s time.

As a side note, you should actually be going with protected in those other languages: You never know your class might be inherited later and for what it might be used. Best to only protect those variables that you are certain cannot or should not be used by foreign code.


回答 3

您不应该从私有数据开始,而是在必要时将其公开。相反,您应该首先确定对象的接口。即,您应该首先弄清楚世界所看到的(公共事物),然后弄清楚要实现这一目标需要哪些私人事物。

其他语言很难使曾经公开的语言私有化。也就是说,如果我将变量设为私有或受保护,则会破坏很多代码。但是对于python中的属性,情况并非如此。相反,即使重新排列内部数据,我也可以保持相同的接口。

_和__之间的区别是python实际上试图强制后者。当然,它并不会很努力,但确实会增加难度。拥有_只是告诉其他程序员意图是什么,他们可以无视自己的危险。但是忽略该规则有时会有所帮助。例子包括调试,临时黑客攻击以及使用非您打算使用的第三方代码的方式。

You shouldn’t start with private data and make it public as necessary. Rather, you should start by figuring out the interface of your object. I.e. you should start by figuring out what the world sees (the public stuff) and then figure out what private stuff is necessary for that to happen.

Other language make difficult to make private that which once was public. I.e. I’ll break lots of code if I make my variable private or protected. But with properties in python this isn’t the case. Rather, I can maintain the same interface even with rearranging the internal data.

The difference between _ and __ is that python actually makes an attempt to enforce the latter. Of course, it doesn’t try really hard but it does make it difficult. Having _ merely tells other programmers what the intention is, they are free to ignore at their peril. But ignoring that rule is sometimes helpful. Examples include debugging, temporary hacks, and working with third party code that wasn’t intended to be used the way you use it.


回答 4

对此已经有很多好的答案,但是我将提供另一个答案。这也是对一直说双下划线不是私密的(实际上是私密的)人们的回应。

如果您查看Java / C#,则它们都具有private / protected / public。所有这些都是编译时构造。它们仅在编译时强制执行。如果要在Java / C#中使用反射,则可以轻松访问私有方法。

现在,每次您在Python中调用函数时,本质上都是在使用反射。这些代码在Python中是相同的。

lst = []
lst.append(1)
getattr(lst, 'append')(1)

对于后面的代码,“点”语法只是语法糖。主要是因为仅使用一个函数调用就已经很难使用getattr。从那里变得更糟。

所以就没有了会有Java / C#版本的private,因为Python不会编译代码。Java和C#无法在运行时检查函数是私有的还是公共的,因为该信息已消失(并且不知道从何处调用该函数)。

现在,有了这些信息,双重下划线的名称修饰对于实现“私密性”最有意义。现在,当从“ self”实例调用函数时,它注意到它以“ __”开头,它只是在此处执行名称修改。它只是语法上的糖。该语法糖允许仅使用反射进行数据成员访问的语言中的“私有”等价物。

免责声明:我从没听过Python开发人员说过这样的话。缺乏“私有”的真正原因是文化上的,但是您还将注意到大多数脚本/解释语言没有私有。除了编译时,严格执行的私有方法在任何情况下都不可行。

There are already a lot of good answers to this, but I’m going to offer another one. This is also partially a response to people who keep saying that double underscore isn’t private (it really is).

If you look at Java/C#, both of them have private/protected/public. All of these are compile-time constructs. They are only enforced at the time of compilation. If you were to use reflection in Java/C#, you could easily access private method.

Now every time you call a function in Python, you are inherently using reflection. These pieces of code are the same in Python.

lst = []
lst.append(1)
getattr(lst, 'append')(1)

The “dot” syntax is only syntactic sugar for the latter piece of code. Mostly because using getattr is already ugly with only one function call. It just gets worse from there.

So with that, there can’t be a Java/C# version of private, as Python doesn’t compile the code. Java and C# can’t check if a function is private or public at runtime, as that information is gone (and it has no knowledge of where the function is being called from).

Now with that information, the name mangling of the double underscore makes the most sense for achieving “private-ness”. Now when a function is called from the ‘self’ instance and it notices that it starts with ‘__’, it just performs the name mangling right there. It’s just more syntactic sugar. That syntactic sugar allows the equivalent of ‘private’ in a language that only uses reflection for data member access.

Disclaimer: I have never heard anybody from the Python development say anything like this. The real reason for the lack of “private” is cultural, but you’ll also notice that most scripting/interpreted languages have no private. A strictly enforceable private is not practical at anything except for compile time.


回答 5

第一:为什么要隐藏数据?为什么这么重要?

大多数时候,您并不是真的想这样做,但是您这样做是因为其他人正在这样做。

如果您确实真的不希望别人使用某些东西,请添加一个在其前面下划线。就是这样… Pythonistas知道带有下划线的内容并不能保证每次都能正常工作,并且可能在您不知情的情况下发生变化。

那就是我们的生活方式,我们对此表示满意。

使用两个下划线会使您的类难以继承,甚至您也不想那样工作。

First: Why do you want to hide your data? Why is that so important?

Most of the time you don’t really want to do it but you do because others are doing.

If you really really really don’t want people using something, add one underscore in front of it. That’s it… Pythonistas know that things with one underscore is not guaranteed to work every time and may change without you knowing.

That’s the way we live and we’re okay with that.

Using two underscores will make your class so bad to subclass that even you will not want to work that way.


回答 6

选择的答案很好地解释了属性如何消除对私有属性的需求,但是我还要补充一点,模块级的函数消除了对私有方法的需求

如果在模块级别将方法转换为函数,则将消除子类覆盖它的机会。将某些功能移至模块级别比使用隐藏名称修饰的方法更具Python风格。

The chosen answer does a good job of explaining how properties remove the need for private attributes, but I would also add that functions at the module level remove the need for private methods.

If you turn a method into a function at the module level, you remove the opportunity for subclasses to override it. Moving some functionality to the module level is more Pythonic than trying to hide methods with name mangling.


回答 7

以下代码段将解释所有不同的情况:

  • 两个下划线(__a)
  • 单个前划线(_a)
  • 没有下划线(a)

    class Test:
    
    def __init__(self):
        self.__a = 'test1'
        self._a = 'test2'
        self.a = 'test3'
    
    def change_value(self,value):
        self.__a = value
        return self.__a

打印测试对象的所有有效属性

testObj1 = Test()
valid_attributes = dir(testObj1)
print valid_attributes

['_Test__a', '__doc__', '__init__', '__module__', '_a', 'a', 
'change_value']

在这里,您可以看到__a的名称已更改为_Test__a,以防止任何子类都覆盖此变量。这个概念在python中被称为“名称修改”。您可以这样访问:

testObj2 = Test()
print testObj2._Test__a

test1

同样,在_a情况下,该变量只是通知开发人员应将其用作该类的内部变量,即使您访问python解释器也不会执行任何操作,但这不是一个好习惯。

testObj3 = Test()
print testObj3._a

test2

变量可以像公共类变量一样从任何地方进行访问。

testObj4 = Test()
print testObj4.a

test3

希望答案对您有所帮助:)

Following code snippet will explain all different cases :

  • two leading underscores (__a)
  • single leading underscore (_a)
  • no underscore (a)

    class Test:
    
    def __init__(self):
        self.__a = 'test1'
        self._a = 'test2'
        self.a = 'test3'
    
    def change_value(self,value):
        self.__a = value
        return self.__a
    

printing all valid attributes of Test Object

testObj1 = Test()
valid_attributes = dir(testObj1)
print valid_attributes

['_Test__a', '__doc__', '__init__', '__module__', '_a', 'a', 
'change_value']

Here, you can see that name of __a has been changed to _Test__a to prevent this variable to be overridden by any of the subclass. This concept is known as “Name Mangling” in python. You can access this like this :

testObj2 = Test()
print testObj2._Test__a

test1

Similarly, in case of _a, the variable is just to notify the developer that it should be used as internal variable of that class, the python interpreter won’t do anything even if you access it, but it is not a good practise.

testObj3 = Test()
print testObj3._a

test2

a variable can be accesses from anywhere it’s like a public class variable.

testObj4 = Test()
print testObj4.a

test3

Hope the answer helped you :)


回答 8

乍一看,它应该与其他语言相同(在“其他”下,我指的是Java或C ++),但事实并非如此。

在Java中,您将所有不应在外部访问的变量设为私有。在Python中,由于没有“私密性”,因此您无法实现这一目标(正如Python原则之一所说的:“我们都是成年人”)。因此,双下划线仅表示“伙计,请勿直接使用此字段”。相同的含义是下划线,当您必须从所考虑的类继承时,这不会引起任何头痛(这只是双下划线可能引起的问题的一个示例)。

因此,我建议您默认对“私有”成员使用单个下划线。

At first glance it should be the same as for other languages (under “other” I mean Java or C++), but it isn’t.

In Java you made private all variables that shouldn’t be accessible outside. In the same time in Python you can’t achieve this since there is no “privateness” (as one of Python principles says – “We’re all adults”). So double underscore means only “Guys, do not use this field directly”. The same meaning has singe underscore, which in the same time doesn’t cause any headache when you have to inherit from considered class (just an example of possible problem caused by double underscore).

So, I’d recommend you to use single underscore by default for “private” members.


回答 9

“如果不确定变量是私有变量还是受保护变量,最好选择私有变量。” -是的,在Python中也是如此。

这里有一些关于“约定”的答案,但没有提供这些约定的链接。PEP 8是Python的权威指南,明确指出:

如有疑问,请选择非公开;稍后将其公开比将公共属性设为不公开要容易。

其他答案也考虑了公共和私有之间的区别以及Python中的名称修饰。从同一个链接,

我们在这里不使用术语“私有”,因为在Python中没有任何属性是真正私有的(通常没有不必要的工作量)。

“If in doubt about whether a variable should be private or protected, it’s better to go with private.” – yes, same holds in Python.

Some answers here say about ‘conventions’, but don’t give the links to those conventions. The authoritative guide for Python, PEP 8 states explicitly:

If in doubt, choose non-public; it’s easier to make it public later than to make a public attribute non-public.

The distinction between public and private, and name mangling in Python have been considered in other answers. From the same link,

We don’t use the term “private” here, since no attribute is really private in Python (without a generally unnecessary amount of work).


模块的Python命名约定

问题:模块的Python命名约定

我有一个模块,其目的是定义一个称为“ nib”的类。(以及一些相关的类。)我应该如何调用模块本身?“笔尖”?“ nibmodule”?还要别的吗?

I have a module whose purpose is to define a class called “nib”. (and a few related classes too.) How should I call the module itself? “nib”? “nibmodule”? Anything else?


回答 0

只是笔尖。将类Nib命名为大写N。有关命名约定和其他样式建议的更多信息,请参见Python样式指南PEP 8

Just nib. Name the class Nib, with a capital N. For more on naming conventions and other style advice, see PEP 8, the Python style guide.


回答 1

我称它为nib.py。我也将其命名为Nib类。

在我正在处理的一个较大的python项目中,我们有许多模块定义了一个重要的类。类以大写字母开头。模块的名称类似于小写的类。这导致如下所示的导入:

from nib import Nib
from foo import Foo
from spam.eggs import Eggs, FriedEggs

有点像模拟Java方式。每个文件一个类。但是,通过增加的灵活性,您可以在合理的情况下始终将另一个类添加到单个文件中。

I would call it nib.py. And I would also name the class Nib.

In a larger python project I’m working on, we have lots of modules defining basically one important class. Classes are named beginning with a capital letter. The modules are named like the class in lowercase. This leads to imports like the following:

from nib import Nib
from foo import Foo
from spam.eggs import Eggs, FriedEggs

It’s a bit like emulating the Java way. One class per file. But with the added flexibility, that you can allways add another class to a single file if it makes sense.


回答 2

我知道我的解决方案从pythonic的角度来看不是很流行,但是我更喜欢使用Java的方法,即一个模块->一个类,并将模块命名为该类。我确实了解python样式背后的原因,但是我不太喜欢包含很多类的非常大的文件。尽管折叠,但我发现很难浏览。

另一个原因是版本控制:拥有大文件意味着您的提交倾向于集中在该文件上。这有可能导致解决大量冲突。您还将丢失提交修改特定文件(因此涉及特定类)的其他日志信息。取而代之的是,您看到了对模块文件的修改,仅带有提交注释以了解已进行了哪些修改。

总结一下,如果您喜欢python原理,请参考其他文章的建议。如果您更喜欢类似Java的哲学,请创建一个包含Nib类的Nib.py。

I know my solution is not very popular from the pythonic point of view, but I prefer to use the Java approach of one module->one class, with the module named as the class. I do understand the reason behind the python style, but I am not too fond of having a very large file containing a lot of classes. I find it difficult to browse, despite folding.

Another reason is version control: having a large file means that your commits tend to concentrate on that file. This can potentially lead to a higher quantity of conflicts to be resolved. You also loose the additional log information that your commit modifies specific files (therefore involving specific classes). Instead you see a modification to the module file, with only the commit comment to understand what modification has been done.

Summing up, if you prefer the python philosophy, go for the suggestions of the other posts. If you instead prefer the java-like philosophy, create a Nib.py containing class Nib.


回答 3

笔尖很好。如有疑问,请参阅Python样式指南。

PEP 8

程序包和模块名称模块应使用简短的全小写名称。如果模块名称可以提高可读性,则可以在模块名称中使用下划线。尽管不鼓励使用下划线,但Python软件包也应使用短小写全名。

由于模块名称已映射到文件名,并且某些文件系统不区分大小写,并且截断了长名称,因此,将模块名称选择为相当短是很重要的-在Unix上这不是问题,但可能是代码传输到较旧的Mac或Windows版本或DOS时出现问题。

当用C或C ++编写的扩展模块具有随附的Python模块提供更高级别(例如,面向对象)的接口时,C / C ++模块具有下划线(例如_socket)。

nib is fine. If in doubt, refer to the Python style guide.

From PEP 8:

Package and Module Names Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability. Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

Since module names are mapped to file names, and some file systems are case insensitive and truncate long names, it is important that module names be chosen to be fairly short — this won’t be a problem on Unix, but it may be a problem when the code is transported to older Mac or Windows versions, or DOS.

When an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object oriented) interface, the C/C++ module has a leading underscore (e.g. _socket).


回答 4

PEP-8:程序包和模块名称

模块应使用简短的全小写名称。如果模块名称可以提高可读性,则可以在模块名称中使用下划线。

尽管不鼓励使用下划线,但Python软件包也应使用短小写全名。

当用C或C ++编写的扩展模块具有随附的Python模块提供更高级别(例如,面向对象)的接口时,C / C ++模块具有下划线(例如_socket)。

From PEP-8: Package and Module Names:

Modules should have short, all-lowercase names. Underscores can be used in the module name if it improves readability.

Python packages should also have short, all-lowercase names, although the use of underscores is discouraged.

When an extension module written in C or C++ has an accompanying Python module that provides a higher level (e.g. more object oriented) interface, the C/C++ module has a leading underscore (e.g. _socket).


回答 5

python中的foo模块等效于Java中的Foo类文件

要么

python中的foob​​ar模块等同于Java中的FooBar类文件

foo module in python would be the equivalent to a Foo class file in Java

or

foobar module in python would be the equivalent to a FooBar class file in Java


Python中单个下划线“ _”变量的用途是什么?

问题:Python中单个下划线“ _”变量的用途是什么?

此代码中的_after 是什么意思for

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1

What is the meaning of _ after for in this code?

if tbh.bag:
   n = 0
   for _ in tbh.bag.atom_set():
      n += 1

回答 0

_ 在Python中有4种主要的常规用法:

  1. 在交互式解释器会话中保存上次执行的表达式的结果。此先例是由标准CPython解释器设置的,其他解释器也纷纷效仿
  2. 有关在i18n中进行翻译查找的信息,请参见 gettext 例如,文档),如代码所示: raise forms.ValidationError(_("Please enter a correct username"))
  3. 作为通用“一次性”的变量名指示函数结果的一部分被故意忽略(在概念上,它被丢弃。),如类似的代码: label, has_label, _ = text.partition(':')
  4. 作为函数定义的一部分(使用deflambda),其中的签名是固定的(例如,通过回调或父类API),但是此特定函数实现不需要所有参数,如代码所示:callback = lambda _: True

(很长一段时间以来,这个答案只列出了前三个用例,但是第四个用例经常出现,如前所述 这里,将值得明确列出)

后者的“抛弃型变量或参数名称”用例可能与翻译查找用例冲突,因此有必要避免_在也将其用于i18n转换的任何代码块中将其用作抛弃型变量(许多人更喜欢双下划线,__正是由于这个原因而将其作为一次性变量)。

_ has 4 main conventional uses in Python:

  1. To hold the result of the last executed expression(/statement) in an interactive interpreter session. This precedent was set by the standard CPython interpreter, and other interpreters have followed suit
  2. For translation lookup in i18n (see the gettext documentation for example), as in code like: raise forms.ValidationError(_("Please enter a correct username"))
  3. As a general purpose “throwaway” variable name to indicate that part of a function result is being deliberately ignored (Conceptually, it is being discarded.), as in code like: label, has_label, _ = text.partition(':').
  4. As part of a function definition (using either def or lambda), where the signature is fixed (e.g. by a callback or parent class API), but this particular function implementation doesn’t need all of the parameters, as in code like: callback = lambda _: True

(For a long time this answer only listed the first three use cases, but the fourth case came up often enough, as noted here, to be worth listing explicitly)

The latter “throwaway variable or parameter name” uses cases can conflict with the translation lookup use case, so it is necessary to avoid using _ as a throwaway variable in any code block that also uses it for i18n translation (many folks prefer a double-underscore, __, as their throwaway variable for exactly this reason).


回答 1

它只是一个变量名,在python中通常_用于丢弃变量。它仅表示循环变量未实际使用。

It’s just a variable name, and it’s conventional in python to use _ for throwaway variables. It just indicates that the loop variable isn’t actually used.


回答 2

下划线在Python中_被视为“ 我不在乎 ”或“ 抛出 ”变量

  • python解释器将最后一个表达式值存储到名为的特殊变量中_

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
  • 下划线_也用于忽略特定值。如果不需要特定值或不使用这些值,只需将这些值分配给下划线即可。

    开箱时忽略值

    x, _, y = (1, 2, 3)
    
    >>> x
    1
    
    >>> y 
    3

    忽略索引

    for _ in range(10):     
        do_something()

Underscore _ is considered as “I don’t Care” or “Throwaway” variable in Python

  • The python interpreter stores the last expression value to the special variable called _.

    >>> 10 
    10
    
    >>> _ 
    10
    
    >>> _ * 3 
    30
    
  • The underscore _ is also used for ignoring the specific values. If you don’t need the specific values or the values are not used, just assign the values to underscore.

    Ignore a value when unpacking

    x, _, y = (1, 2, 3)
    
    >>> x
    1
    
    >>> y 
    3
    

    Ignore the index

    for _ in range(10):     
        do_something()
    

回答 3

在Python中使用下划线有5种情况。

  1. 用于将最后一个表达式的值存储在解释器中。

  2. 用于忽略特定值。(所谓的“我不在乎”)

  3. 给变量或函数的名称赋予特殊的含义和功能。

  4. 用作“国际化(i18n)”或“本地化(l10n)”功能。

  5. 分隔数字文字值的数字。

是一篇不错的文章,上面有mingrammer的示例。

There are 5 cases for using the underscore in Python.

  1. For storing the value of last expression in interpreter.

  2. For ignoring the specific values. (so-called “I don’t care”)

  3. To give special meanings and functions to name of vartiables or functions.

  4. To use as ‘Internationalization(i18n)’ or ‘Localization(l10n)’ functions.

  5. To separate the digits of number literal value.

Here is a nice article with examples by mingrammer.


回答 4

就Python语言而言,_没有特殊含义。与或一样,它是有效的标识符_foofoo__f_o_o_

的任何特殊含义_纯属约定。常见几种情况:

  • 如果不打算使用变量,但是语法/语义需要一个虚拟名称。

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
  • 许多REPL / shell将最后一个顶级表达式的结果存储到builtins._

    特殊的标识符_在交互式解释器中用于存储上一次评估的结果。它存储在builtins模块中。如果不在交互模式下,_则没有特殊含义并且未定义。[ 来源 ]

    由于查找名称的方式,除非由全局或局部_定义遮盖,否则裸_指的是builtins._

    >>> 42
    42
    >>> f'the last answer is {_}'
    'the last answer is 42'
    >>> _
    'the last answer is 42'
    >>> _ = 4  # shadow ``builtins._`` with global ``_``
    >>> 23
    23
    >>> _
    4

    注意:某些外壳程序(例如)ipython不分配给builtins._而是特例_

  • 在上下文中,国际化和本地化_用作主要翻译功能的别名。

    gettext.gettext(消息)

    根据当前的全局域,语言和语言环境目录,返回消息的本地化翻译。在本地命名空间中,此函数通常别名为_()(请参见下面的示例)。

As far as the Python languages is concerned, _ has no special meaning. It is a valid identifier just like _foo, foo_ or _f_o_o_.

Any special meaning of _ is purely by convention. Several cases are common:

  • A dummy name when a variable is not intended to be used, but a name is required by syntax/semantics.

    # iteration disregarding content
    sum(1 for _ in some_iterable)
    # unpacking disregarding specific elements
    head, *_ = values
    # function disregarding its argument
    def callback(_): return True
    
  • Many REPLs/shells store the result of the last top-level expression to builtins._.

    The special identifier _ is used in the interactive interpreter to store the result of the last evaluation; it is stored in the builtins module. When not in interactive mode, _ has no special meaning and is not defined. [source]

    Due to the way names are looked up, unless shadowed by a global or local _ definition the bare _ refers to builtins._ .

    >>> 42
    42
    >>> f'the last answer is {_}'
    'the last answer is 42'
    >>> _
    'the last answer is 42'
    >>> _ = 4  # shadow ``builtins._`` with global ``_``
    >>> 23
    23
    >>> _
    4
    

    Note: Some shells such as ipython do not assign to builtins._ but special-case _.

  • In the context internationalization and localization, _ is used as an alias for the primary translation function.

    gettext.gettext(message)

    Return the localized translation of message, based on the current global domain, language, and locale directory. This function is usually aliased as _() in the local namespace (see examples below).


Python中变量和函数名称的命名约定是什么?

问题:Python中变量和函数名称的命名约定是什么?

来自C#背景的变量和方法名称的命名约定通常为camelCase或PascalCase:

// C# example
string thisIsMyVariable = "a"
public void ThisIsMyMethod()

在Python中,我已经看到了上述内容,但也看到了使用下划线的情况:

# python example
this_is_my_variable = 'a'
def this_is_my_function():

有没有更优选的,确定的Python编码风格?

Coming from a C# background the naming convention for variables and method names are usually either camelCase or PascalCase:

// C# example
string thisIsMyVariable = "a"
public void ThisIsMyMethod()

In Python, I have seen the above but I have also seen underscores being used:

# python example
this_is_my_variable = 'a'
def this_is_my_function():

Is there a more preferable, definitive coding style for Python?


回答 0

请参阅Python PEP 8:函数和变量名称

函数名称应小写,必要时用下划线分隔单词,以提高可读性。

变量名遵循与函数名相同的约定。

仅在已经是主流样式(例如threading.py)的上下文中才允许使用blendCase,以保持向后兼容性。

See Python PEP 8: Function and Variable Names:

Function names should be lowercase, with words separated by underscores as necessary to improve readability.

Variable names follow the same convention as function names.

mixedCase is allowed only in contexts where that’s already the prevailing style (e.g. threading.py), to retain backwards compatibility.


回答 1

Google Python样式指南》具有以下约定:

module_namepackage_nameClassNamemethod_nameExceptionNamefunction_nameGLOBAL_CONSTANT_NAMEglobal_var_nameinstance_var_namefunction_parameter_namelocal_var_name

类似的命名方案应适用于 CLASS_CONSTANT_NAME

The Google Python Style Guide has the following convention:

module_name, package_name, ClassName, method_name, ExceptionName, function_name, GLOBAL_CONSTANT_NAME, global_var_name, instance_var_name, function_parameter_name, local_var_name.

A similar naming scheme should be applied to a CLASS_CONSTANT_NAME


回答 2

大卫·Goodger(在“代码就像Pythonista” 在这里)描述了PEP 8项建议如下:

  • joined_lower 用于函数,方法,属性,变量

  • joined_lowerALL_CAPS常量

  • StudlyCaps 上课

  • camelCase 仅符合先前的约定

David Goodger (in “Code Like a Pythonista” here) describes the PEP 8 recommendations as follows:

  • joined_lower for functions, methods, attributes, variables

  • joined_lower or ALL_CAPS for constants

  • StudlyCaps for classes

  • camelCase only to conform to pre-existing conventions


回答 3

正如Python代码样式指南所承认的那样,

Python库的命名约定有些混乱,因此我们永远都无法做到这一点

请注意,这仅指Python的标准库。如果他们不能得到那个一致,那么就几乎是具有很大的希望通常附着到约定所有的 Python代码,不是吗?

因此,在这里的讨论中,我可以推断出,如果在过渡到Python时继续使用变量或函数的Java或C#命名惯例(例如清晰明确的命名规则),这并不是一个可怕的罪过。当然,请记住,最好遵守代码库/项目/团队的流行风格。正如《 Python风格指南》指出的那样,内部一致性最重要。

随意将我视为异端。:-)像OP一样,我也不是“ Pythonista”,无论如何也没有。

As the Style Guide for Python Code admits,

The naming conventions of Python’s library are a bit of a mess, so we’ll never get this completely consistent

Note that this refers just to Python’s standard library. If they can’t get that consistent, then there hardly is much hope of having a generally-adhered-to convention for all Python code, is there?

From that, and the discussion here, I would deduce that it’s not a horrible sin if one keeps using e.g. Java’s or C#’s (clear and well-established) naming conventions for variables and functions when crossing over to Python. Keeping in mind, of course, that it is best to abide with whatever the prevailing style for a codebase / project / team happens to be. As the Python Style Guide points out, internal consistency matters most.

Feel free to dismiss me as a heretic. :-) Like the OP, I’m not a “Pythonista”, not yet anyway.


回答 4

如其他答案所示,有PEP 8,但是PEP 8只是标准库的样式指南,在其中仅作为福音。PEP 8对于其他代码段最常见的偏差之一是变量命名,尤其是方法。尽管考虑到使用mixedCase的代码量很大,但没有单一的主导风格,如果要进行严格的普查,则可能最终会得到带有mixedCase的PEP 8版本。与PEP 8几乎没有其他偏差是很常见的。

There is PEP 8, as other answers show, but PEP 8 is only the styleguide for the standard library, and it’s only taken as gospel therein. One of the most frequent deviations of PEP 8 for other pieces of code is the variable naming, specifically for methods. There is no single predominate style, although considering the volume of code that uses mixedCase, if one were to make a strict census one would probably end up with a version of PEP 8 with mixedCase. There is little other deviation from PEP 8 that is quite as common.


回答 5

如前所述,PEP 8表示可lower_case_with_underscores用于变量,方法和函数。

我更喜欢使用lower_case_with_underscores变量以及mixedCase方法和函数使代码更明确和可读。因此,遵循Python Zen的 “显式优于隐式”和“可读性”

As mentioned, PEP 8 says to use lower_case_with_underscores for variables, methods and functions.

I prefer using lower_case_with_underscores for variables and mixedCase for methods and functions makes the code more explicit and readable. Thus following the Zen of Python’s “explicit is better than implicit” and “Readability counts”


回答 6

@JohnTESlade回答的内容更进一步。Google的python样式指南提供了一些非常简洁的建议,

避免使用的名称

  • 单个字符名称(计数器或迭代器除外)
  • 任何程序包/模块名称中的破折号(-)
  • \__double_leading_and_trailing_underscore__ names (由Python保留)

命名约定

  • “内部”是指模块内部或类中受保护或私有的内部。
  • 在单个下划线(_)前面有一些支持来保护模块变量和函数(import * from中不包括)。在实例变量或方法前加双下划线(__)可以有效地使变量或方法对其类具有私有性(使用名称修饰)。
  • 将相关的类和顶级功能放到一个模块中。与Java不同,不需要将自己限制为每个模块一个类。
  • 使用CapWords类的名字,但lower_with_under.py对模块名称。尽管有许多命名的现有模块CapWords.py,但现在不建议这样做,因为当碰巧以一个类命名该模块时会造成混淆。(“等待-我写import StringIO还是写from StringIO import StringIO?”)

源自Guido建议的指南

further to what @JohnTESlade has answered. Google’s python style guide has some pretty neat recommendations,

Names to Avoid

  • single character names except for counters or iterators
  • dashes (-) in any package/module name
  • \__double_leading_and_trailing_underscore__ names (reserved by Python)

Naming Convention

  • “Internal” means internal to a module or protected or private within a class.
  • Prepending a single underscore (_) has some support for protecting module variables and functions (not included with import * from). Prepending a double underscore (__) to an instance variable or method effectively serves to make the variable or method private to its class (using name mangling).
  • Place related classes and top-level functions together in a module. Unlike Java, there is no need to limit yourself to one class per module.
  • Use CapWords for class names, but lower_with_under.py for module names. Although there are many existing modules named CapWords.py, this is now discouraged because it’s confusing when the module happens to be named after a class. (“wait — did I write import StringIO or from StringIO import StringIO?”)

Guidelines derived from Guido’s Recommendations


回答 7

大多数python的人都喜欢使用下划线,但是自从5年前以来,即使我使用python,我仍然不喜欢它们。它们对我来说看起来很难看,但也许这就是我脑海中的所有Java。

我只是喜欢驼峰更好,因为它适合与类的命名方式更好,感觉更符合逻辑具有SomeClass.doSomething()SomeClass.do_something()。如果您在python中查看全局模块索引,则会发现这两者,这是因为它是随着时间的推移而增长的各种来源的库的集合,而不是由像Sun这样的公司开发的具有严格编码规则的库。我要说的底线是:使用任何您喜欢的更好的东西,这只是个人品味的问题。

Most python people prefer underscores, but even I am using python since more than 5 years right now, I still do not like them. They just look ugly to me, but maybe that’s all the Java in my head.

I simply like CamelCase better since it fits better with the way classes are named, It feels more logical to have SomeClass.doSomething() than SomeClass.do_something(). If you look around in the global module index in python, you will find both, which is due to the fact that it’s a collection of libraries from various sources that grew overtime and not something that was developed by one company like Sun with strict coding rules. I would say the bottom line is: Use whatever you like better, it’s just a question of personal taste.


回答 8

我个人尝试将CamelCase用于类,mixedCase方法和函数。变量通常用下划线分隔(当我记得时)。这样一来,我就可以一目了然地告诉我我到底在叫什么,而不是所有看起来都一样的东西。

Personally I try to use CamelCase for classes, mixedCase methods and functions. Variables are usually underscore separated (when I can remember). This way I can tell at a glance what exactly I’m calling, rather than everything looking the same.


回答 9

有一篇关于此的论文:http : //www.cs.kent.edu/~jmaletic/papers/ICPC2010-CamelCaseUnderScoreClouds.pdf

TL; DR它说snake_case比camelCase更具可读性。这就是为什么现代语言在任何可能的地方使用(或应该使用)蛇的原因。

There is a paper about this: http://www.cs.kent.edu/~jmaletic/papers/ICPC2010-CamelCaseUnderScoreClouds.pdf

TL;DR It says that snake_case is more readable than camelCase. That’s why modern languages use (or should use) snake wherever they can.


回答 10

编码风格通常是组织内部政策/惯例标准的一部分,但我认为一般来说,all_lower_case_underscore_separator风格(也称为snake_case)在python中最为常见。

The coding style is usually part of an organization’s internal policy/convention standards, but I think in general, the all_lower_case_underscore_separator style (also called snake_case) is most common in python.


回答 11

在以其他编程语言进行开发时,我个人使用Java的命名约定,因为它一致且易于遵循。这样,我就不会一直在努力使用哪些约定不应该成为我项目中最难的部分!

I personally use Java’s naming conventions when developing in other programming languages as it is consistent and easy to follow. That way I am not continuously struggling over what conventions to use which shouldn’t be the hardest part of my project!


回答 12

通常,遵循语言标准库中使用的约定。

Typically, one follow the conventions used in the language’s standard library.


对象名称前的单下划线和双下划线是什么意思?

问题:对象名称前的单下划线和双下划线是什么意思?

有人可以解释一下在Python中对象名称前加下划线的确切含义,以及两者之间的区别吗?

此外,无论所讨论的对象是变量,函数,方法等,该含义是否都保持不变?

Can someone please explain the exact meaning of having leading underscores before an object’s name in Python, and the difference between both?

Also, does that meaning stay the same whether the object in question is a variable, a function, a method, etc.?


回答 0

单下划线

类中带有下划线的名称仅是为了向其他程序员表明该属性或方法旨在私有。但是,名称本身并没有做任何特别的事情。

引用PEP-8

_single_leading_underscore:“内部使用”指标较弱。例如from M import *,不导入名称以下划线开头的对象。

双下划线(名称改写)

Python文档

形式上的任何标识符__spam(至少两个前导下划线,至多一个尾随下划线)在文本上均替换为_classname__spam,其中classname是当前类名,其中已删除前导下划线。进行这种修饰时无需考虑标识符的语法位置,因此可用于定义类私有实例和类变量,方法,全局变量中存储的变量,甚至实例中存储的变量。在其他类的实例上对此类私有。

和来自同一页面的警告:

名称修饰旨在为类提供一种轻松的方法来定义“私有”实例变量和方法,而不必担心派生类定义的实例变量或类外部代码对实例变量的处理。请注意,修改规则主要是为了避免发生意外。坚定的灵魂仍然有可能访问或修改被视为私有的变量。

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

Single Underscore

Names, in a class, with a leading underscore are simply to indicate to other programmers that the attribute or method is intended to be private. However, nothing special is done with the name itself.

To quote PEP-8:

_single_leading_underscore: weak “internal use” indicator. E.g. from M import * does not import objects whose name starts with an underscore.

Double Underscore (Name Mangling)

From the Python docs:

Any identifier of the form __spam (at least two leading underscores, at most one trailing underscore) is textually replaced with _classname__spam, where classname is the current class name with leading underscore(s) stripped. This mangling is done without regard to the syntactic position of the identifier, so it can be used to define class-private instance and class variables, methods, variables stored in globals, and even variables stored in instances. private to this class on instances of other classes.

And a warning from the same page:

Name mangling is intended to give classes an easy way to define “private” instance variables and methods, without having to worry about instance variables defined by derived classes, or mucking with instance variables by code outside the class. Note that the mangling rules are designed mostly to avoid accidents; it still is possible for a determined soul to access or modify a variable that is considered private.

Example

>>> class MyClass():
...     def __init__(self):
...             self.__superprivate = "Hello"
...             self._semiprivate = ", world!"
...
>>> mc = MyClass()
>>> print mc.__superprivate
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: myClass instance has no attribute '__superprivate'
>>> print mc._semiprivate
, world!
>>> print mc.__dict__
{'_MyClass__superprivate': 'Hello', '_semiprivate': ', world!'}

回答 1

到目前为止,很好的答案,但缺少一些花絮。单个前导下划线并不仅仅是一个约定:如果使用from foobar import *,并且模块foobar未定义__all__列表,则从模块导入的名称将包括带有下划线的名称。可以说这主要是一个约定,因为这种情况是一个相当模糊的角落;-)。

领先的下划线惯例被广泛用于不只是私人的名字,而且对什么C ++称之为保护的-例如,都完全的方法名称由子类(甚至是那些覆盖被否决,因为在它们的基类raise NotImplementedError!-)通常是单引号下划线名称,用于指示使用该类(或子类)的实例进行编码时,这些方法并不旨在被直接调用。

例如,要创建一个与FIFO不同的排队规则的线程安全队列,可以导入Queue,将Queue.Queue子类化,并覆盖诸如_get_put;之类的方法。“客户端代码”从不调用那些(“挂钩”)方法,而是调用(和“组织”)公共方法,例如putget(称为模板方法设计模式),例如,有关基于视频的有趣演示,请参见此处。我关于这个话题的演讲,以及抄本的提要)。

编辑:演讲说明中的视频链接现在已断开。您可以在此处此处找到前两个视频。

Excellent answers so far but some tidbits are missing. A single leading underscore isn’t exactly just a convention: if you use from foobar import *, and module foobar does not define an __all__ list, the names imported from the module do not include those with a leading underscore. Let’s say it’s mostly a convention, since this case is a pretty obscure corner;-).

The leading-underscore convention is widely used not just for private names, but also for what C++ would call protected ones — for example, names of methods that are fully intended to be overridden by subclasses (even ones that have to be overridden since in the base class they raise NotImplementedError!-) are often single-leading-underscore names to indicate to code using instances of that class (or subclasses) that said methods are not meant to be called directly.

For example, to make a thread-safe queue with a different queueing discipline than FIFO, one imports Queue, subclasses Queue.Queue, and overrides such methods as _get and _put; “client code” never calls those (“hook”) methods, but rather the (“organizing”) public methods such as put and get (this is known as the Template Method design pattern — see e.g. here for an interesting presentation based on a video of a talk of mine on the subject, with the addition of synopses of the transcript).

Edit: The video links in the description of the talks are now broken. You can find the first two videos here and here.


回答 2

__foo__:这只是一个约定,这是Python系统使用不会与用户名冲突的名称的一种方式。

_foo:这只是一个约定,是程序员用来表明变量是私有的(无论在Python中是什么意思)的一种方式。

__foo:这具有实际含义:解释器将其替换为,_classname__foo以确保该名称不会与另一个类中的相似名称重叠。

在Python世界中,没有其他形式的下划线具有意义。

在这些约定中,类,变量,全局等之间没有区别。

__foo__: this is just a convention, a way for the Python system to use names that won’t conflict with user names.

_foo: this is just a convention, a way for the programmer to indicate that the variable is private (whatever that means in Python).

__foo: this has real meaning: the interpreter replaces this name with _classname__foo as a way to ensure that the name will not overlap with a similar name in another class.

No other form of underscores have meaning in the Python world.

There’s no difference between class, variable, global, etc in these conventions.


回答 3

._variable 是半私有的,仅用于约定

.__variable通常被错误地认为是超私有的,而其实际含义只是为了防止意外访问而使用 namemangle [1]

.__variable__ 通常为内置方法或变量保留

您仍然可以.__mangled根据需要访问变量。双下划线只是将变量命名或重命名为类似instance._className__mangled

例:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b是可访问的,因为它仅被约定隐藏

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

找不到t .__ a,因为由于名称修改而不再存在

>>> t._Test__a
'a'

通过访问instance._className__variable而不只是双下划线名称,您可以访问隐藏值

._variable is semiprivate and meant just for convention

.__variable is often incorrectly considered superprivate, while it’s actual meaning is just to namemangle to prevent accidental access[1]

.__variable__ is typically reserved for builtin methods or variables

You can still access .__mangled variables if you desperately want to. The double underscores just namemangles, or renames, the variable to something like instance._className__mangled

Example:

class Test(object):
    def __init__(self):
        self.__a = 'a'
        self._b = 'b'

>>> t = Test()
>>> t._b
'b'

t._b is accessible because it is only hidden by convention

>>> t.__a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Test' object has no attribute '__a'

t.__a isn’t found because it no longer exists due to namemangling

>>> t._Test__a
'a'

By accessing instance._className__variable instead of just the double underscore name, you can access the hidden value


回答 4

开头下划线:

Python没有真正的私有方法。相反,在方法或属性名称的开头加下划线表示您不应访问此方法,因为它不是API的一部分。

class BaseForm(StrAndUnicode):

    def _get_errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors

    errors = property(_get_errors)

(此代码段摘自django源代码:django / forms / forms.py)。在这段代码中,它errors是一个公共属性,但是此属性调用的方法_get_errors是“私有”的,因此您不应访问它。

一开始有两个下划线:

这引起很多混乱。不应将其用于创建私有方法。应该使用它来避免您的方法被子类覆盖或意外访问。让我们来看一个例子:

class A(object):
    def __test(self):
        print "I'm a test method in class A"

    def test(self):
        self.__test()

a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!

输出:

$ python test.py
I'm test method in class A
I'm test method in class A

现在创建一个子类B并为__test方法进行自定义

class B(A):
    def __test(self):
        print "I'm test method in class B"

b = B()
b.test()

输出将是…。

$ python test.py
I'm test method in class A

如我们所见,A.test()没有像我们期望的那样调用B .__ test()方法。但实际上,这是__的正确行为。这两个称为__test()的方法会自动重命名(混合)为_A__test()和_B__test(),因此不会意外覆盖它们。当您创建以__开头的方法时,这意味着您不希望任何人都可以覆盖它,而只打算从其自己的类内部访问它。

开头和结尾有两个下划线:

当我们看到类似的方法时__this__,请勿调用它。这是python而不是您要调用的方法。让我们来看看:

>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11

>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60

总是有一个调用这些魔术方法的运算符或本机函数。有时,在特定情况下,这只是python的一个钩子调用。例如__init__()在创建对象之后创建对象时__new__()调用,以构建实例…

让我们举个例子…

class FalseCalculator(object):

    def __init__(self, number):
        self.number = number

    def __add__(self, number):
        return self.number - number

    def __sub__(self, number):
        return self.number + number

number = FalseCalculator(20)
print number + 10      # 10
print number - 20      # 40

有关更多详细信息,请参阅PEP-8指南。有关更多魔术方法,请参见此PDF

Single underscore at the beginning:

Python doesn’t have real private methods. Instead, one underscore at the start of a method or attribute name means you shouldn’t access this method, because it’s not part of the API.

class BaseForm(StrAndUnicode):

    def _get_errors(self):
        "Returns an ErrorDict for the data provided for the form"
        if self._errors is None:
            self.full_clean()
        return self._errors

    errors = property(_get_errors)

(This code snippet was taken from django source code: django/forms/forms.py). In this code, errors is a public property, but the method this property calls, _get_errors, is “private”, so you shouldn’t access it.

Two underscores at the beginning:

This causes a lot of confusion. It should not be used to create a private method. It should be used to avoid your method being overridden by a subclass or accessed accidentally. Let’s see an example:

class A(object):
    def __test(self):
        print "I'm a test method in class A"

    def test(self):
        self.__test()

a = A()
a.test()
# a.__test() # This fails with an AttributeError
a._A__test() # Works! We can access the mangled name directly!

Output:

$ python test.py
I'm test method in class A
I'm test method in class A

Now create a subclass B and do customization for __test method

class B(A):
    def __test(self):
        print "I'm test method in class B"

b = B()
b.test()

Output will be….

$ python test.py
I'm test method in class A

As we have seen, A.test() didn’t call B.__test() methods, as we might expect. But in fact, this is the correct behavior for __. The two methods called __test() are automatically renamed (mangled) to _A__test() and _B__test(), so they do not accidentally override. When you create a method starting with __ it means that you don’t want to anyone to be able to override it, and you only intend to access it from inside its own class.

Two underscores at the beginning and at the end:

When we see a method like __this__, don’t call it. This is a method which python is meant to call, not you. Let’s take a look:

>>> name = "test string"
>>> name.__len__()
11
>>> len(name)
11

>>> number = 10
>>> number.__add__(40)
50
>>> number + 50
60

There is always an operator or native function which calls these magic methods. Sometimes it’s just a hook python calls in specific situations. For example __init__() is called when the object is created after __new__() is called to build the instance…

Let’s take an example…

class FalseCalculator(object):

    def __init__(self, number):
        self.number = number

    def __add__(self, number):
        return self.number - number

    def __sub__(self, number):
        return self.number + number

number = FalseCalculator(20)
print number + 10      # 10
print number - 20      # 40

For more details, see the PEP-8 guide. For more magic methods, see this PDF.


回答 5

有时您看起来像是一个带下划线的元组,如下所示

def foo(bar):
    return _('my_' + bar)

在这种情况下,正在发生的情况是_()是本地化功能的别名,该功能基于文本在文本上进行操作以将其放入适当的语言等。例如,Sphinx执行此操作,您将在导入文件中找到

from sphinx.locale import l_, _

在sphinx.locale中,_()被分配为某些本地化功能的别名。

Sometimes you have what appears to be a tuple with a leading underscore as in

def foo(bar):
    return _('my_' + bar)

In this case, what’s going on is that _() is an alias for a localization function that operates on text to put it into the proper language, etc. based on the locale. For example, Sphinx does this, and you’ll find among the imports

from sphinx.locale import l_, _

and in sphinx.locale, _() is assigned as an alias of some localization function.


回答 6

既然有这么多人在谈论雷蒙德的演讲,我将写下他的话简化一下:

双下划线的目的不是关于隐私。目的是像这样完全使用它

class Circle(object):

    def __init__(self, radius):
        self.radius = radius

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

实际上,这是隐私的对立面,它与自由有关。它使您的子类可以随意覆盖任何一种方法而不会破坏其他方法

假设您没有保留perimeterin 的本地引用Circle。现在,派生类将Tire覆盖实现perimeter,而无需触摸areaTire(5).area()从理论上讲,当您调用时,它仍Circle.perimeter应用于计算,但实际上,它正在使用Tire.perimeter,这不是预期的行为。这就是为什么我们在Circle中需要本地引用。

但是为什么要__perimeter代替_perimeter呢?因为_perimeter仍然给派生类重写的机会:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

双下划线具有名称修饰,因此父类中的本地引用在派生类中被覆盖的可能性很小。因此“ 使子类可以自由地覆盖任何一种方法而不会破坏其他方法 ”。

如果您的类不会被继承,或者方法重写不会破坏任何内容,那么您根本不需要__double_leading_underscore

Since so many people are referring to Raymond’s talk, I’ll just make it a little easier by writing down what he said:

The intention of the double underscores was not about privacy. The intention was to use it exactly like this

class Circle(object):

    def __init__(self, radius):
        self.radius = radius

    def area(self):
        p = self.__perimeter()
        r = p / math.pi / 2.0
        return math.pi * r ** 2.0

    def perimeter(self):
        return 2.0 * math.pi * self.radius

    __perimeter = perimeter  # local reference


class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

It’s actually the opposite of privacy, it’s all about freedom. It makes your subclasses free to override any one method without breaking the others.

Say you don’t keep a local reference of perimeter in Circle. Now, a derived class Tire overrides the implementation of perimeter, without touching area. When you call Tire(5).area(), in theory it should still be using Circle.perimeter for computation, but in reality it’s using Tire.perimeter, which is not the intended behavior. That’s why we need a local reference in Circle.

But why __perimeter instead of _perimeter? Because _perimeter still gives derived class the chance to override:

class Tire(Circle):

    def perimeter(self):
        return Circle.perimeter(self) * 1.25

    _perimeter = perimeter

Double underscores has name mangling, so there’s a very little chance that the local reference in parent class get override in derived class. thus “makes your subclasses free to override any one method without breaking the others“.

If your class won’t be inherited, or method overriding does not break anything, then you simply don’t need __double_leading_underscore.


回答 7

如果您真的想将变量设为只读,恕我直言,最好的方法是使用仅传递有getter的property()。使用property(),我们可以完全控制数据。

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

我知道OP提出了一个稍有不同的问题,但是由于我发现了另一个问题,询问“如何设置私有变量”与此标记为重复,因此我想在此处添加此附加信息。

If one really wants to make a variable read-only, IMHO the best way would be to use property() with only getter passed to it. With property() we can have complete control over the data.

class PrivateVarC(object):

    def get_x(self):
        pass

    def set_x(self, val):
        pass

    rwvar = property(get_p, set_p)  

    ronly = property(get_p) 

I understand that OP asked a little different question but since I found another question asking for ‘how to set private variables’ marked duplicate with this one, I thought of adding this additional info here.


回答 8

进入https://dbader.org/blog/含义-underscores-in-python

  • 单个前导下划线(_var):表示名称的命名约定仅供内部使用。通常不由Python解释器强制执行(通配符导入除外),并且仅作为对程序员的提示。
  • 单个尾随下划线(var_):按惯例用于避免与Python关键字命名冲突。
  • 双引号下划线(__var):在类上下文中使用时触发名称修饰。由Python解释器实施。
  • 前后双下划线(__var__):表示Python语言定义的特殊方法。避免为您自己的属性使用此命名方案。
  • 单个下划线(_):有时用作临时或无关紧要的变量的名称(“无关紧要”)。另外:Python REPL中最后一个表达式的结果。

Accroding to https://dbader.org/blog/meaning-of-underscores-in-python

  • Single Leading Underscore(_var): Naming convention indicating a name is meant for internal use. Generally not enforced by the Python interpreter (except in wildcard imports) and meant as a hint to the programmer only.
  • Single Trailing Underscore(var_): Used by convention to avoid naming conflicts with Python keywords.
  • Double Leading Underscore(__var): Triggers name mangling when used in a class context. Enforced by the Python interpreter.
  • Double Leading and Trailing Underscore(__var__): Indicates special methods defined by the Python language. Avoid this naming scheme for your own attributes.
  • Single Underscore(_): Sometimes used as a name for temporary or insignificant variables (“don’t care”). Also: The result of the last expression in a Python REPL.

回答 9

单个下划线是惯例。名称是否以单个下划线开头,与解释器的观点没有区别。

双开头和结尾的下划线用于内置的方法,如__init____bool__

双下划线开头W / O尾随同行是惯例也是如此,但是,该类方法将被错位的解释。对于变量或基本函数名称,没有区别。

Single leading underscores is a convention. there is no difference from the interpreter’s point of view if whether names starts with a single underscore or not.

Double leading and trailing underscores are used for built-in methods, such as __init__, __bool__, etc.

Double leading underscores w/o trailing counterparts are a convention too, however, the class methods will be mangled by the interpreter. For variables or basic function names no difference exists.


回答 10

好的答案都正确。我提供了简单的示例以及简单的定义/含义。

含义:

some_variable–►任何人都可以看到这是公开的。

_some_variable–►任何人都可以看到这是公开的,但这是表示私有的惯例… 警告 Python不会执行任何强制执行。

__some_varaible–►Python将变量名替换为_classname__some_varaible(又名名称改写),它降低/隐藏了它的可见性,更像是私有变量。

坦白地说,根据Python文档

“只能从对象内部访问的“私有”实例变量在Python中不存在”

这个例子:

class A():
    here="abc"
    _here="_abc"
    __here="__abc"


aObject=A()
print(aObject.here) 
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable 
#print(aObject.__here)

Great answers and all are correct.I have provided simple example along with simple definition/meaning.

Meaning:

some_variable –► it’s public anyone can see this.

_some_variable –► it’s public anyone can see this but it’s a convention to indicate private…warning no enforcement is done by Python.

__some_varaible –► Python replaces the variable name with _classname__some_varaible (AKA name mangling) and it reduces/hides it’s visibility and be more like private variable.

Just to be honest here According to Python documentation

““Private” instance variables that cannot be accessed except from inside an object don’t exist in Python”

The example:

class A():
    here="abc"
    _here="_abc"
    __here="__abc"


aObject=A()
print(aObject.here) 
print(aObject._here)
# now if we try to print __here then it will fail because it's not public variable 
#print(aObject.__here)

回答 11

您的问题很好,不仅是方法。模块中的函数和对象通常也以一个下划线为前缀,并且可以以两个为前缀。

但是,例如,__double_underscore名称在模块中没有名称混杂。发生的情况是,如果您从模块(从module import *)全部导入,则不会导入以一个(或多个)下划线开头的名称,也不会在help(module)中显示名称。

Your question is good, it is not only about methods. Functions and objects in modules are commonly prefixed with one underscore as well, and can be prefixed by two.

But __double_underscore names are not name-mangled in modules, for example. What happens is that names beginning with one (or more) underscores are not imported if you import all from a module (from module import *), nor are the names shown in help(module).


回答 12

这是一个关于双下划线属性如何影响继承的类的简单说明性示例。因此,使用以下设置:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

如果您随后在python REPL中创建一个子实例,则会看到以下内容

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

这对于某些人可能是显而易见的,但是在更复杂的环境中使我措手不及

Here is a simple illustrative example on how double underscore properties can affect an inherited class. So with the following setup:

class parent(object):
    __default = "parent"
    def __init__(self, name=None):
        self.default = name or self.__default

    @property
    def default(self):
        return self.__default

    @default.setter
    def default(self, value):
        self.__default = value


class child(parent):
    __default = "child"

if you then create a child instance in the python REPL, you will see the below

child_a = child()
child_a.default            # 'parent'
child_a._child__default    # 'child'
child_a._parent__default   # 'parent'

child_b = child("orphan")
## this will show 
child_b.default            # 'orphan'
child_a._child__default    # 'child'
child_a._parent__default   # 'orphan'

This may be obvious to some, but it caught me off guard in a much more complex environment


回答 13

Python中不存在只能从对象内部访问的“私有”实例变量。但是,大多数Python代码遵循一个约定:以下划线开头的名称(例如_spam)应被视为API的非公开部分(无论是函数,方法还是数据成员) 。它应被视为实现细节,如有更改,恕不另行通知。

参考 https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references

“Private” instance variables that cannot be accessed except from inside an object don’t exist in Python. However, there is a convention that is followed by most Python code: a name prefixed with an underscore (e.g. _spam) should be treated as a non-public part of the API (whether it is a function, a method or a data member). It should be considered an implementation detail and subject to change without notice.

reference https://docs.python.org/2/tutorial/classes.html#private-variables-and-class-local-references


回答 14

得到_和__的事实非常容易。其他答案很好地表达了他们。使用情况很难确定。

这是我的看法:

_

应该用于表示某个功能不公开使用,例如API。这和导入限制使它的行为很像internal在c#中。

__

应该用来避免继承层次结构中的名称冲突以及避免后期绑定。就像C#中的private。

==>

如果您想指出某事不是公共用途,而是应该像protecteduse 一样_。如果您想指出某事不是公共用途,而是应该像privateuse 一样__

这也是我非常喜欢的报价:

问题在于,类的作者可能会合理地认为“此属性/方法名称应为私有的,只能从该类定义中访问”,并使用__private约定。但是稍后,该类的用户可能会创建合法需要访问该名称的子类。因此,要么必须修改超类(可能很难或不可能),要么子类代码必须使用手动修改的名称(充其量是丑陋和脆弱的)。

但是我的问题是,如果没有IDE在您重写方法时警告您,如果您意外地从基类中重写了一个方法,则发现错误可能会花费您一段时间。

Getting the facts of _ and __ is pretty easy; the other answers express them pretty well. The usage is much harder to determine.

This is how I see it:

_

Should be used to indicate that a function is not for public use as for example an API. This and the import restriction make it behave much like internal in c#.

__

Should be used to avoid name collision in the inheritace hirarchy and to avoid latebinding. Much like private in c#.

==>

If you want to indicate that something is not for public use, but it should act like protected use _. If you want to indicate that something is not for public use, but it should act like private use __.

This is also a quote that I like very much:

The problem is that the author of a class may legitimately think “this attribute/method name should be private, only accessible from within this class definition” and use the __private convention. But later on, a user of that class may make a subclass that legitimately needs access to that name. So either the superclass has to be modified (which may be difficult or impossible), or the subclass code has to use manually mangled names (which is ugly and fragile at best).

But the problem with that is in my opinion that if there’s no IDE that warns you when you override methods, finding the error might take you a while if you have accidentially overriden a method from a base-class.