为什么 Python 是“私有的”? 方法实际上不是私有的?
Python 使我们能够通过在名称前添加双下划线来在类中创建“私有”方法和变量,如下所示:__myPrivateMethod()
。 那么,如何解释这
>>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
是怎么回事?
我将为那些不太明白的人解释一下。
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
我创建一个具有公共方法和私有方法的类并实例化它。
接下来,我调用它的公共方法。
>>> obj.myPublicMethod()
public method
接下来,我尝试调用它的私有方法。
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
这里一切看起来都很好; 我们无法调用它。 事实上,它是“私人的”。 嗯,实际上并非如此。 在对象上运行 dir() 会揭示 Python 为所有“私有”方法神奇地创建的新神奇方法。
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
这个新方法的名称始终是一个下划线,后跟类名,然后是方法名。
>>> obj._MyClass__myPrivateMethod()
this is private!!
封装就这么多了,是吗?
无论如何,我一直听说 Python 不支持封装,那为什么还要尝试呢? 是什么赋予了?
Python gives us the ability to create 'private' methods and variables within a class by prepending double underscores to the name, like this: __myPrivateMethod()
. How, then, can one explain this
>>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
>>> obj.myPublicMethod()
public method
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
>>> obj._MyClass__myPrivateMethod()
this is private!!
What's the deal?!
I'll explain this a little for those who didn't quite get that.
>>> class MyClass:
... def myPublicMethod(self):
... print 'public method'
... def __myPrivateMethod(self):
... print 'this is private!!'
...
>>> obj = MyClass()
I create a class with a public method and a private method and instantiate it.
Next, I call its public method.
>>> obj.myPublicMethod()
public method
Next, I try and call its private method.
>>> obj.__myPrivateMethod()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: MyClass instance has no attribute '__myPrivateMethod'
Everything looks good here; we're unable to call it. It is, in fact, 'private'. Well, actually it isn't. Running dir()
on the object reveals a new magical method that Python creates magically for all of your 'private' methods.
>>> dir(obj)
['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']
This new method's name is always an underscore, followed by the class name, followed by the method name.
>>> obj._MyClass__myPrivateMethod()
this is private!!
So much for encapsulation, eh?
In any case, I'd always heard Python doesn't support encapsulation, so why even try? What gives?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
发布评论
评论(12)
重要提示:
任何 __name
形式的标识符(至少两个前导下划线,最多一个尾随下划线)都会公开替换为 _classname__name
,其中 classname
是当前类名,去掉了前导下划线。
因此,__name
无法直接访问,但可以通过_classname__name
访问。
这并不意味着您可以按原样保护您的私有数据通过更改变量名称即可轻松访问。
来源:
官方文档中的“私有变量”部分:https://docs。 python.org/3/tutorial/classes.html#tut-private
示例
class Cat:
def __init__(self, name='unnamed'):
self.name = name
def __print_my_name(self):
print(self.name)
tom = Cat()
tom.__print_my_name() #Error
tom._Cat__print_my_name() #Prints name
严格来说,私有方法是
可以在课堂之外访问,只需
不容易到达。 里面什么都没有
Python 是真正私有的; 内部,
私有方法的名称和
属性被破坏和未破坏
飞快地让他们看起来
无法通过他们的名字来访问。 你
可以访问 __parse 方法
MP3FileInfo 类的名称
_MP3FileInfo__解析。 承认这很有趣,然后承诺
永远、永远不要在真正的代码中这样做。
私有方法对于 a 来说是私有的
原因,但就像许多其他事情一样
Python,他们的隐私是
最终是一个惯例问题,而不是
力。
私有函数示例
import re
import inspect
class MyClass:
def __init__(self):
pass
def private_function(self):
try:
function_call = inspect.stack()[1][4][0].strip()
# See if the function_call has "self." in the beginning
matched = re.match( '^self\.', function_call)
if not matched:
print 'This is a private function. Go away.'
return
except:
print 'This is a private function. Go away.'
return
# This is the real function, only accessible inside the class #
print 'Hey, welcome in to the function.'
def public_function(self):
# I can call a private function from inside the class
self.private_function()
### End ###
当我第一次从 Java 转向 Python 时,我讨厌这个。 吓死我了。
今天,这可能是关于 Python 我最喜欢的一件事。
我喜欢在一个平台上,人们彼此信任,并且不需要在代码周围建立坚不可摧的墙。 在强封装语言中,如果 API 有错误,并且您已经找出了问题所在,您可能仍然无法解决它,因为所需的方法是私有的。 在 Python 中,态度是:“当然”。 如果你认为你了解情况,也许你已经读过它,那么我们只能说“祝你好运!”。
请记住,封装与“安全”或让孩子远离草坪甚至没有微弱的关系。 这只是另一种应该用来使代码库更易于理解的模式。
对于 Python 3.4,这是行为:
>>> class Foo:
def __init__(self):
pass
def __privateMethod(self):
return 3
def invoke(self):
return self.__privateMethod()
>>> help(Foo)
Help on class Foo in module __main__:
class Foo(builtins.object)
| Methods defined here:
|
| __init__(self)
|
| invoke(self)
|
| ----------------------------------------------------------------------
| Data descriptors defined here:
|
| __dict__
| dictionary for instance variables (if defined)
|
| __weakref__
| list of weak references to the object (if defined)
>>> f = Foo()
>>> f.invoke()
3
>>> f.__privateMethod()
Traceback (most recent call last):
File "<pyshell#47>", line 1, in <module>
f.__privateMethod()
AttributeError: 'Foo' object has no attribute '__privateMethod'
从 9.6 开始。 私有变量:
请注意,修改规则主要是为了避免意外而设计的; 仍然可以访问或修改被视为私有的变量。这甚至在特殊情况下很有用,例如在调试器中。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
名称加扰用于确保子类不会意外覆盖其超类的私有方法和属性。 它的设计初衷并不是为了防止来自外部的故意访问。
例如:
当然,如果两个不同的类具有相同的名称,它就会崩溃。
The name scrambling is used to ensure that subclasses don't accidentally override the private methods and attributes of their superclasses. It's not designed to prevent deliberate access from outside.
For example:
Of course, it breaks down if two different classes have the same name.