293

http://www.faqs.org/docs/diveintopython/fileinfo_private.htmlによると:

ほとんどの言語と同様に、Pythonにはプライベート要素の概念があります。

  • モジュールの外部から呼び出すことができないプライベート関数

ただし、2つのファイルを定義すると、次のようになります。

#a.py
__num=1

と:

#b.py
import a
print a.__num

実行すると、例外なくb.py出力されます。1diveintopythonは間違っていますか、それとも私は何かを誤解しましたか?そして、モジュールの関数をプライベートとして定義する方法はありますか?

4

9 に答える 9

409

Pythonでは、「プライバシー」は「同意する大人の」合意レベルに依存します-強制することはできません(実際の生活でできる以上のことです;-)。単一の先頭のアンダースコアは、「外部から」アクセスすることを想定していないことを意味します。2つの先頭のアンダースコア(末尾のアンダースコアなし)は、メッセージをさらに強力に伝達します...しかし、最終的には、ソーシャルに依存します。慣習とコンセンサス:Pythonの内省は十分に強力であるため、世界中の他のすべてのプログラマーに手錠をかけて自分の希望を尊重することはできません。

((ところで、これは秘密にされていますが、C ++でもほぼ同じです。ほとんどのコンパイラでは、ファイルを作成する#define private public前の簡単な行だけで、賢いコーダーが「プライバシー」のハッシュを作成できます...!-) )。#include.h

于 2009-10-10T05:43:03.570 に答える
333

クラスプライベートモジュールプライベートの間で混乱が生じる可能性があります。

モジュールprivateは1つのアンダースコアで始まりますこのような要素は、importコマンド
の形式を使用するときに一緒にコピーされません。ただし、構文from <module_name> import *を使用する場合はインポートされます( Ben Wilhelmの回答を参照) 。質問の例のa .__ numからアンダースコアを1つ削除するだけで、構文を使用してa.pyをインポートするモジュールには表示されません。import <moudule_name>
from a import *

クラスprivateは、2つのアンダースコア (別名dunder、つまりd-oubleアンダースコア)で始まります。
このような変数の名前は「mangled」で、クラス名などが含まれます。mangled名
を使用して、クラスロジックの外部からアクセスできます。
名前マングリングは、不正アクセスに対する軽度の防止デバイスとして機能しますが、その主な目的は、祖先クラスのクラスメンバーとの名前の衝突を防ぐことです。アレックス・マルテッリがこれらの変数に関して使用される慣習を説明しているので、同意する大人への面白いが正確な言及を参照してください。

>>> class Foo(object):
...    __bar = 99
...    def PrintBar(self):
...        print(self.__bar)
...
>>> myFoo = Foo()
>>> myFoo.__bar  #direct attempt no go
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Foo' object has no attribute '__bar'
>>> myFoo.PrintBar()  # the class itself of course can access it
99
>>> dir(Foo)    # yet can see it
['PrintBar', '_Foo__bar', '__class__', '__delattr__', '__dict__', '__doc__', '__
format__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__',
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__
', '__subclasshook__', '__weakref__']
>>> myFoo._Foo__bar  #and get to it by its mangled name !  (but I shouldn't!!!)
99
>>>
于 2009-10-10T05:40:54.340 に答える
95

モジュールのプライバシーは純粋に慣習的なものではないため、この質問には完全には答えていません。

モジュールでプライベート名を定義すると、それらの名前、構文「import module_name」を使用するすべてのスクリプトにインポートされます。したがって、例でモジュールprivate、_numをa.pyで正しく定義したと仮定すると、次のようになります..

#a.py
_num=1

..モジュール名記号を使用して b.py でアクセスできます。

#b.py
import a
...
foo = a._num # 1

a.py から非プライベートのみをインポートするには、from構文を使用する必要があります。

#b.py
from a import *
...
foo = _num # throws NameError: name '_num' is not defined

ただし、明確にするために、モジュールから名前をインポートするときは、すべてを「*」でインポートするよりも、明示的に指定することをお勧めします。

#b.py
from a import name1 
from a import name2
...
于 2012-11-29T03:50:32.373 に答える
35

Pythonでは、二重アンダースコアプレフィックスを持つプライベートクラスメンバーを使用できます。この手法はモジュールレベルでは機能しないため、これはDiveIntoPythonの間違いだと思います。

プライベートクラス関数の例を次に示します。

class foo():
    def bar(self): pass
    def __bar(self): pass

f = foo()
f.bar()   # this call succeeds
f.__bar() # this call fails
于 2009-10-10T05:39:17.650 に答える
1

クロージャーまたは関数を埋め込むことは 1 つの方法です。これは JS では一般的ですが、ブラウザ以外のプラットフォームやブラウザ ワーカーには必要ありません。

Python では少し奇妙に思えますが、何かを本当に隠す必要がある場合は、それが方法かもしれません。さらに言えば、Python API を使用して、C (または他の言語) で非表示にする必要があるものを維持することが、おそらく最良の方法です。コードを関数内に配置し、それを呼び出して、エクスポートするアイテムを返すようにすることに失敗しました。

于 2018-01-14T11:25:00.843 に答える
-21

Python には、private、public、および protected の 3 つのモードがあります。モジュールのインポート中は、public モードのみにアクセスできます。したがって、private および protected モジュールは、モジュールの外部、つまり import 時に呼び出すことはできません。

于 2016-06-18T08:40:48.907 に答える