Omn*_*ent 532 python private class
我来自Java世界并阅读Bruce Eckels的Python 3模式,食谱和成语.
在阅读类时,接着说在Python中没有必要声明实例变量.你只需在构造函数中使用它们,然后繁荣,它们就在那里.
例如:
class Simple:
def __init__(self, s):
print("inside the simple constructor")
self.s = s
def show(self):
print(self.s)
def showMsg(self, msg):
print(msg + ':', self.show())
Run Code Online (Sandbox Code Playgroud)
如果这是真的,那么类的任何对象都Simple可以只改变s类外的变量值.
例如:
if __name__ == "__main__":
x = Simple("constructor argument")
x.s = "test15" # this changes the value
x.show()
x.showMsg("A message")
Run Code Online (Sandbox Code Playgroud)
在Java中,我们学习了有关公共/私有/受保护变量的知识.这些关键字是有意义的,因为有时你想要类中的变量,类外没有人可以访问.
为什么Python中不需要这样做?
Kir*_*ser 915
这是文化.在Python中,您不会写入其他类的实例或类变量.在Java中,如果你真的想要,没有什么能阻止你做同样的事情- 毕竟,你总是可以编辑类本身的源来达到同样的效果.Python放弃了安全性的假装并鼓励程序员负责.在实践中,这非常好用.
如果由于某种原因想要模拟私有变量,可以始终使用PEP 8中的__前缀.Python破坏了变量的名称,使得它们不容易被包含它们的类外的代码看到(尽管如果你足够坚定,你可以解决它,就像你可以绕过Java的保护,如果你在它工作).__foo
按照相同的惯例,即使您没有在技术上阻止这样做,_前缀意味着远离.你不会玩另一个看起来像__foo或类的变量_bar.
wat*_*HUN 141
python中的私有变量或多或少是一个hack:解释器故意重命名变量.
class A:
def __init__(self):
self.__var = 123
def printVar(self):
print self.__var
Run Code Online (Sandbox Code Playgroud)
现在,如果您尝试__var在类定义之外访问,它将失败:
>>>x = A()
>>>x.__var # this will return error: "A has no attribute __var"
>>>x.printVar() # this gives back 123
Run Code Online (Sandbox Code Playgroud)
但你可以很容易地逃脱这个:
>>>x.__dict__ # this will show everything that is contained in object x
# which in this case is something like {'_A__var' : 123}
>>>x._A__var = 456 # you now know the masked name of private variables
>>>x.printVar() # this gives back 456
Run Code Online (Sandbox Code Playgroud)
您可能知道OOP中的方法是这样调用的:x.printVar() => A.printVar(x)如果A.printVar()可以访问某个字段x,则此字段也可以在外部 访问A.printVar()...毕竟,函数是为了可重用性而创建的,内部语句没有特殊的功能.
当涉及编译器时,游戏是不同的(隐私是编译器级概念).它知道带有访问控制修饰符的类定义,因此如果在编译时没有遵循规则,它就会出错
小智 27
正如上面许多评论中正确提到的那样,让我们不要忘记访问修饰符的主要目标:帮助代码用户理解应该更改的内容和不应该更改的内容.当你看到私人领域时,你不会乱用它.所以它主要是语法糖,可以通过_和__在Python中轻松实现.
S.L*_*ott 19
"在java中,我们已经了解了公共/私有/受保护的变量"
"为什么在python中不需要?"
出于同样的原因,Java中不需要它.
你可以自由使用 - 或者不使用private和protected.
作为一个Python和Java程序员,我发现,private和protected是非常,非常重要的设计理念.但实际上,在数以万计的Java和Python系列中,我从未真正使用过private或者protected.
为什么不?
这是我的问题"受到谁保护?"
我团队中的其他程序员?他们有源头.受保护意味着何时可以改变它?
其他团队的其他程序员?他们在同一家公司工作.他们可以 - 通过电话 - 获取消息来源.
客户端?这是一种招聘工作(一般).客户(通常)拥有代码.
那么,究竟是谁 - 我保护它免受伤害?
对.拒绝阅读API评论的精神分裂症反社会人士阻止.
Sha*_*yne 18
下划线约定中有一些私有变量.
In [5]: class Test(object):
...: def __private_method(self):
...: return "Boo"
...: def public_method(self):
...: return self.__private_method()
...:
In [6]: x = Test()
In [7]: x.public_method()
Out[7]: 'Boo'
In [8]: x.__private_method()
---------------------------------------------------------------------------
AttributeError Traceback (most recent call last)
<ipython-input-8-fa17ce05d8bc> in <module>()
----> 1 x.__private_method()
AttributeError: 'Test' object has no attribute '__private_method'
Run Code Online (Sandbox Code Playgroud)
有一些微妙的差异,但为了编程模式的思想纯度,它足够好.
有一些@private装饰器的例子更接近实现这个概念,但是YMMV.可以说,人们也可以写一个使用meta的类定义
Hat*_*ter 12
Python 没有像 C++ 或 Java 那样的任何私有变量。如果需要,您也可以随时访问任何成员变量。但是,在 Python 中不需要私有变量,因为在 Python 中公开类成员变量也不错。如果您需要封装成员变量,您可以稍后使用“@property”来完成此操作,而不会破坏现有的客户端代码。
在 python 中,单个下划线“_”用于表示方法或变量不被视为类的公共 api 的一部分,并且 api 的这一部分可能会在不同版本之间发生变化。您可以使用这些方法/变量,但如果您使用此类的较新版本,您的代码可能会中断。
双下划线“__”并不意味着“私有变量”。您可以使用它来定义“类本地”变量,并且不能轻易被子类覆盖。它破坏了变量名称。
例如:
class A(object):
def __init__(self):
self.__foobar = None # will be automatically mangled to self._A__foobar
class B(A):
def __init__(self):
self.__foobar = 1 # will be automatically mangled to self._B__foobar
Run Code Online (Sandbox Code Playgroud)
self.__foobar 的名称在 A 类中被自动修改为 self._A__foobar。在 B 类中它被修改为 self._B__foobar。所以每个子类都可以定义自己的变量 __foobar 而不覆盖其父变量。但是没有什么可以阻止您访问以双下划线开头的变量。但是,名称修改可防止您偶然调用此变量/方法。
我强烈建议您在 Pycon 2013 中观看 Raymond Hettinger 的Python 类开发工具包,它提供了一个很好的示例,为什么以及如何使用 @property 和“__”-instance 变量。
如果你已经暴露了公共变量并且需要封装它们,那么你可以使用@property。因此,您可以从最简单的解决方案开始。除非您有具体的理由不这样做,否则您可以将成员变量设为公开。下面是一个例子:
class Distance:
def __init__(self, meter):
self.meter = meter
d = Distance(1.0)
print(d.meter)
# prints 1.0
class Distance:
def __init__(self, meter):
# Customer request: Distances must be stored in millimeters.
# Public available internals must be changed.
# This would break client code in C++.
# This is why you never expose public variables in C++ or Java.
# However, this is python.
self.millimeter = meter * 1000
# In python we have @property to the rescue.
@property
def meter(self):
return self.millimeter *0.001
@meter.setter
def meter(self, value):
self.millimeter = meter * 1000
d = Distance(1.0)
print(d.meter)
# prints 1.0
Run Code Online (Sandbox Code Playgroud)
Isa*_*old 10
如前所述,您可以通过在其前面添加下划线来指示变量或方法是私有的.如果您觉得这不够,您可以随时使用property装饰器.这是一个例子:
class Foo:
def __init__(self, bar):
self._bar = bar
@property
def bar(self):
"""Getter for '_bar'."""
return self._bar
Run Code Online (Sandbox Code Playgroud)
这样,引用的某个人或某个东西bar实际上是引用bar函数的返回值而不是变量本身,因此可以访问但不能更改它.但是,如果有人真的想要,他们可以简单地使用_bar并为其分配新值.正如已经反复说过的那样,没有万无一知的方法来阻止某人访问你想要隐藏的变量和方法.但是,使用property是您可以发送的最清晰的消息,即不编辑变量.property也可以用于更复杂的getter/setter/deleter访问路径,如下所述:https://docs.python.org/3/library/functions.html#property
小智 8
我唯一一次使用私有变量是在写入或读取变量时我需要做其他事情,因此我需要强制使用setter和/或getter.
如前所述,这再次涉及文化.我一直致力于读取和编写其他类变量的项目是免费的.当一个实现被弃用时,需要花费更长的时间来识别使用该功能的所有代码路径.当强制使用setter和getter时,可以很容易地编写一个debug语句来识别已经调用过的方法以及调用它的代码路径.
当您在一个任何人都可以编写扩展的项目中,通知用户有关在几个版本中消失的弃用方法因此对于在升级时将模块破坏保持在最低限度至关重要.
所以我的答案是; 如果您和您的同事维护一个简单的代码集,那么保护类变量并不总是必要的.如果您正在编写可扩展系统,则必须使用代码对所有扩展需要捕获的核心进行更改.
小智 7
私人和受保护的概念非常重要.但是python - 只是一个用于原型设计和快速开发的工具,可用于开发的资源有限,这就是为什么python中的一些保护级别不是那么严格的原因.您可以在类成员中使用"__",它可以正常工作,但看起来不够好 - 每次访问此类字段都包含这些字符.
此外,你可以注意到python OOP概念并不完美,smaltalk或ruby更接近纯OOP概念.甚至C#或Java也更接近.
Python是非常好的工具.但它是简化的OOP语言.在语法和概念上简化.python存在的主要目标是为开发人员提供以非常快的方式编写具有高抽象级别的易读代码的可能性.
抱歉,“恢复”线程,但是,我希望这会对某人有所帮助:
在Python3中,如果您只想“封装”类属性(例如在Java中),则可以执行以下操作:
class Simple:
def __init__(self, str):
print("inside the simple constructor")
self.__s = str
def show(self):
print(self.__s)
def showMsg(self, msg):
print(msg + ':', self.show())
Run Code Online (Sandbox Code Playgroud)
要实例化此操作,请执行以下操作:
ss = Simple("lol")
ss.show()
Run Code Online (Sandbox Code Playgroud)
注意:print(ss.__s)会抛出错误。
实际上,Python3将混淆全局属性名称。像在Java中一样,将其变为“私有”属性。该属性的名称仍然是全局的,但是以一种无法访问的方式,就像其他语言中的私有属性一样。
但是不要害怕。没关系 它也做这项工作。;)
| 归档时间: |
|
| 查看次数: |
416657 次 |
| 最近记录: |