Skip to content

Commit 83bdc04

Browse files
author
Saeid Darvish
committed
l20: complete - Encapsulation
1 parent 0dfb1f2 commit 83bdc04

1 file changed

Lines changed: 96 additions & 1 deletion

File tree

lessons/l20.rst

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,102 @@
3131

3232
در مبحث شی گرایی به پنهان‌سازی اطلاعات درونی یک شی و محدود کردن دسترسی به آن‌ها از بیرون، **کپسوله‌سازی (Encapsulation)** گفته می‌شود - در واقع Encapsulation برابر است با **Information hiding**.
3333

34-
زبان برنامه‌نویسی پایتون از فلسفه‌ای به نام «اینجا همه بزرگسال هستیم» "we are all consenting adults here" پیروی می‌کند! بنابراین این زبان برخلاف زبان‌هایی همانند Java یک Encapsulation قوی و محافظت شده در اختیار برنامه‌نویس قرار نمی‌دهد. پایتون به برنامه‌نویس اعتماد دارد و می‌گوید «اگر دوست داری در مکان‌های تاریک پرسه بزنی، من مطمئنم که دلیل خوبی داری و هیچ مشکلی ایجاد نمی‌کنی!»
34+
زبان برنامه‌نویسی پایتون از فلسفه‌ای به نام «اینجا همه بزرگسال هستیم» "we are all consenting adults here" پیروی می‌کند! بنابراین این زبان برخلاف زبان‌هایی مانند Java و ++C یک Encapsulation قوی (strong) در اختیار برنامه‌نویس قرار نمی‌دهد. پایتون به برنامه‌نویس اعتماد دارد و می‌گوید «اگر دوست داری در مکان‌های تاریک پرسه بزنی، من مطمئنم که دلیل خوبی داری و هیچ مشکلی ایجاد نمی‌کنی!»
35+
36+
37+
.. tip::
38+
به صورت پیش‌فرض تمام اجزای داخلی یک کلاس، **public** هستند و از هر جایی خارج از کلاس مرتبط خود، قابل دستیابی می‌باشند.
39+
40+
.. tip::
41+
بر اساس یک قرارداد مابین برنامه‌نویسان پایتون،‌ چنانچه ابتدای نام Attributeها و Methodها با **یک کاراکتر خط زیرین** (``_``) آغاز شود، این مفهوم را با خود می‌رساند که «دست نزنید مگر داخل همان کلاس یا subclassهای آن». رعایت این قرارداد معادل سطح دسترسی **protected** در Java و ++C می‌باشد.
42+
43+
.. tip::
44+
45+
زبان برنامه‌نویسی پایتون از تکنیک «دستکاری نام» یا **name mangling** [`ویکی‌پدیا <https://en.wikipedia.org/wiki/Name_mangling>`__] پشتیبانی می‌کند. به کمک این تکنیک و با قراردادن **دو کاراکتر خط زیرین** (``__``) در ابتدای نام هر یک از اجزای داخلی یک کلاس، می‌توان معادل سطح دسترسی **private** در Java و ++C را پیاده‌سازی کرد [`اسناد پایتون <https://docs.python.org/3/tutorial/classes.html#private-variables>`__].
46+
47+
به نمونه کد زیر توجه نمایید:
48+
49+
.. code-block:: python
50+
:linenos:
51+
52+
class Student:
53+
54+
def __init__(self, name, score=0):
55+
self.name = name
56+
self.__score = score
57+
58+
def display(self):
59+
print('name:', self.name)
60+
print('score:', self.__score)
61+
62+
63+
student = Student('Saeid', 70)
64+
65+
#accessing using method
66+
student.display()
67+
68+
#accessing directly from outside
69+
print('-' * 10, 'Accessing directly from outside')
70+
print('name:', student.name)
71+
print('score:', student.__score)
72+
73+
74+
::
75+
76+
name: Saeid
77+
score: 70
78+
---------- Accessing directly from outside
79+
name: Saeid
80+
Traceback (most recent call last):
81+
File "sample.py", line 20, in <module>
82+
print('score:', student.__score)
83+
AttributeError: 'Student' object has no attribute '__score'
84+
85+
داده‌های private را در خارج از کلاس نمی‌توان مستقیم مورد دستیابی قرار داد و همانطور که از نمونه کد بالا مشاهده می‌شود دستیابی چنین عناصری در پایتون باعث بروز AttributeError می‌شود. اما گفته شد که پایتون Encapsulation قوی ندارد، چه اتفاقی افتاد؟
86+
87+
مفسر پایتون بر اساس تکنیک **name mangling**، نام تمام عناصری که تنها با **دو کاراکتر خط زیرین** شروع شده باشند (مانند ``spam__``) را به صورت زیر با افزودن نام کلاس به ابتدای آن تغییر می‌دهد::
88+
89+
_classname__spam
90+
91+
بنابراین اگر برنامه‌نویسی به دنبال دستیابی نام موجود (``spam__``) در کلاس باشد، چیزی پیدا نخواهد کرد. با این کار پایتون به صورت ضعیف امکان دور نگه‌داشتن برخی از عناصر را از حالت عمومی فراهم آورده است. برای مثال پیش داریم::
92+
93+
>>> dir(student)
94+
['_Student__score', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'display', 'name']
95+
96+
97+
متدهای Setter و Getter
98+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99+
100+
در برنامه‌نویسی شی گرا چنانچه بخواهیم دسترسی به داده‌ای را به شدت محدود کنیم، به آن داده سطح دسترسی private را اعمال می‌کنیم. اما گاهی می‌خواهیم تنها روند دستیابی و تغییر برخی از داده‌ها را کنترل کنیم - دسترسی مجاز است ولی چگونگی آن مهم است - در این صورت علاوه بر تنظیم سطح دسترسی private به آن عناصر متدهایی را برای تغییر (به عنوان Setter) و دستیابی (به عنوان Getter) آن‌ها نیز می‌بایست ایجاد کنیم:
101+
102+
.. code-block:: python
103+
:linenos:
104+
105+
class Student:
106+
107+
def __init__(self, name, score=0):
108+
self.name = name
109+
self.__score = score
110+
111+
def set_score(self, score):
112+
if isinstance(score, int) and 0 <= score <= 100:
113+
self.__score = score
114+
115+
def get_score(self):
116+
return self.__score
117+
118+
119+
student = Student('Saeid', 70)
120+
student.set_score(99)
121+
student.set_score('100')
122+
student.set_score(-10)
123+
print(f'{student.name}, score:', student.get_score())
124+
125+
126+
::
127+
128+
Saeid, score: 99
129+
35130

36131

37132

0 commit comments

Comments
 (0)