【问题标题】:member or class variables in pythonpython中的成员或类变量
【发布时间】:2012-04-11 13:02:07
【问题描述】:

我来自 Java,所以我在这里感到困惑。

class Sample(object):
    x = 100                     # class var?
    def __init__(self, value):
        self.y = value          # instance var?
        z = 300                 # private var? how do we access this outside Sample?

这3个变量声明有什么区别?

【问题讨论】:

  • 重复,重复,重复...很多和很多这样的问题,很多和很多完整的文档。
  • @ChrisMorgan:如果你要打电话给重复,至少找到最好的重复答案并在此处发布链接。
  • 举几个例子来说明这个问题的所有要点:class and instance variables, private variables

标签: python variables


【解决方案1】:
class Sample(object):
    x = 100      
    _a = 1
    __b = 11               
    def __init__(self, value):
        self.y = value      
        self._c = 'private'    
        self.__d = 'more private'
        z = 300         

在这个例子中:

  • x 是类变量,
  • _a 是私有类变量(按命名约定),
  • __b 是私有类变量(被解释器破坏),
  • y 是实例变量,
  • _c 是私有实例变量(按命名约定),
  • __d 是私有实例变量(被解释器破坏),
  • z__init__ 方法范围内的局部变量。

如果名称中有单下划线,则严格遵守约定。仍然可以访问这些变量。在双下划线名称的情况下,它们会被破坏。仍然可以绕过它。

【讨论】:

  • dunderscore 在 Python 中很少使用。通常只在前面加上一个下划线来表示该变量是供内部使用的。
  • 我只是说很多现实世界的 Python 代码没有使用这种“强制”,因为它没有真正的优势。是的,无论如何您都可以通过self._Class__variable 轻松访问它。
  • @vartec:enforced 在这里是一个强有力的词。真的只是名字错了。
  • 来自PEP 8 的相关引用:“仅对非公共方法和实例变量使用一个前导下划线。为避免与子类发生名称冲突,请使用两个前导下划线来调用 Python 的名称修饰规则。”它不比单个下划线更 private
  • @John:不,dunderscore 会导致解释器启用名称修改,请参阅链接。但它们的意图相同:将变量标记为内部使用。
【解决方案2】:

@vartec 恰到好处。但是,由于您来自 Java,因此需要澄清一下:

  • Java 有publicprivate 成员。严禁访问private 成员,这是由语言强制执行的。
  • Python 只有公共成员。 没有方法可以强制执行诸如 java 的 private 关键字之类的内容。

    如果你想声明某事只是一个实现细节并且不应该被其他代码依赖,你可以在它前面加上一个下划线——_variable_function()。这是对其他程序员的提示,他们不应该使用那个变量或那个函数,但它没有强制执行。

    看起来 Python 中省略了一个特性,但 Python 的文化是“每个人都是同意的成年人”。如果你告诉其他程序员某些东西是“私有的”,在它前面加上一个下划线,他们通常会接受这个提示。

【讨论】:

  • 好吧,从技术上讲,您可以创建一个真正的私有,您只需通过覆盖 __setattr__() 来破坏您的类,以便在尝试从类外部设置给定值时抛出错误本身。当然,这是非常不符合 Python 的,但如果你想 Java 化 Python(我有一个经理强迫我们在以前的工作中这样做),你可以实现它。
  • @sr2222:我们说话的时候,我在角落里前后摇晃。呃。
  • @LiAungYip 我相信有一个 PEP 说这是对这种做法的正确回应。
  • @sr2222:我敢打赌,你也可以绕过它。
  • “如果它运行,它可以被黑客入侵。”
【解决方案3】:

你似乎已经掌握了窍门。唯一完全错误的是z = 300。这是 __init__ 方法的本地名称。 Python从不为你插入self,就像C++和Java在可能的地方假设this一样。

在继续学习 Python 时要记住的一件事是,成员函数始终可以作为类成员执行。考虑以下几点:

>>> class Sample(object):
...   def __init__(self, value):
...     self.value = value
...   def get_value(self):
...     return self.value
...
>>> s = Sample(1)
>>> t = Sample(2)
>>> s.get_value()
1
>>> Sample.get_value(s)
1
>>> t.__class__.get_value(s)
1

最后三个例子都调用了s对象的成员函数。最后两个使用 get_value 只是 Sample 类的一个属性这一事实,它期望接收 Sample 的实例作为参数。

【讨论】:

  • 谢谢。我看到一篇文章说通过创建 init 方法的局部变量,就像一个私有变量(就像在 Java 中一样)。但我找不到在其他任何地方访问 z 的方法。
  • 另外,我丢失了该文章的链接。 :(
猜你喜欢
  • 2011-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-30
  • 2015-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多