لماذا الثعبان هو " خاص " طرق ليست في الحقيقة خاص ؟
-
09-06-2019 - |
سؤال
بيثون يعطينا القدرة على إنشاء 'خاصة' أساليب المتغيرات داخل فئة من يتبع مزدوجة يؤكد أن الاسم مثل هذا: __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
ليست خاصة في بيثون ، فإنه ليس أكثر من شائعة اسم المعلمة الأولى من وظيفة.