<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های محمد محمودی</title>
        <link>https://virgool.io/feed/@mohammed1994159</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 08:09:58</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1296551/avatar/BRHT7k.jpeg?height=120&amp;width=120</url>
            <title>محمد محمودی</title>
            <link>https://virgool.io/@mohammed1994159</link>
        </image>

                    <item>
                <title>نگاهی به property در پایتون</title>
                <link>https://virgool.io/@mohammed1994159/%D8%A8%D8%A7-property-%D8%AF%D8%B1-%D9%BE%D8%A7%DB%8C%D8%AA%D9%88%D9%86-attribute%D9%87%D8%A7%DB%8C-%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%B4%D8%AF%D9%87-%D8%A8%D9%87-%DA%A9%D9%84%D8%A7%D8%B3-%D9%87%D8%A7%DB%8C-%D8%AE%D9%88%D8%AF-%D8%A7%D8%B6%D8%A7%D9%81%D9%87-%DA%A9%D9%86%DB%8C%D8%AF-skq6goblaczl</link>
                <description>با property در پایتون attributeهای مدیریت شده به کلاس های خود اضافه کنید.با property در پایتون attributeهای مدیریت شده به کلاس های خود اضافه کنید.پیشنیاز: آشنایی با شی گرایی و دکوریتور ها در پایتونسلام دوستان امیدوارم روزهای خوبی رو سپری کنیدمیخوام درباره property در پایتون صحبت کنمبامن همراه باشید تا مروری بر اون چیزی که میخوام باهاتون صحبت کنم داشته باشیم:شما حتما با attributes ها در پایتون آشنایی دارید(نیازه که داشته باشید) یک سری ویژگی ها که میخواهیم به کلاس هامون اضافه کنیم بهش میگم attributes.در پایتون attributesها معمولا بصورت خام ذخیره میشن.حالا اگر ما بخواهیم کنترل روی attributesها داشته باشیم باید از attributesهای مدیریت شده یا همون property استفاده کنیم.خب حالا بیایید ببینیم propertyچه کمکی به ما می کنه؟      فرض کنید یک کتابخانه یا یک کلاس نوشتید که خیلیا دارن ازش استفاده میکنن  و حالا میخواین یکی از attributesها رو اصلاح کنید یا کنترل بذارید رو اون و میخواهید که کاربرانی که دارن از کلاس یا کتابخانه شما استفاده می کنن دچار مشکل نشن در این صورت بهترین راه استفاده از propertyاست.حالا ما در این آموزش میخواهیم چی یاد بگیریم:1.ساختن attributesهای مدیریت شده یا همون property در کلاس2.انجام lazy attribute evaluation  و ارائه computed attributes3.جلوگیری  استفاده از setter, getter برای اینکه پایتونی تر و تمیزتر (clean code)کد بزنیم 4.نوشتن property های read-only  ,read-write,   write-only5.ساخت کلاس ها یا کتابخانه های استوار و قابل برگشت به عقب(backward-compatible)خب دوستان یه توضیح ریز درباره backward-compatible بدم:        سازگاری به عقب --&gt;  قابلیت اجرای کد نوشته شده در نسخه های قدیمی ترخب حالا بریم سراغ اولین بحث :attributesهای مدیریت شده در کلاسزمانی که یک کلاس در زبان های شی گرا تعریف می کنیداحتمالا با یکسری از attributesهای کلاس یا نمونه یا شی مواجه خواهید شد.اگر بخواهیم بهتر بگیم وابسته به زبانی که استفاده می کنید شما با متغیر هایی که قابل دسترس از طریق نمونه و کلاس یا هردو  باشند ،مواجه خواهید شد.attributesها اغلب حالت داخلی شی یا مقادیر داخلی شی را یا نشان می دهند یا نگهداری می کنند که ما نیاز خواهیم داشت که دسترسی پیدا کنیم به انها یا تغییرشون بدیم.معمولا حداقل دو راه برای مدیریت کردن attributesها وجود داره.یا اینکه مستقیما به attributesها دسترسی پیدا کنیم و تغییر بدیم یا اینکه از متد ها استفاده کنیم.متدها توابعی هستند که درون کلاس ها نوشته میشن و رفتارها و اعمالی را ارائه می دهن که یک شی می تونه با داده ها و ویژگی های داخلی خودش انجام بده.اگر  attributeها رو در معرض استفاده کاربران قرار بدید کاربر این  attribute مستقیما در کد خود دسترسی و تغییر می ده و مشکل زمانی پیش میاد که نیاز به تغییر پیاده سازی داخلی یک  attribute دارید.حالا فرض کنید که ما یک کلاس داریم بنام دایره (Circle)  و این کلاس یک  attribute داره بنام شعاع(radius.)و کلاس شما آماده شده و دراختیار کاربرنهایی قرار دادید و اون هم داره از کد استفاده میکنه و هیچ مشکلی هم وجود نداره .آفرین!!!!حالا یکی از کاربر های مهم شما میاد و میگه که دیگه نمیخواییم شعاع رو ذخیره کنیم و میخواییم قطر را بعنوان  attribute عمومی ذخیره کنیم.حالا در این حالت حذف شعاعradius. و جایگزینی  قطرdiameter. باعث شکستن کد و کار نکردن آن میشود.خب این مشکل را ماباید با راهی بجز حذف کردن حل کنیم.زبان های برنامه نویسی مانند جاوا و C++ شما را تشویق میکنند که هیچ گاه attribute ها در معرض دسترسی کاربر قرار ندهید.در عوض شما باید متدهایی مانند getter, setter بنویسد جهت دسترسی و تغییر attribute ها.این متدها اغلب راهی برای تغییر و دسترسی attribute ها بدون تغییر در کلاسی که کابران نهایی استفاده می کنن ارائه میده.نکته:معمولا متدهای getter, setter به عنوان یک الگوی نادرست و نشانه‌ای از طراحی ضعیف شیء‌گرایی محسوب می‌شون.و دلیل اصلی هم اینکه encapsulation رو میشکنه و به شما اجازه دسترسی و تغییر  کامپوننت ها رو میده.روش Getterو Setter در پایتوناز نظر فنی کسی نمیتونه جلوی شما رو بگیره تا از getterو setter در پایتون استفاده نکنید.خب حالابیاید تاببینم چجور باید استفاده کنیم:# point.py
class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    def get_x(self):
        return self._x

    def set_x(self, value):
        self._x = value

    def get_y(self):
        return self._y

    def set_y(self, value):
        self._y = valueدر مثال بالا یک کلاس نوشتیم بنام نقطه که مختصات دکارتی نقطه رو مشخص میکنه که در این مثال  x_.وy_. دو attributeهای خصوصی (private) ماهستند.نکته:در پایتون چیزی بنام access modifiers نداریم access modifiers یعنی اصلاح کننده دسترسی مثل : private, protected, publicدر پایتون شما می تونید با گذاشتن علامت underscore یا _ قبل از نام متغیر آن متغیر رو تبدیل به متغیر خصوصی کنید یا باگذاشتن دوتا آندراسکور تبدیل به متغیر  protectedکنید. اما اینها فقط یک قرارداد است و پایتون برنامه نویس رو به زور وادار نمیکنه که نتونه  استفاده کنه  از متغیر های private, protected و با dot notation  امکان دسترسی و استفاده رو به برنامه نویس میده برای مثال obj._attr یک نمونه از دسترسی می باشد.برای دسترسی و تغییر به x و y میتونیم از getter , setter استفاده کنیم .خب حالا میخوایم با استفاده از شل پایتون کدی که نوشتیم رو تست کنیم:&gt;&gt;&gt; from point import Point

&gt;&gt;&gt; point = Point(12, 5)
&gt;&gt;&gt; point.get_x()
12
&gt;&gt;&gt; point.get_y()
5

&gt;&gt;&gt; point.set_x(42)
&gt;&gt;&gt; point.get_x()
42

&gt;&gt;&gt; # ویژگی های غیر عمومی هنوز در دسترس هستند
&gt;&gt;&gt; point._x
42
&gt;&gt;&gt; point._y
5روش پایتونیکبا اینکه مثالی که در قبل دیدید از سبک(سینتکس) کدنویسی پایتون استفاده می کند اما پایتونیک نیست.خب حالا میخواییم کدمون رو بازنویسی کنیم طوریکه متدهای getter, setter هیچ پردازشی در برنامه ندارند.&gt;&gt;&gt; class Point:
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...

&gt;&gt;&gt; point = Point(12, 5)
&gt;&gt;&gt; point.x
12
&gt;&gt;&gt; point.y
5

&gt;&gt;&gt; point.x = 42
&gt;&gt;&gt; point.x
42این کد یک اصل اساسی را آشکار می‌کند. ارائه attributeها به کاربران نهایی در پایتون طبیعی و رایج است. شما نیازی ندارید که همیشه کلاس‌های خود را با متدهای getter , setter پر کنید که خیلی خوب به نظر می‌رسد!خب حالا باید چجوری تغییرات مورد نظرمون که ممکنه کلاس هایی که کابران نهایی استفاده میکنند رو هم درگیر میکنه اعمال کنیم؟برخلاف جاوا و سی‌پلاس‌پلاس، پایتون ابزارهای مفیدی ارائه می‌ده که به شما امکان می‌ده تا پیاده‌سازی اصلی ویژگی‌های خود را بدون تغییرکلاس های عمومی‌تون تغییر بدید.محبوب ترین رویکردی که پایتون ارائه میده اینه که بیایم attributeهامون رو به properties تبدیل کنیم.نکته :یکی دیگه از راه ها استفاده از discriptorsها هستش که ما در این اموزش تمرکزمون روی property هستش.خب ببینید دوستان propertyها یک عملکرد میانی  بین attributeهای ساده و متدها رو نشون میدن.درواقع بشما این اجازه رومیدن که یک سری متد هارو بسازید که رفتارشون شبیه attriubuteهاست.با استفاده از property می‌توانید نحوه محاسبه attributeهای مورد نظر خود را هر زمان که نیاز دارید تغییر دهیدبعنوان مثال ما میتوانیم x. و y. تبدیل به propertyکنیم.همچنین، یک متد پایه وجود خواهد داشت که مقادیر .x و .y را نگه می‌داره و به شما امکان می‌ده تا پیاده‌سازی داخلی آن‌ها را تغییر بدید و عملیاتی را بر روی آن‌ها انجام بدید درست  قبل از اینکه کاربران شما به آن‌ها دسترسی پیدا کنن و آن‌ها را تغییر بدهن.نکته: propertyها محدود به پایتون نیستند. زبان‌هایی مانند جاوااسکریپت، C#، کاتلین و... همچنین ابزارها و تکنیک‌هایی را برای ایجاد propertyها به عنوان اعضای کلاس فراهم می‌کنند.اصلی‌ترین مزیت propertyهای پایتون اینه که به شما اجازه می‌ده تا attributeهای خود را به عنوان بخش عمومی و در دسترس کلاس نشان بدید. اگر زمانی نیاز به تغییر اساسی در پیاده سازی داشتید میتونید با تبدیل attributeها به property  بدون دردسر زیاد تغییرات رو اعمال کنید...شروع کار با propertyهای پایتونتا اینجا فهمیدیم که property یک روش پایتونیک برای جلوگیری از نوشتن getter و setter در کد است.تابع  ()property این امکان رو میده که attributeهای کلاس رو تبدیل به propertyکنیم.از ان جایی که property یک تابع داخلی پایتون است نیاز به ایمپورت ندارد و بخاطر پیاده سازی شدن با زبان C بهینه سازی شده است.نکته:از انجایی که property یک تابع داخلی پایتون است اما propertyیک کلاس است که بعنوان تابع کار می کند.با استفاده از property، می‌توانید متدهای getter , setter را به attributeهای کلاس اضافه کنید. به این ترتیب، می‌توانید پیاده‌سازی داخلی برای آن attribute را مدیریت کنید بدون اینکه متدهای getter , setterرا در کلاس خود بنمایش بگذارید. همچنین، می‌توانید یک روش برای مدیریت حذف attributeها مشخص کنید و برای attributeهای خود یک مستند متناسب فراهم کنید.بیایید یه نگاهی به نحوه نگارش تابع property بندازیم:property(fget=None, fset=None, fdel=None, doc=None)آرگومان fget: تابعی است که یک مقدار از attribute رو برمیگرداندآرگومان fset:تابعی که یه مقدار در attributeموردنظر ست میکند.آرگومان fdel:تابعی که مقدار ست شده را حذف میکند.آرگومان doc:داک‌استرینگی (docstring)که برای attribute موردنظر نیاز هست نوشته شود.خب اگه شما بخواهید به مقدار property دسترسی پیدا کنید obj.attr پایتون بطور اتوماتیک تابع fgetرو صدا میزنه و اگر بخواهید مقداری رو ست کنید obj.attr = value  پایتون بطور اتوماتیک fsetرو صدا میزنه. و درنهایت برای حذف del obj.attr تابع fdel رو صدا میزنه.تونید از آرگومان doc برای نوشتن یک مستند مناسب برای propertyهای خود استفاده کنید. خودتون و همکاران برنامه‌نویس تون می‌تونید این مستند را با استفاده از help پایتون بخونید. همچنین، آرگومان doc وقتی که با ویرایشگرهای کد و IDEها که از دسترسی به مستندهای متنی پشتیبانی می‌کنن کار می‌کنی، مفیده.شما می تونید property با دو روش استفاده کنید :استفاده از دکوریتور استفاده از تابعدراین اموزش هر دو رو اموزش میدیم اما روش دکوریتور محبوب تر است.ساخت attribute با propertyخب در مثال زیر میخوایم یک attribute با propertyبسازیم:# circle.py

class Circle:
    def __init__(self, radius):
        self._radius = radius

    def _get_radius(self):
        print(&amp;quotGet radius&amp;quot)
        return self._radius

    def _set_radius(self, value):
        print(&amp;quotSet radius&amp;quot)
        self._radius = value

    def _del_radius(self):
        print(&amp;quotDelete radius&amp;quot)
        del self._radius

    radius = property(
        fget=_get_radius,
        fset=_set_radius,
        fdel=_del_radius,
        doc=&amp;quotThe radius property.&amp;quot
    )در قطعه کد بالا متد سازنده(__init__) کلاس شعاع(radius) رو بعنوان ارگومان خصوصی (radius_.)جهت ذخیره دریافت می کند.بعد سه تابع خصوصی داریم :تابع get_radius_ که مقدار radius_.  برمی گردونه.تابع set_radius_ که مقدار  radius_.  رو ست میکنه تابع del_radius_ که attribute آبجکت رو حذف میکنهوقتی این سه متد را در دسترس داشته باشید، یک attribute کلاس به نام .radius برای ذخیره شیءproperty ایجاد می‌کنید.حالا برای ساخت property  باید این سه متد رو بعنوان ارگومان به تابع  propertyبدیم.خب حالا بیاید کدی که نوشتیم رو تست کنیم:&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)

&gt;&gt;&gt; circle.radius
Get radius
42.0

&gt;&gt;&gt; circle.radius = 100.0
Set radius
&gt;&gt;&gt; circle.radius
Get radius
100.0

&gt;&gt;&gt; del circle.radius
Delete radius
&gt;&gt;&gt; circle.radius
Get radius
Traceback (most recent call last):
    ...
AttributeError: &#039;Circle&#039; object has no attribute &#039;_radius&#039;

&gt;&gt;&gt; help(circle)
Help on Circle in module __main__ object:

class Circle(builtins.object)
    ...
 |  radius
 |      The radius property.خب وقتی help گرفتیم دیدیم که property  مربوط به radius اومده و attribute خصوصی کلاس رو پنهان کرده .پس porpertyها attributeهای کلاس هستند که attribute های شی رو مدیریت می کنند.&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; Circle.radius.fget
&lt;function Circle._get_radius at 0x7fba7e1d7d30&gt;

&gt;&gt;&gt; Circle.radius.fset
&lt;function Circle._set_radius at 0x7fba7e1d78b0&gt;

&gt;&gt;&gt; Circle.radius.fdel
&lt;function Circle._del_radius at 0x7fba7e1d7040&gt;

&gt;&gt;&gt; dir(Circle.radius)
[..., &#039;__get__&#039;, ..., &#039;__set__&#039;, ...]خب ببینید دوستان propertyها  override می کنن descriptorsها رو.اگر ()dir استفاده کنیم برای دیدن عضو ها ، متدهای  __set__ و  __get__ دیده خواهند شد.زمانی که ما متد setter برای property مورد نظر مشخص نکرده باشیم بطور پیش فرض __set__ فراخوانی میشود که در این صورت AttributeError  دریافت خواهیم کرد.چون هیچ راهی برای ست کردن پیدا نمیکنه.استفاده از property بعنوان دکوریتوردکوراتورها در پایتون در همه‌جا هستن. آن‌ها توابعی هستن که یک تابع دیگر را به عنوان آرگومان می‌پذیرن و یک تابع جدید با قابلیت‌های اضافی برمی‌گردانن. با استفاده از یک دکوراتور، می‌توانید عملیات‌های پیش و پس از پردازش را به یک تابع موجود اضافه کنید.زمانی که property در نسخه 2.2 پایتون معرفی شده هنوز چیزی بنام دکوریتور در پایتون در دسترس نبود. بنابراین از روش قبلی که نوشتن   تابع property بود استفاده می شد.خب حالا میخواهیم مثال دایره رو با استفاده از دکوریتور property بازنویسی کنیم:# circle.py

 class Circle:
    def __init__(self, radius):
        self._radius = radius

    @property
    def radius(self):
        &amp;quot&amp;quot&amp;quotThe radius property.&amp;quot&amp;quot&amp;quot
        print(&amp;quotGet radius&amp;quot)
        return self._radius

    @radius.setter
    def radius(self, value):
        print(&amp;quotSet radius&amp;quot)
        self._radius = value

    @radius.deleter
    def radius(self):
        print(&amp;quotDelete radius&amp;quot)
        del self._radiusاین کد بسیار زیباتر از روشی است که درآن متد های getter, setterرا می نویسیم.حالا کلاس Circle پایتونی تر و اصول کدنویسی تمیز در ان رعایت شده است.دیگه نیاز نیست از متد هایی با نام های ()get_radius(), ._set_radius(), ._del_radius_.استفاده کنیم.اولین متدی مینویسیم باید نام پابلیک (عمومی)  همان attribtueباشد که قراره تبدیل به propertyبشه این متد باید منطق getterرا پیاده سازی کنه.دومین و سومین متد هم باید هم نام متد اول باشد با تفاوت هایی که در دکوریتور های انها دیده می شود.&gt;&gt;&gt; dir(Circle.radius)
[..., &#039;deleter&#039;, ..., &#039;getter&#039;, &#039;setter&#039;]در کنار fget, .fset, .fdel. و سایر attributeها و متدها propertyاین سه متد (()deleter(), .getter(), and .setter.)رو میسازه و هر کدوم یک  property جدید برمیگردونه(return میکنه)حالا وقتی شما دومین متد ()radius. دکوریت میکنید با radius.setter@درواقع دارید یک ویژگی جدید می سازید و به radius.که در خط 8 کد بالا نوشتیم اضافه می کنید. حالا این propertyیا همون ویژگی که ایجاد کردیم مجموعه ای از متد ها رو داره یکیش خط 8 و یکیش خط 14.مکانیزم کارکردradius.deleter@  این به شکل بالا می باشد.خب دوستان بیاید تا کدی که در بالا با استفاده از دکوریتور نوشتیم تست کنیم:&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)

&gt;&gt;&gt; circle.radius
Get radius
42.0

&gt;&gt;&gt; circle.radius = 100.0
Set radius
&gt;&gt;&gt; circle.radius
Get radius
100.0

&gt;&gt;&gt; del circle.radius
Delete radius
&gt;&gt;&gt; circle.radius
Get radius
Traceback (most recent call last):
    ...
AttributeError: &#039;Circle&#039; object has no attribute &#039;_radius&#039;

&gt;&gt;&gt; help(circle)
Help on Circle in module __main__ object:

class Circle(builtins.object)
    ...
 |  radius
 |      The radius property.با توجه به تستی که در بالا انجام دادیم دیگه نیاز به پرانتز برای فراخوانیradius. شبیه متدها نداریم و میتوانیم شبیه دسترسی به attribute ها که داشتیم انها فراخوانی کنیم که این اصلی ترین ویژگی استفاده از propertyاست.خب دوستان یک خلاصه ای از چیزهایی که گفتیم رو مرور کنیم:دکوریتورproperty@ رو باید روی متد getter بذاریممستندات یا همون docstring حتما باید در متد getterنوشته بشهپمتد های setter , deleterباید دکوریت بشن با نام متدی که برای getter در نظرگرفتیم بعلاوه setter. و getter.خب حالا یه نکته :دوستان باید اجتناب کنیم از تبدیلattribute به property زمانی که نیاز نداریم هیچ گونه پردازش اضافی رو attribute داشته باشیم.استفاده از property در جای نامناسب میتون کد شما رو:بی جهت شلوغ کنهبرنامه نویس های دیگه رو گیج کنهکند تر کنهمگر اینکه نیاز داشته باشید چیزی بجز attribute خالی داشته باشید،property ننویسید.property بیجا باعث هدررفتن زمان cpuو زمان خودتون میشه.خب حالا میخواهیم attributeهای read-only بنویسیمبچه ها شاید ابتدایی ترین استفاده از property ساختن attributeهای read-only باشه.خب حالا فرض کنید شما میخواهید یک کلاس غیر قابل تغییر (immutable) بنام نقطه(Point) داشته باشید که به کاربر اجازه تغییر مختصات رو نده برای این کار کلاسمون رو به شکل زیر  مینویسیم:# point.py

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @property
    def y(self):
        return self._yدر اینجا ما اومدیم دوتا ورودی از کاربر گرفتیم و بعنوان attributeهای x_.و  y_. ذخیره کردیم و همانطور که قبلا یادگرفتیم استفاده از underscore این مفهوم به سایر دولوپر ها میگه که این attributeها غیرعمومی(non-public) هستند و برای دسترسی به انها نباید از dot notiation مانند point._x استفاده کرد.و درنهایت ماباید با استفاده property@ یک متد getterبرای دسترسی به آن بنویسیم.&gt;&gt;&gt; from point import Point

&gt;&gt;&gt; point = Point(12, 5)

&gt;&gt;&gt; # Read coordinates
&gt;&gt;&gt; point.x
12
&gt;&gt;&gt; point.y
5

&gt;&gt;&gt; # Write coordinates
&gt;&gt;&gt; point.x = 42
Traceback (most recent call last):
    ...
AttributeError: can&#039;t set attributeخب دوستان ببیند getterما بدرستی کار میکنه و موقع ست کردن attribtue به خطا  خوردیم چرا؟قبلا کمی درباره discriptorها صبحت کردیم رفتارpropertyها بسیار متکی به descriptor هست که این property رو میسازه و دراین جا پیش فرض دیسکریپتور ()__set__.خطای AttributeError است  تازمانی که بیایم و setter رو تعریف کنیم.حالا کد بالا رو یه کم بهبود می بخشیم:# point.py

class WriteCoordinateError(Exception):
    pass

class Point:
    def __init__(self, x, y):
        self._x = x
        self._y = y

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        raise WriteCoordinateError(&amp;quotx coordinate is read-only&amp;quot)

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        raise WriteCoordinateError(&amp;quoty coordinate is read-only&amp;quot)درمثال بالا اومدیم و exception رو شخصی سازی کردیم .خب حالا میخواهیم attributeهای read-write بسازیم:شما میتونید با استفاده از property بیاید و attributeهایی که قابلیت خوندن و نوشتن دارند بنویسید.حالا ما میخواییم تو این تمرین getter مناسب برای read و setter  مناسب برای write بنویسیم.خب حالا فرض کنید برای کلاس دایره (Circle) که قبلا نوشتید یک attribute قُطر(diameter.) هم اضافه کنید.گرفتن قطر بعنوان ورودی در متد سازنده(__init__) ضروری نیست و با داشتن یکی میتونیم اون یکی رو محاسبه کنیم.# circle.py

import math

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._radius = float(value)

    @property
    def diameter(self):
        return self.radius * 2

    @diameter.setter
    def diameter(self, value):
        self.radius = value / 2خب تو مثال بالا ما اومدیم یک کلاس دایره نوشتیم که radius. در آن قابلیت  read-write دارد.اگر برگردید به عقب و کلاس Circle که نوشته بودیم رو نگاه کنید میبینید که با این کلاس جدید یه تفاوت ریز داره.بریم که توضیح بدیم داستان از چه قراره...اگر دقت کنید یک نکته ظریف اینجا وجود داره و اونم اینه که ما مثل قبل مقداری که هنگام ساختن شی(آبجکت) ارسال میشه به خود property شعاع نسبت میدیم در صورتی که در مثال های قبل در یک متغیر خصوصی ذخیره میکردیم.خب علت این کار چیه؟ما برای اینکه موقع ساخت آبجکت هم مقدار ارسالی از کاربر رو تبدیل به float کنیم نیاز داریم که متد setterهنگام ساخت آبجکت هم فراخوانی بشه بخاطر همین میاییم مقدار ارسالی کاربر مستقیما بخود property نسبت میدیم که کنترل ها و محاسبات لازم در موقع ساخت ابجکت هم اعمال بشه.و در نهایت برای محاسبه  قطر هم از خوده property شعاع استفاده می کنیم.حالا بیایید کد رو تست کنیم:&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42)
&gt;&gt;&gt; circle.radius
42.0

&gt;&gt;&gt; circle.diameter
84.0

&gt;&gt;&gt; circle.diameter = 100
&gt;&gt;&gt; circle.diameter
100.0

&gt;&gt;&gt; circle.radius
50.0خب حالا میخواییم attributeهای فقط نوشتنی(Write-Only) بنویسیم:شما همچنین می‌توانید attributeهای فقط‌نوشتنی (write-only) را با تنظیماتی در متد (getter) در propertyهای خود پیاده‌سازی کنید. به عنوان مثال، می‌توانید متد (getter) را به گونه‌ای تغییر دهید که هر زمان کاربر خواست به مقدار attribute دسترسی داشته باشد، یک استثناء ایجاد شود.خب مثال زیر یک کد برای هندل کردن پسورد است:# users.py

import hashlib
import os

class User:
    def __init__(self, name, password):
        self.name = name
        self.password = password

    @property
    def password(self):
        raise AttributeError(&amp;quotPassword is write-only&amp;quot)

    @password.setter
    def password(self, plaintext):
        salt = os.urandom(32)
        self._hashed_password = hashlib.pbkdf2_hmac(
            &amp;quotsha256&amp;quot, plaintext.encode(&amp;quotutf-8&amp;quot), salt, 100_000
        )در کد بالا ما میاییم دوتا مقدار username , password رو در متد سازنده(__init__) از کاربر میگیریم.نام کاربری رو بصورت خام ذخیره میکنیم ولی پسورد رو با استفاده از الگوریتم خاصی هش میکنیم و بصورت خام ذخیره نمیکنیم و اجازه دیدن پسورد رو هم به کاربر نمیدیم.و هرزمان که کاربر خواست پسورد رو ببینه  AttributeError بهش نشون داده میشه.حالا بیاید تست کنیم:&gt;&gt;&gt; from users import User

&gt;&gt;&gt; Mohammad = User(&amp;quotMohammad&amp;quot, &amp;quotsecret&amp;quot)

&gt;&gt;&gt; Mohammad._hashed_password
b&#039;b\xc7^ai\x9f3\xd2g ... \x89^-\x92\xbe\xe6&#039;

&gt;&gt;&gt; Mohammad.password
Traceback (most recent call last):
    ...
AttributeError: Password is write-only

&gt;&gt;&gt; Mohammad.password = &amp;quotsupersecret&amp;quot
&gt;&gt;&gt; Mohammad._hashed_password
b&#039;\xe9l$\x9f\xaf\x9d ... b\xe8\xc8\xfcaU\r_&#039;در این مثال ما میاییم و یک instanceیا شی از کلاس بنام Mohammad میسازیم و پسورد رو هم موقع ساختن  شی  میدیم.حالا موقعی که ما میخواییم به hashed_password_. دسترسی پیدا کنیم مشکلی نیست و پسورد رو بصورت هش نمایش میده اما اگر بخواییم بدونیم که پسورد اصلی ذخیره شده چیه به ما خطا Password is write-only میده.و همین رفتار بعد از  ست کردن پسورد جدید اتفاق می افتد.توضیح کوتاه:os.urandom  یک استرینگ 32 بیتی تولید میکنه.که این رو بعنوان نمک درنظر میگیریم.با استفاده از کتابخانه hashlib  و الگوریتم SHA-256 و نمکی که تولید کردیم پسورد ما به اندازه 100000 بار  با نمک ترکیب میشه و یک هش جدید تولید میشه.اعمال ویژگی ()property در پایتوندوستان تا اینجا بیشتر مواردی که مربوط به propertyبود رو یاد گرفتید دو روش استفاده از دکوریتور و تابع رو یادگرفتید با تفاوت هاش.حالا میخواییم برای درک بیشتر مثال بیشتری حل کنیم ...اعتبار سنجی ورودی هایکی از رایج ترین استفاده های property ،برای اعتبار سنجی داده قبل از ذخیره شدن یا حتی قبول کردن داده بعنوان داده ایمن است.اعتبارسنجی داده یک نیاز متداول در کدهایی است که ورودی‌ها را از کاربران یا منابع اطلاعاتی دیگری دریافت می کنند که ممکنه  غیرقابل اعتمادباشند.ویژگی property در پایتون ابزاری سریع و قابل اعتماد برای رسیدگی به اعتبارسنجی داده‌های ورودی فراهم می‌کند.برای مثال برگردید به کلاس نقطه(Point) که نوشتیم در این کلاسی که نوشته شده کاربر آزاده که هر نوع داده ای که میخواد وارد کنه خب حالا میتونیم این اعتبار سنجی رو انجام بدیم تا کاربر موظف باشه حتما داده عددی وارد کنه.# point.py

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def x(self):
        return self._x

    @x.setter
    def x(self, value):
        try:
            self._x = float(value)
            print(&amp;quotValidated!&amp;quot)
        except ValueError:
            raise ValueError(&#039;&amp;quotx&amp;quot must be a number&#039;) from None

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, value):
        try:
            self._y = float(value)
            print(&amp;quotValidated!&amp;quot)
        except ValueError:
            raise ValueError(&#039;&amp;quoty&amp;quot must be a number&#039;) from Noneخب بیایید درباره متد setter که برای x. نوشتیم صحبت کنیم:با خاصیت try ..except سعی کردیم که بگیم تلاشتو بکن که x رو تبدیل به floatکنی و بعد ذخیره کنی اما اگر نتونستی یه استثناValueError برگردون.برای y هم به همین شکل...در مثال بالا ما اومدیم از raise … from None  استفاده کردیم چرا؟ این سینتکس نوشتاری میاد جزئیات مربوط به استثنایی که رخ داده رو پنهان میکنه.از دیدگاه کاربران نهایی، این جزئیات ممکنه گیج‌کننده باشه و کلاس شما را ناقص به نظر بیاره.خب حالا کلاسی که نوشتیم چجور کار میکنه؟&gt;&gt;&gt; from point import Point

&gt;&gt;&gt; point = Point(12, 5)
Validated!
Validated!
&gt;&gt;&gt; point.x
12.0
&gt;&gt;&gt; point.y
5.0

&gt;&gt;&gt; point.x = 42
Validated!
&gt;&gt;&gt; point.x
42.0

&gt;&gt;&gt; point.y = 100.0
Validated!
&gt;&gt;&gt; point.y
100.0

&gt;&gt;&gt; point.x = &amp;quotone&amp;quot
Traceback (most recent call last):
     ...
ValueError: &amp;quotx&amp;quot must be a number

&gt;&gt;&gt; point.y = &amp;quot1o&amp;quot
Traceback (most recent call last):
    ...
ValueError: &amp;quoty&amp;quot must be a numberتست کد قبل که در  بالا امده به نظر میاد کامل گویا باشه نیاز به توضیح نداشته باشه.اما کد قبلی که نوشتیم یه اشکال ریز داره و اونم اینه که کد تکراری داریم و این با اصل DRY در پایتون مغایرت دارد .کد قبل رو بصورت زیر بهبود میدیم اما برای درک کد زیر نیاز هست درباره discriptorها در پایتون بدونید که خودش مبحث جدایی و نمی گنجه که در این اموزش توضیح بدم و فقط کد رو میزارم ...# point.py

class Coordinate:
    def __set_name__(self, owner, name):
        self._name = name

    def __get__(self, instance, owner):
        return instance.__dict__[self._name]

    def __set__(self, instance, value):
        try:
            instance.__dict__[self._name] = float(value)
            print(&amp;quotValidated!&amp;quot)
        except ValueError:
            raise ValueError(f&#039;&amp;quot{self._name}&amp;quot must be a number&#039;) from None

class Point:
    x = Coordinate()
    y = Coordinate()

    def __init__(self, x, y):
        self.x = x
        self.y = y
خب میریم سراغ کاربرد بعدی ...2.بریم سراغ attributeهای محاسبه شدهاگر نیاز به یک attribute دارید که موقع دسترسی به آن بصورت پویا ساخته (محاسبه )بشه propertyمیتونه کمکتون کنه.به این نوع از attributeها معمولا میگن computed attributes.این نوع attributerها اماده(eager) بنظر میرسند درصورتی خیلی تنبل(lazy)هستند تا موقعی که صدا زده نشن هیچ محاسبه ای انجام نمیشه .دلیل اصلی برای ایجاد  (eager attributes) بهینه‌سازی هزینه محاسباتی است زمانی که به طور مکرر به attribueها دسترسی می‌یابید. از سوی دیگر، اگر به اندازه کمی از یک attribute خاص استفاده می‌کنید، در این صورت یک (lazy property) می‌تواند محاسبات آن را تا زمان لزوم به تأخیر بیندازد، که می‌تواند کارایی برنامه‌های شما را افزایش دهد.به کلاس مستطیل زیر نگاه کنید:class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height

    @property
    def area(self):
        return self.width * self.heightدر کد بالا مساحت مستطیل تازمانی که صدا زده نشه محاسبه نمیشه.یکی از کاربردهای دیگه auto-formatted هستش که فرمت خروجی رو متناسب میکنه به مثال زیر توجه کنید:class Product:
    def __init__(self, name, price):
        self._name = name
        self._price = float(price)

    @property
    def price(self):
        return f&amp;quot${self._price:,.2f}&amp;quotبعنوان آخرین مثال می خواهیم در کلاس  Point علاوه بر مختصات دکارتی ،مختصات قطبی هم داشته باشیم.سیستم مختصات قطبی، هر نقطه را با استفاده از فاصله تا مبدأ و زاویه با محور افقی مختصات نشان می‌دهد.# point.py

import math

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    @property
    def distance(self):
        return round(math.dist((0, 0), (self.x, self.y)))

    @property
    def angle(self):
        return round(math.degrees(math.atan(self.y / self.x)), 1)

    def as_cartesian(self):
        return self.x, self.y

    def as_polar(self):
        return self.distance, self.angleخب بیاید کد بالا رو تست کنیم:&gt;&gt;&gt; from point import Point

&gt;&gt;&gt; point = Point(12, 5)

&gt;&gt;&gt; point.x
12
&gt;&gt;&gt; point.y
5

&gt;&gt;&gt; point.distance
13
&gt;&gt;&gt; point.angle
22.6

&gt;&gt;&gt; point.as_cartesian()
(12, 5)
&gt;&gt;&gt; point.as_polar()
(13, 22.6)زمانی که قراره ما یک attribute محاسبه شده یا تنبل داشته باشیم propertyیک ابزار بسیار مفید است.پس با این حال اگر یک attribute داشته باشید که بسیار استفاده میشه محاسبه آن هر لحظه بسیار هزینه بر و بی فایده است.بهترین استراتژی این است که بعد از انجام محاسبات آنرا در حافظه cache نهگداری کنیم .ذخیره (caching)  attributeهای محاسبه شدهگاهی اوقات شما یه سری attribute های محاسبه شده داری که خیلی ازشون استفاده میکنی.تکرار مدام همان محاسبات ممکن است غیر ضروری و پر هزینه باشد.برای حل این مشکل بهتر یک attribute اختصاصی و خصوصی(private)برای ذخیره مقدار محاسبه شده داشته باشی برای استفاده های مجدد .برای جلوگیری از رفتار غیرمنتظره ،به تغییر پذیری داده ورودی فکر کرده باشید.اگر شما یک property  ساختید که مقدار محاسبه شده رو از یک داده ثابت ورودی محاسبه میکنه عملا خروجی کد شما تغییر نخواهد کرد.مثال زیر مقدار را فقط یکبار محاسبه میکند:# circle.py

from time import sleep

class Circle:
    def __init__(self, radius):
        self.radius = radius
        self._diameter = None

    @property
    def diameter(self):
        if self._diameter is None:
            sleep(0.5)  # Simulate a costly computation
            self._diameter = self.radius * 2
        return self._diameterکد بالا یک اشکال دارد و اون هم اینه که در مرحله اول diameter.به درستی محاسبه میکنه و تو این کد ما یه کم تاخیر شبیه سازی کردیم با sleep.اما اگربیاییم و مقدار radius. را تغییر دهیم مقدارdiameter. تغییر نخواهد کرد.&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)
&gt;&gt;&gt; circle.radius
42.0

&gt;&gt;&gt; circle.diameter  # با تاخیر
84.0
&gt;&gt;&gt; circle.diameter  # بدون تاخیر
84.0

&gt;&gt;&gt; circle.radius = 100.0
&gt;&gt;&gt; circle.diameter  # قطر نادرست
84.0کد بالا گویای همه چیز است حالا میخواهیم کد رو جوری تغییر دهیم که در صورت تغییر radius. مقدار diameter.دوباره محاسبه گردد.# circle.py

from time import sleep

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    def radius(self):
        return self._radius

    @radius.setter
    def radius(self, value):
        self._diameter = None
        self._radius = value

    @property
    def diameter(self):
        if self._diameter is None:
            sleep(0.5)  # Simulate a costly computation
            self._diameter = self._radius * 2
        return self._diameterخب چه تغییراتی باعث درست کارکردن کد ما شد؟ما میاییم  در setter مربوط به radius. مقدار diameter. ریست میکنیم  به None هرزمانی که مقدار radiusتغییر کند.با همین آپدیت کردن کوچک مقدار diameter. دوباره محاسبه میگردد.&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)

&gt;&gt;&gt; circle.radius
42.0
&gt;&gt;&gt; circle.diameter  # With delay
84.0
&gt;&gt;&gt; circle.diameter  # Without delay
84.0

&gt;&gt;&gt; circle.radius = 100.0
&gt;&gt;&gt; circle.diameter  # With delay
200.0
&gt;&gt;&gt; circle.diameter  # Without delay
200.0حالا کلاس Circleدیگه به درستی کار میکند.خب یه گزینه دیگه برای cacheکردن attribute داریم خب بنظرتون چیه؟استفاده از functools.cached_property از کتابخانه استاندارد پایتون.این تابع بصورت دکوریتور رو متد کار میکنه و بشما اجازه میده که یک متد رو تبدیل به  cached property کنید.propertyفقط یک بار مقدار خود را محاسبه می‌کند و آن را به عنوان یک attribute عادی در طول عمر شی ذخیره می‌کند.# circle.py

from functools import cached_property
from time import sleep

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @cached_property
    def diameter(self):
        sleep(0.5)  # Simulate a costly computation
        return self.radius * 2دراینجاdiameter. برای اولین بار که درخواست دسترسی بهش میشه محاسبه و ذخیره میشه .اما این پیاده سازی فقط برای زمانی جواب میده که مقدار ورودی ما تغییر نمیکنه.&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)
&gt;&gt;&gt; circle.diameter  # With delay
84.0
&gt;&gt;&gt; circle.diameter  # Without delay
84.0

&gt;&gt;&gt; circle.radius = 100
&gt;&gt;&gt; circle.diameter  # Wrong diameter
84.0

&gt;&gt;&gt; # Allow direct assignment
&gt;&gt;&gt; circle.diameter = 200
&gt;&gt;&gt; circle.diameter  # Cached value
200زمانی که شما به diameter. دسترسی پیدا می کنید،مقدار محاسبه شده را دریافت می کنید.بعداز این مقدار دیگه ثابت می مونه.با این حال برخلاف propertyدرcached_property  اجازه ست کردن مستقیم رو همانطور که در کد بالا میبینیم میده مگر اینکه setterمتناسب رو نوشته باشیم.خب حالا اگر میخوایید یک cached property بسازید که درمثال بالا اجازه تغییر مستقیم diameter. نده باید کدتون رو به شکل زیر اصلاح کنید:# circle.py

from functools import cache
from time import sleep

class Circle:
    def __init__(self, radius):
        self.radius = radius

    @property
    @cache
    def diameter(self):
        sleep(0.5) # Simulate a costly computation
        return self.radius * 2ترکیب دو دکوریتور  property@وcache@یکcached property  میسازه که اجازه تغییر نمیده.&gt;&gt;&gt; from circle import Circle

&gt;&gt;&gt; circle = Circle(42.0)

&gt;&gt;&gt; circle.diameter  # With delay
84.0
&gt;&gt;&gt; circle.diameter  # Without delay
84.0

&gt;&gt;&gt; circle.radius = 100
&gt;&gt;&gt; circle.diameter
84.0

&gt;&gt;&gt; circle.diameter = 200
Traceback (most recent call last):
    ...
AttributeError: can&#039;t set attributeدر کد بالا مشخصه که اگر مابخواهیم بصورت مستقیم مقدار دهیم کنیم AttributeError میگیریم.مدیریت کردن attributeمربوط به Deletionشما میتونید یکسری propertyهای بسازید که عملکرد deleting رو پیاده سازی کنه.ممکنه خیلی کم پیش بیاد که برای این کار از property استفاده کنید.اما داشتن یک راه برای دیلیت کردن ممکنه در برخی جاها مفید باشه.فرض کنید که شما یک نوع داده درختی(tree) پیاده سازی کردید.درخت یک نوع داده ای است که داده ها رو بصورت سلسله مراتبی ذخیره میکنه. که به هرکدام از اجزاش میگن گره(node).هر گره در درخت یک parentداره  و گره ای که parent نداشته بشه بهش ریشه یا root درخت میگن.هر گره میتون فرزند نداشته باشه یا بیش از یکی داشته باشه.خب حالا فرض کنید شما یک راه نیاز دارید که بیاد فرزندان یک گره را خذف یا پاک کنه.در اینجا یک مثال داریم که یک گره درختی را پیاده‌سازی می‌کنه که از property برای ارائه بیشتر عملکردهای خود استفاده می‌کنه، از جمله امکان پاک کردن لیست فرزندان گره مورد نظر.# tree.py

class TreeNode:
    def __init__(self, data):
        self._data = data
        self._children = []

    @property
    def children(self):
        return self._children

    @children.setter
    def children(self, value):
        if isinstance(value, list):
            self._children = value
        else:
            del self.children
            self._children.append(value)

    @children.deleter
    def children(self):
        self._children.clear()

    def __repr__(self):
        return f&#039;{self.__class__.__name__}(&amp;quot{self._data}&amp;quot)&#039;در مثال بالاTreeNode یک گره در ساختار درختی ماهست.هر گره فرزندان خود را در یک لیست ذخیره میکند.متد deleter همه فرزندان یک گره رو پاک می کند.&gt;&gt;&gt; from tree import TreeNode

&gt;&gt;&gt; root = TreeNode(&amp;quotroot&amp;quot)
&gt;&gt;&gt; child1 = TreeNode(&amp;quotchild 1&amp;quot)
&gt;&gt;&gt; child2 = TreeNode(&amp;quotchild 2&amp;quot)

&gt;&gt;&gt; root.children = [child1, child2]

&gt;&gt;&gt; root.children
[TreeNode(&amp;quotchild 1&amp;quot), TreeNode(&amp;quotchild 2&amp;quot)]

&gt;&gt;&gt; del root.children
&gt;&gt;&gt; root.children
[]ساختن کلاس های سازگار به عقب(Backward-Compatible)همانطور که میدونید _ میان متدهای فراخوندی رو تبدیل به attributeهایی میکنن که قابلیت دسترسی مستقیم دارند.این ویژگی به شما اجازه میده کدهای تمیزبنویسید.حالا شما میتونید attributeهای عمومی خودتون رو بدون setterو getter انتشار بدید.فرض کنیدشما یک برنامه حسابداری برای مدیریت ارز نوشتید و دراختیار کاربران نهایی قرار دادید:class Currency:
    def __init__(self, units, cents):
        self.units = units
        self.cents = centsنکته خارج از بحث:دوستان سیستم پولی ایالات متحده امریکا مبتنی بر ده دهی است، و واحد اصلی پول این کشور دلار (Dollar) و واحد جزء این کشور سنت (Cent) نامیده می شود یعنی هر 100 سنت یک دلار است.در مثال بالا فرض کنید که شما 10 دلارو 20 سنت دارید 10 در units مقدار دهی میشه و 20 در cents.کد بالا بسیار تمیز نوشته شده است.حالا فرض کنید نیازمندی های شما تغییر می کند و تصمیم میگیرید که تعداد کل سنت ها رو ذخیره کنید.حالا اگر بخواهیم cents و unitsپاک  کنیم و بجاش از total_cents استفاده کنیم کاربران نهایی که از این کلاس استفاده می کردن به مشکل خواهند خورد.راه حل استفاده ازproperty است:# currency.py

CENTS_PER_UNIT = 100

class Currency:
    def __init__(self, units, cents):
        self._total_cents = units * CENTS_PER_UNIT + cents

    @property
    def units(self):
        return self._total_cents // CENTS_PER_UNIT

    @units.setter
    def units(self, value):
        self._total_cents = self.cents + value * CENTS_PER_UNIT

    @property
    def cents(self):
        return self._total_cents % CENTS_PER_UNIT

    @cents.setter
    def cents(self, value):
        self._total_cents = self.units * CENTS_PER_UNIT + valueیه توضیح درباره کد بالا:زمانی که کاربر مقدار در موقع ساخت شی، دلار و سنت وارد میکنهtotal_cents میسازیم درواقع عمل تبدیل رو انجام میدیم .خب حالا فرض کاربر تصمیم میگیره مقدار دلار رو عوض کنه دراین صورت مقدار دلار رو در 100 ضرب میکنیم و مقدار سنت که ازقبل داشتیم رو بهش اضافه میکنیم و بهمین ترتیب برای سنت ...خب دوستان این اموزش هم به پایان رسید خیلی مطالب زیاد شد اما سعی کردم مطالب مهم رو بگم.و درنهایت گوش جان میسپاریم به نظرات و انتقادات ارزشمند شما جهت بهبود آموزش هابا تشکر محمد محمودی</description>
                <category>محمد محمودی</category>
                <author>محمد محمودی</author>
                <pubDate>Sat, 30 Mar 2024 12:12:31 +0330</pubDate>
            </item>
                    <item>
                <title>بررسی freeCodeCamp</title>
                <link>https://virgool.io/@mohammed1994159/%D8%A8%D8%B1%D8%B1%D8%B3%DB%8C-freecodecamp-loynuqmm61uh</link>
                <description>      این وبسایت به عنوان یک سازمان ناسودبر دوره های کدنویسی رابه صورت رایگان ارائه می دهدبه هر کسی که می خواهد آنها رابگیرد. دانش آموزان نیازی به داشتن تجربه قبلی یا تحصیلا ت مرتبط ندارند، و هیچ فرآیند درخواستی وجود ندارد -فقط ثبت نام کرده وشروع به یادگیری کنید.      ادعای FreeCodeCamp این است که بیش از 40000نفر از فارغ التحصیلان آن ازسال 2014شغل فنی پیدا کرده اند و در آمازون، اپل، گوگل، مایکروسافت، اسپاتیفا ی وبسیار ی ازشرکت ها ی دیگر مشغول به کار شده اند.       برنامه درسی   FreeCodeCamp ده حوزه مطالعه را دربر می گیرد که تکمیل هریک از آنها حدود 300ساعت طول می کشد که در مجموع 3000 ساعت آموزش می بینید. این سازمان همچنین هزاران ساعت محتوای آموزشی را در کانال یوتیوب خود ارائه می دهد.       فارغ التحصیلان میتوانند ازیک شبکه قوی فارغ التحصیلان بهره مندشوند. freeCodeCampبیش از 115000فارغ التحصیل در لینکدین دارد. FreeCodeCamp همچنین آماده ساز ی مصاحبه کدنویسی رابا هزاران ساعت چالش کدنویسی  تمرینی فرا هم می کند.گواهینامه های freeCodeCampسایت freeCodeCamp همچنان 10 گواهینامه آنلاین مختلف ارائه می دهد که توصیه دارد که به ترتیب خاصی دریافت کنید.انواع گواهینامه های freeCodeCamp1)Responsive Web Designاولین گواهینامه FreeCodeCampطراحی وب واکنشگرا را پوشش می دهد. دانش آموزان یاد می گیرند که چگونه از HTMLو CSSبرای ایجاد و بسایتهایی استفاده کنند که روی صفحه های نمایش با هر اندازه ای خوب به نظربرسند. دانش آموزان باید چندین پروژه رابرای کسب گواهینامه خودبسازند، از جمله یک فرم نظرسنجی،یک صفحه فروش محصول،یک صفحه مستندات فنی ویک نمونه کارشخصی.2)JavaScript Algorithms and Data Structuresدانش‌آموزان در حین کسب گواهی الگوریتم‌های جاوا اسکریپت و ساختار داده، نحوه استفاده از جاوا اسکریپت برای ایجاد یک صفحه وب تعاملی را بررسی می‌کنند. دانش آموزان در مورد آرایه ها، متغیرها، توابع، اشیا و حلقه ها یاد می گیرند.برنامه درسی این گواهینامه هم برنامه نویسی شی گرا و هم برنامه نویسی کاربردی را پوشش می دهد. دانش آموزان باید قبل از اتمام برنامه چندین پروژه جاوا اسکریپت را تکمیل کنند.3)Front-End Development Librariesدر دوره صدور گوا هینامه کتابخانه های توسعه ،end-frontدانش آموزان با استفاده از jQuery، React، Sass ،Bootstrapو Reduxتجربه کسب می کنند.شرکتکنندگان یاد میگیرند که چگونه به یک و بسایت استایل بدهند برنامه های و ب تک صفحه ای ایجاد کنند و عملکردسبد خرید رابرا ی یک صفحه وب بسازند.4)Data Visualizationدروس تجسم داده هابه دانش آموزان آموزش می دهد که از کتابخانه  js.D3  برا ی ساختن  نمودار ها و نقشه ها استفاده کنند. دانش آموزان همچنین یاد می گیرند که چگونه داده ها رابایک APIدستکاری کنند و چگونه از JSON استفاده کنند.برا ی کسب این گوا هی، فراگیران بایدپنج پروژه رابا استفاده از رو ش ها ی متعددتجسم داده هاتکمیل کنند: نمودار میلها ی، نمودارپراکندگی، نقشه حرارتی و نمودار درختی.5)APIs and Microservicesدانش آموزانی که مجوز APIو میکروسرویس ها را دنبال می کنند،یاد می گیرند که چگونه از جاوا اسکریپت برا ی توسعه و ب بک اند استفاده کنند. دانشآموزان از npmو js.Nodeو همچنین چارچو ب MongoDB، Express و کتابخانه Mongooseاستفاده میکنند.پروژه هایی که برا ی کسب این گواهینامه بایدتکمیل شوند عبارتند از ایجادیک میکروسرویس برچسب زمانی،یک میکروسرویس کوتاه کننده URLویک میکروسرویس فراداده فایل.6)Quality Assuranceدوره گواهینامه تضمین کیفیت نحوه آزمایش برنامه های کاربردی وب برای اطمینان از عملکرد صحیح آنها راپوشش می د هد. دانشآموزان مفاهیم پیشرفته Expressو Nodeرایاد می گیرند، از کتابخانه آزمایشی JavaScript Chaiاستفاده میکنند ویک ردیاب مشکل ویک برنامه چت ایجاد میکنند که از احراز هویت استفاده می کند.7)Scientific Computing With Pythonاین گزینه گواهی برنامه نویسی با پایتون راشامل آموزش نحوه استفاده ازشرطی ها، حلقه ها، متغیر ها وتوابع می کند. دانش آموزان همچنین در موردشبکه ساز ی،ساختارهای داده،تجسم دادهها وپایگاه های داده رابطه ای می آموزند.برا ی کسب این گوا هی، دانش آموزان باید چندین پروژه رابا استفاده ازپایتون انجام دهند، از جمله یک برنامه بودجه ویک ماشین حساب احتمال.8)Data Analysis With Pythonدانش آموزانی که این گواهینامه را دریافت می کنند،تجزیه وتحلیل داده ها رابا استفاده ازپایتون یاد می گیرند. دانش آموزان همچنین از ،SQLپاندا ها و NumPyاستفاده می کنند.برا ی کسب گواهینامه، دانش آموزان بایدیک تحلیلگر داده های جمعیتی، یک تصویرساز داده های پزشکی ویک پیشبینی کننده سطح دریا طراحی کنند.9)Information Securityاین دوره گواهینامه امنیت اطلاعات به دانش آموزان می آموزد که چگونه با استفاده از js.Helmetو Pythonاطلاعا ت را ایمن نگه دارند.برا ی کسب این گواهی، دانش آموزان بایدیک چک کننده قیمت سهام،یک تابلوی پیام ناشناس،یک اسکنرپورت، یک رمز عبور ویک بازی چند نفره ایمن طراحی کنند.10)Machine Learning With Pythonدر حین پیگیری صدور گواهینامه یادگیری ماشینی freeCodeCamp  دانش آموزان یاد می گیرند که از چارچوب TensorFlowبرا ی کشف یادگیری تقویتی وپردازش زبان طبیعی وساخت شبکه های عصبی استفاده کنند.برای کسب گواهینامه، دانش آموزان بایدیک طبقه بندی کننده تصویر گربه وسگ،یک موتورتوصیه کتاب ویک طبقه بندی متن پیام کوتاه شبکه عصبی طراحی کنند.</description>
                <category>محمد محمودی</category>
                <author>محمد محمودی</author>
                <pubDate>Sun, 10 Jul 2022 00:20:13 +0430</pubDate>
            </item>
            </channel>
</rss>