سؤال

بيثون يعطينا القدرة على إنشاء 'خاصة' أساليب المتغيرات داخل فئة من يتبع مزدوجة يؤكد أن الاسم مثل هذا: __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 "", line 1, in 
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 "", line 1, in 
AttributeError: MyClass instance has no attribute '__myPrivateMethod'

كل شيء يبدو جيدا هنا ؛ نستطيع أن نسميها.هو ، في الواقع ، 'الخاصة'.في الواقع ليس كذلك.تشغيل dir() على الكائن يكشف عن طريقة سحرية جديدة أن الثعبان يخلق سحرية من "الخاص" الأساليب.

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

هذا الأسلوب الجديد اسم هو دائما تسطير ، يليه اسم الفئة ، يليه اسم الأسلوب.

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

كثيرا التغليف ؟

في أي حال, كنت دائما استمع الثعبان لا يدعم التغليف ، فلماذا تحاول حتى ؟ ما يعطي ؟

هل كانت مفيدة؟

المحلول

اسم الهرولة المستخدمة لضمان فرعية لا قصد تجاوز أساليب خاصة وسمات من superclasses.إنها لا تهدف إلى منع المتعمد الوصول من الخارج.

على سبيل المثال:

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

وبطبيعة الحال, فإنه ينهار إذا اثنين من فئات مختلفة لها نفس الاسم.

نصائح أخرى

مثال على وظيفة خاصة

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

عندما جئت لأول مرة من جاوة إلى بيثون أنا كرهت هذا.انها خائفة من الموت.

اليوم قد يكون مجرد شيء واحد أنا أحب أكثر عن الثعبان.

أحب أن أكون على منصة ، حيث كان الناس يثقون في بعضهم البعض و لا يشعرون أنهم بحاجة إلى بناء الجدران التي لا يمكن اختراقها حول التعليمات البرمجية الخاصة بهم.في بقوة مغلفة اللغات ، إذا API له علة, و كنت احسب ما يذهب على نحو خاطئ, قد يكون لا يزال غير قادر على العمل حوله لأن الحاجة طريقة خاصة.في بيثون الموقف هو:"بالتأكيد".إذا كنت تعتقد أنك تفهم الوضع, ربما لديك حتى قراءة ذلك, ثم كل ما يمكننا قوله هو "حظا سعيدا!".

تذكر التغليف حتى لا ضعيفة ذات الصلة "الأمن" ، أو الحفاظ على الاطفال من العشب.هو مجرد نمط آخر ينبغي أن تستخدم لجعل رمز قاعدة أسهل للفهم.

من http://www.faqs.org/docs/diveintopython/fileinfo_private.html

بالمعنى الدقيق للكلمة ، خاصة الطرق يمكن الوصول إليها من خارج هذه الفئة فقط لا يمكن الوصول إليها بسهولة.لا شيء في بيثون هو حقا من القطاع الخاص ؛ داخليا ، أسماء أساليب خاصة ، سمات تلفت unmangled على الطاير لجعلها تبدو لا يمكن الوصول إليها من قبل أسمائهم.لك يمكن الوصول إلى __تحليل طريقة MP3FileInfo الدرجة اسمه _MP3FileInfo__تحليل.نعترف بأن هذا هو المثير للاهتمام ، ثم وعد أبدا لا تفعل ذلك في رمز حقيقي.خاصة أساليب القطاع الخاص السبب, ولكن مثل أشياء أخرى كثيرة في بيثون ، خصوصية هو في نهاية المطاف مسألة الاتفاقية ، القوة.

عبارة تستخدم عادة هو "نحن جميعا بالغين متراضين هنا".قبل أن يتبع واحد التأكيد (لا تعرض) أو مزدوجة تؤكد (إخفاء) أنت تقول المستخدم من الفئة الخاصة بك أن كنت تنوي الأعضاء إلى " خاص " في بعض الطريق.ومع ذلك ، كنت يثق الجميع إلى التصرف بمسؤولية واحترام ، ما لم يكن لديهم سبب مقنع لا (مثلا ، مصححات إنجاز قانون).

إذا كنت حقا يجب أن يكون شيئا خاصا ، ثم يمكنك تنفيذ ذلك في ملحق (مثلا ، في C CPython).في معظم الحالات, لكن, يمكنك ببساطة تعلم Pythonic وسيلة للقيام بهذه الأمور.

انها ليست مثل كنت وأنا لا يمكن أن تحصل حول خصوصية الأعضاء في أي لغة (مؤشر الحساب في C++, تأملات في .NET/Java).

وهذه النقطة هي أن تحصل على خطأ إذا حاولت الاتصال الخاصة طريقة عن طريق الصدفة.ولكن إذا كنت تريد أن تطلق النار على قدمك, المضي قدما ونفعل ذلك.

تحرير:لا تحاول تأمين الأشياء الخاصة بك بواسطة OO-تغليف, أليس كذلك ؟

على class.__stuff تسمية الاتفاقية يتيح للمبرمج أعلم أنه ليس من المفترض أن الوصول __stuff من خارج.اسم تغيير اسم يجعل من المرجح أن أي شخص سوف تفعل ذلك عن طريق الصدفة.

صحيح أنت لا يزال يمكن أن تعمل حول هذا الأمر أسهل مما كانت عليه في اللغات الأخرى (والتي بالمناسبة أيضا تمكنك من فعل هذا), ولكن لا بيثون مبرمج تفعل هذا إذا كان يهتم التغليف.

سلوك مماثل موجود عند وحدة السمة أسماء تبدأ مع واحد يؤكد (على سبيل المثال_foo).

وحدة سمات اسمه على هذا النحو لا يمكن نسخها إلى استيراد وحدة عند استخدام from* طريقة, على سبيل المثال:

from bar import *

إلا أن هذه الاتفاقية لا تشكل اللغة عائقا.هذه ليست خاصة الصفات ؛ أنها يمكن الرجوع إليها و التلاعب بها من قبل أي المستورد.ويرى البعض أنه بسبب هذا الثعبان لا يمكن تنفيذ صحيح التغليف.

انها مجرد واحدة من تلك اللغة خيارات التصميم.على مستوى ما كانت مبررة.أنها تجعل من ذلك عليك أن تذهب بعيدا جدا للخروج من الطريق الخاص بك في محاولة استدعاء الأسلوب ، إذا كنت حقا في حاجة إليها بشدة, يجب أن يكون لديك سبب جيد!

التصحيح السنانير اختبار تتبادر إلى الذهن ممكن تطبيقات استخدامها بمسؤولية بالطبع.

مع بايثون 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'

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

لاحظ أن تغيير اسم القواعد صممت في الغالب لتجنب الحوادث ؛ فإنه لا يزال من الممكن الوصول إلى أو تعديل متغير التي تعتبر خاصة. هذا يمكن أن تكون مفيدة حتى في ظروف خاصة ، مثل في المصحح.

حتى إذا كان السؤال القديم اتمنى ان مقتطف يمكن أن تكون مفيدة.

أهم القلق حول طرق خاصة وسمات هو أن أقول المطورين لا نسميها خارج الصف و هذا هو التغليف.واحد قد يسيئون فهم الأمن من التغليف.عندما تعمد استخدام بناء الجملة هكذا(خوار) ذكرت, كنت لا تريد التغليف.

obj._MyClass__myPrivateMethod()

لقد هاجروا من C# و في البداية كان الأمر غريبا جدا بالنسبة لي ولكن بعد حين جئت إلى فكرة أن الطريقة التي الثعبان رمز المصممين التفكير OOP مختلفة.

لماذا الثعبان هو " خاص " طرق ليست في الحقيقة خاص ؟

كما فهمت أنها لا يمكن تكون خاصة.كيف يمكن أن الخصوصية أن تنفذ ؟

الجواب الواضح هو "خاصة أعضاء يمكن الوصول إليها فقط من خلال self"لكن هذا لن ينجح - self ليست خاصة في بيثون ، فإنه ليس أكثر من شائعة اسم المعلمة الأولى من وظيفة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top