为什么 Python 的“私有"方法实际上不是私有的? [英] Why are Python's 'private' methods not actually private?

查看:28
本文介绍了为什么 Python 的“私有"方法实际上不是私有的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Python 使我们能够通过在名称前加上双下划线来在类中创建私有"方法和变量,例如:__myPrivateMethod().那么,如何解释这一点

>>> class MyClass:... def myPublicMethod(self):...打印'公共方法'... def __myPrivateMethod(self):...打印'这是私人的!!'...>>> obj = MyClass()>>> obj.myPublicMethod()公共方法>>> obj.__myPrivateMethod()回溯(最近一次调用最后一次):文件",第 1 行,在AttributeError: MyClass 实例没有属性__myPrivateMethod">>> 目录(对象)['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']>>> obj._MyClass__myPrivateMethod()这是私人的!!

这是怎么回事?!

我会为那些不太明白的人解释一下.

>>> class MyClass:... def myPublicMethod(self):...打印'公共方法'... def __myPrivateMethod(self):...打印'这是私人的!!'...>>> obj = MyClass()

我所做的是创建一个具有公共方法和私有方法的类并实例化它.

接下来,我调用它的公共方法.

>>> obj.myPublicMethod()公共方法

接下来,我尝试调用它的私有方法.

>>> obj.__myPrivateMethod()回溯(最近一次调用最后一次):文件",第 1 行,在AttributeError: MyClass 实例没有属性__myPrivateMethod"

这里的一切看起来都不错;我们无法调用它.事实上,它是私人的".好吧,实际上并非如此.在对象上运行 dir() 揭示了一个新的神奇方法,python 为您的所有私有"方法神奇地创建了该方法.

>>> dir(obj)['_MyClass__myPrivateMethod', '__doc__', '__module__', 'myPublicMethod']

这个新方法的名字总是一个下划线,后面跟着类名,后面跟着方法名.

>>> obj._MyClass__myPrivateMethod()这是私人的!!

封装就这么多,嗯?

无论如何,我一直听说 Python 不支持封装,那为什么还要尝试呢?什么给?

解决方案

名称加扰用于确保子类不会意外覆盖其超类的私有方法和属性.它的设计目的不是为了防止从外部故意访问.

例如:

<预><代码>>>>类 Foo(对象):... def __init__(self):... self.__baz = 42... def foo(self):...打印 self.__baz...>>>类酒吧(Foo):... def __init__(self):... super(Bar, self).__init__()... self.__baz = 21...定义栏(自我):...打印 self.__baz...>>>x = 酒吧()>>>x.foo()42>>>x.bar()21>>>打印 x.__dict__{'_Bar__baz':21,'_Foo__baz':42}

当然,如果两个不同的类具有相同的名称,它就会崩溃.

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 "", line 1, in 
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()

What I did there is 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 "", line 1, in 
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?

解决方案

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:

>>> class Foo(object):
...     def __init__(self):
...         self.__baz = 42
...     def foo(self):
...         print self.__baz
...     
>>> class Bar(Foo):
...     def __init__(self):
...         super(Bar, self).__init__()
...         self.__baz = 21
...     def bar(self):
...         print self.__baz
...
>>> x = Bar()
>>> x.foo()
42
>>> x.bar()
21
>>> print x.__dict__
{'_Bar__baz': 21, '_Foo__baz': 42}

Of course, it breaks down if two different classes have the same name.

这篇关于为什么 Python 的“私有"方法实际上不是私有的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆