Python名称混乱

Python名称混乱,python,naming-conventions,Python,Naming Conventions,在其他语言中,有助于生成更好代码的一般准则始终是尽可能隐藏所有内容。如果对变量应该是私有的还是受保护的有疑问,最好使用私有的 Python也是如此吗?我应该首先在所有东西上使用两个前导下划线,并根据需要减少隐藏(仅一个下划线) 如果约定只使用一个下划线,我还想知道其基本原理 这是我留下的评论。它解释了我为什么问这个问题,以及为什么我想知道为什么Python不同于其他语言: 我来自那些训练你认为一切都应该只在需要的时候公开的语言。理由是,这将减少依赖性,并使代码更安全地修改。Python以相反的方

在其他语言中,有助于生成更好代码的一般准则始终是尽可能隐藏所有内容。如果对变量应该是私有的还是受保护的有疑问,最好使用私有的

Python也是如此吗?我应该首先在所有东西上使用两个前导下划线,并根据需要减少隐藏(仅一个下划线)

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

这是我留下的评论。它解释了我为什么问这个问题,以及为什么我想知道为什么Python不同于其他语言:

我来自那些训练你认为一切都应该只在需要的时候公开的语言。理由是,这将减少依赖性,并使代码更安全地修改。Python以相反的方式做事情——从公开开始,到隐藏——对我来说很奇怪

如果有疑问,请将其保留为“public”——我的意思是,不要添加任何东西来模糊属性的名称。如果您有一个具有某些内部值的类,则不必担心它。而不是写:

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家伙也鄙视这个默认值——但不管怎样,它是默认值,所以我真的建议你遵循它,即使你觉得不舒服

如果您确实想向用户发送消息“Can not touch this!”,通常的方法是在变量前面加一个下划线。这只是一个惯例,但人们理解它,在处理此类事情时要加倍小心:

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,它们只获取值,setter只设置值。比方说,您需要七行代码来声明单个属性——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
代码片段。只需添加一个属性(如下所示)

如果您可以这样做,并且仍然使用
person.age=age
,为什么要添加私有字段、getter和setter

(另请参见和。)

无论如何,一切都是可见的——试图隐藏只会使你的工作复杂化 即使在有私有属性的语言中,您也可以通过某种反射/内省库来访问它们。人们经常这样做,在框架内,为了解决紧急需求。问题在于,内省库只是一种很难实现公共属性的方法

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

问题是看不到-需要看到 对于Pythonista来说,封装不是看不到类的内部,而是避免看它的可能性。我的意思是,封装是组件的属性,它允许用户在不关心内部细节的情况下使用它。如果您可以使用一个组件而不必担心它的实现,那么它将被封装(在Python程序员看来)

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

圭多是这么说的 嗯,这是没有争议的:。(寻找“开放和服”。)

这就是文化 是的,有一些原因,但没有关键原因。这主要是Python编程的文化方面。坦率地说,这也可能是另一种方式——但事实并非如此。另外,你也可以很容易地问另一个问题:为什么有些语言默认使用私有属性?与Python实践的主要原因相同:因为这是这些语言的文化,每种选择都有优点和缺点

既然这种文化已经存在,你最好遵循它。否则,当你问一个问题时,Python程序员会告诉你从代码中删除
\uuu
,这会让你很恼火
 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
lst = []
lst.append(1)
getattr(lst, 'append')(1)
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_'
>>> 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'
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']
testObj2 = Test()
print testObj2._Test__a

test1
testObj3 = Test()
print testObj3._a

test2
testObj4 = Test()
print testObj4.a

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


[n for n in dir(Demo) if 'any' in n]   # GIVES OUTPUT AS ['_Demo__any_name', 
                                       #    '_Demo__any_other_name_']