it-swarm-tr.com

Python'un 'özel' yöntemleri neden aslında özel değil?

Python bize şu şekilde ismine çift alt çizgi hazırlayarak bir sınıf içinde 'özel' yöntem ve değişkenler yaratma yeteneği verir: __myPrivateMethod(). Öyleyse, kimse bunu nasıl açıklayabilir?

>>> 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!!

Anlaşma ne?!

Bunu tam olarak anlamayanlara biraz açıklayacağım.

>>> class MyClass:
...     def myPublicMethod(self):
...             print 'public method'
...     def __myPrivateMethod(self):
...             print 'this is private!!'
... 
>>> obj = MyClass()

Orada yaptığım şey, herkese açık bir yöntem ve özel bir yöntem içeren bir sınıf oluşturmak ve onu başlatmak.

Sonra genel yöntemini çağırırım.

>>> obj.myPublicMethod()
public method

Sonra, özel yöntemini çağırmaya çalışıyorum.

>>> obj.__myPrivateMethod()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

Burada her şey iyi görünüyor; arayamıyoruz. Aslında, 'özel'. Şey, aslında değil. Nesne üzerinde dir () çalıştırmak, python'un tüm 'özel' yöntemleriniz için sihirli bir şekilde yarattığı yeni bir büyülü yöntemi ortaya koyuyor.

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

Bu yeni yöntemin adı daima bir alt çizgidir, bunu sınıf adı takip eder, ardından yöntem adı takip eder.

>>> obj._MyClass__myPrivateMethod()
this is private!!

Kapsülleme için çok fazla, ha?

Her durumda, Python'un enkapsülasyonu desteklemediğini her zaman duymuştum, neden denesin ki? Ne verir?

557
willurd

Çırpma adı, alt sınıfların yanlışlıkla üst sınıflarının özel yöntem ve niteliklerini geçersiz kılmamasını sağlamak için kullanılır. Dışarıdan kasıtlı erişimi engellemek için tasarlanmamıştır.

Örneğin:

>>> 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}

Elbette, iki farklı sınıf aynı ada sahipse bozulur.

524
Alya

Özel fonksiyon örneği

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 begining
            matched = re.match( '^self\.', function_call )
            if not matched :
                print 'This is Private Function, Go Away'
                return
        except :
            print 'This is Private Function, Go Away'
            return

        # This is the real Function, only accessible inside class #
        print 'Hey, Welcome in to function'

    def public_function ( self ) :
        # i can call private function from inside the class
        self.private_function()

### End ###
206
arun

Java'dan Python'a ilk geldiğimde I nefret bu. Beni ölümüne korkuttu.

Bugün sadece bir şey olabilir en çok seviyorum Python hakkında.

İnsanların birbirlerine güvendikleri ve kodlarının etrafına geçilemez duvarlar inşa etmeleri gerektiğini hissetmedikleri bir platformda olmayı seviyorum. Güçlü bir şekilde kapsüllenmiş dillerde, eğer bir API'de bir hata varsa ve neyin yanlış gittiğini anladıysanız, gerekli yöntem özel olduğundan, bunun üzerinde çalışmaya devam edemeyebilirsiniz. Python'da tutum: "kesin". Durumu anladığınızı düşünüyorsanız, belki de okudunuz bile, diyebileceğimiz tek şey "iyi şanslar!".

Enkapsülasyonun “güvenlik” ile ya da çocukları çimlerden uzak tutmanın bile zayıf bir ilişkisi olmadığını unutmayın. Bir kod tabanının anlaşılmasını kolaylaştırmak için kullanılması gereken başka bir kalıptır.

141
Thomas Ahle

Http://www.faqs.org/docs/diveintopython/fileinfo_private.html adresinden

Açıkçası, özel yöntemler. sınıflarının dışında erişilebilir, sadece. Kolayca erişilebilir değil. Hiçbir şey yok. Python gerçekten özeldir; içten, Özel yöntemlerin isimleri ve özellikleri karıştırılmış ve yönetilmemiş Onları görünmesi için anında. verilen isimlerle erişilemez. Sen .__ 'nın __parse yöntemine erişebilir. MP3FileInfo sınıfı adına göre. _MP3FileInfo__parse. Bunun ilginç olduğunu kabul edin, ardından asla, asla gerçek kodla yapmazsın. Özel yöntemler a .__ için özeldir. nedeni, ama diğer birçok şey gibi. Python, şaheserleri de Nihayetinde kongre meselesi, değil. Kuvvet.

134
xsl

Yaygın olarak kullanılan ifade "hepimiz yetişkinlere burada izin veriyoruz" ifadesidir. Tek bir alt çizgi (gösterme) veya çift alt çizgi (gizleme) hazırlayarak, sınıfınızın kullanıcısına bir şekilde 'özel' olmayı düşündüğünüzü söylersiniz. Ancak, başkalarının sorumlu davranmalarına ve saygı duymadıklarına (örneğin hata ayıklayıcılar, kod tamamlama) gerekmediği sürece saygı duymalarına güveniyorsunuz.

Gerçekten özel bir şeye sahip olmanız gerekiyorsa, bunu bir uzantıda (örneğin CPython için C) uygulayabilirsiniz. Çoğu durumda, ancak, Pythonic şeyler yapmanın yolunu öğrenirsiniz.

86
Tony Meyer

Hiçbir dilde üyelerin gizliliğini çözemezsiniz (C++ 'daki işaretçi aritmetik, .NET/Java içindeki yansımalar).

Mesele şu ki, özel yöntemi kazara çağırmaya kalkarsanız hata alırsınız. Ama kendini ayağından vurmak istiyorsan, devam et ve yap.

Düzenleme: Eşyalarını O-kapsülleme ile korumaya çalışmıyorsun, değil mi?

32
Maximilian

Modül öznitelik adları tek bir alt çizgi (örneğin, _foo) ile başladığında da benzer davranışlar görülür.

Bunun gibi adlandırılmış modül nitelikleri, from* yöntemini kullanırken bir içe aktarma modülüne kopyalanmayacaktır;

from bar import *

Ancak, bu bir kural değil, bir dil kısıtlamasıdır. Bunlar özel nitelikler değildir; herhangi bir ithalatçı tarafından referans alınabilir ve değiştirilebilir. Bazıları, bu nedenle Python’un gerçek bir enkapsülasyonu uygulayamayacağını savunuyor.

12
Ross

Bu dil tasarım seçeneklerinden sadece bir tanesi. Bir düzeyde onlar haklı. Onlar bunu yapar, bu yüzden yöntemi denemek ve çağırmak için oldukça yolunuza gitmeniz gerekir ve gerçekten bu kadar çok ihtiyacınız varsa, oldukça iyi bir nedeniniz olmalı!

Hata ayıklama kancaları ve testleri, elbette, sorumlu bir şekilde kullanılan olası uygulamalar olarak akla gelmektedir.

12
ctcherry

class.__stuff adlandırma kuralı, programcının dışarıdan __stuff öğesine erişmesi gerekmediğini bilmesini sağlar. “Mangling” ismi, kimsenin kazara yapması ihtimalinin düşük olmasını sağlıyor.

Doğru, hala bu konuda çalışabilirsiniz, diğer dillerden bile daha kolaydır (BTW bunu yapmanıza da izin verir), ancak kapsülleme ile ilgileniyorsa hiçbir Python programcısı bunu yapmaz.

11
Nickolay

Python 3.4 ile bu davranış:

>>> 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'

https://docs.python.org/3/tutorial/classes.html#tut-private

Yönetim kurallarının çoğunlukla kazaları önlemek için tasarlandığını unutmayın; Özel sayılan bir değişkene erişmek veya bunları değiştirmek hala mümkündür. Bu, hata ayıklayıcı gibi özel durumlarda bile faydalı olabilir.

Soru eski olsa bile, pasajımın yardımcı olacağını umuyorum.

3
Alberto

Özel yöntemler ve niteliklerle ilgili en önemli endişe, geliştiricilere sınıf dışında çağırmamalarını söylemektir ve bu kapsüllemedir. bir kişi kapsülleme nedeniyle güvenliği yanlış anlayabilir. Bir kişi kasıtlı olarak bahsettiğiniz sözdizimini (feryat) kullandığında, kapsülleme istemezsiniz.

obj._MyClass__myPrivateMethod()

C # 'dan göç ettim ve ilk başta benim için de tuhaftı ama bir süre sonra Python kod tasarımcılarının OOP hakkındaki düşüncelerinin farklı olduğu fikrine geldim. 

2
Afshin Amiri

Python'un 'özel' yöntemleri neden aslında özel değil?

Anladığım kadarıyla olamaz özel olmalılar. Mahremiyet nasıl uygulanabilir?

Açıkça cevap, "özel üyelere yalnızca self yoluyla erişilebilir" şeklindedir, ancak işe yaramaz - Pyvhon'da self özel değildir, bir işlevin ilk parametresi için sık kullanılan bir addan başka bir şey değildir.

0
user200783