پرسش در مورد Decorators در پایتون

سلام. موضوع Decorators چه قدر سخته. مطالب تو اینترنت زیاد هست ولی بازم متوجه نشدم.

میشه کمی توضیح بدید راجب این موضوع که چی هست. اگر زحمتی نیست بدش این خط کد رو تحلیل میکنید

def noun(i):
    def tag(func):
        def wrapper(name):
            return "My {0} is {1}".format(i,func(name))
        return wrapper
    return tag

@noun("name")
def say_something(something):
    return something

print(say_something("siavash"))

این فیلم آموزشی فارسی احتمالا کمکت کنه

Decorator در پایتون

2 Likes

خب decorator اصلا سخت نیست. احتمالا شما قبل از اینکه با یه سری تعریفها آشنا بشید سراغش رفتید. من یه کم فلسفه‌ی کار رو بیشتر براتون توضیح میدم.

قضیه اینه که توی بعضی زبانهای برنامه نویسی، ما قابلیتهای first class function داریم.
یعنی توابع ما، مثل متغیرهامون قابل فرستادن به یه تابع دیگه یا return شدن از یه تابع دیگه هستن.

مثلا تابع x رو به عنوان آرگومان میفرستیم به تابع y.
در این مورد، به تابع y میگیم «Higher Order Function»

def inc(x):
    return x + 1

def operate(func, x):
    return func(x)

operate(inc, 5)
# 6

توی مثال بالا (که با کمی تغییر از لینک زیر کپی کردم) ما تابع inc رو مثل یه متغیر یا مثل یه عدد میفرستیم به تابع operate و تابع operate داره به ما یه function call برمیگردونه.


خب. حالا ما یه زبان برنامه نویسی داریم که میتونیم داخلش یه تابع رو به یه تابع دیگه بفرستیم یا میتونیم یه تابع داشته باشیم که یه تابع دیگه رو generate کنه (generator ها در پایتون!)

حالا ما توی پایتون یه چیزی داریم به نام decorator. که در حقیقت با استفاده از همین ویژگیها، میاد یه post-processor و یه pre-processor برای تابع ما میسازه.
در حقیقت بدون اینکه تابعمون رو ویرایش کنیم، میتونیم تعیین کنیم که ورودیهای این تابع یه مقدار ویرایش بشن بعد فرستاده بشن به تابع. یا قبل از return شدن، یه سری تغییراتی روشون اعمال بشه. (مثلا فرض کنید که میخوایم قبل از اینکه ورودیها به تابع فرستاده بشن فیلتر بشن و مثلا اعداد منفی از لیست ورودیها حذف بشن و در انتهای کار تابع، خروجیها قبل از return شدن، تبدیل به json بشن)
در این وضعیت، ما از decoratorها استفاده میکنیم.

اینکه یه کم عجیب غریبه، به خاطر اینه که سینتکسش با بقیه‌ی کدها فرق میکنه و در حقیقت یه سینتکس ساده شده بهمون میده که لازم نباشه خودمون تابع‌ها رو به همدیگه پاس کاری کنیم. وگرنه چیز عجیب غریبی نداره.

برای مطالعه‌ی بیشتر درمورد decoratorها و دیدن یه سری مثال، شاید این لینک مناسب باشه:
https://www.programiz.com/python-programming/decorator

7 Likes

سپاس از دوستان علل خصوص از آقا پویا که همیشه مارو از توضیحات و آموزش های خوبشون دریغ نکردند.

2 Likes

خوشحالم که میتونم کمک کنم.
منم یه زمان نه چندان دور، تو همین وضعیت شما بودم (و واقعا decoratorها رو نمیفهمیدم چون با یه سری تعریفهای پیش‌نیاز آشنا نبودم)
یه زمانی از دکوریتورهای flask استفاده میکردم بدون اینکه بدونم واقعا اینا چیکار میکنن.

الآن که فکرشو میکنم، کلوژر خیلی بهم کمک کرد که این مفاهیم رو عمیق‌تر یاد بگیرم. منظورم مفاهیم functional programming هست.
پایتون هم یه سری از ویژگیهای fp رو داخل خودش داره ولی اصلا نمیتونم به عنوان یه زبان functional بهش نگاه کنم.

3 Likes

حالا کار
@property
چیه؟

متد زیرش رو بدون پرانتز صدا میزنه - مثل یک property ( البته متد نباید ورودی بگیره و فقط برای متد های کلاس استفاده میشه )

مثلا

class Human:
   def __init__(self, first_name, last_name): 
       self.first_name, self.last_name = first_name, last_name

   @property
   def full_name(self):
       return self.first_name + ' ' + self.last_name

نحوه استفاده اش اینطوری میشه:

‍‍

ali = Human('ali', 'amiri')

اگر از property استفاده نکنیم ( تو کد بالا ) باید اینطوری اسم کاملش رو بگیری:

ali.full_name()

اگر پسر خوبی باشی و استفاده بکنی، باید اینطوری اسم کاملش رو بگیری:

ali.full_name
1 Likes

ممنونم خیلی خوب توضیح دادین.
لینک فیلمی که از آپارات گذاشته بودین هم خیلی مفید بود واسم :slight_smile: :pray: :heart:
فقط یه سوال دیگه :sweat_smile:

تا جایی که فهمیدم استفاده از [email protected] فقط باعث میشه که از پرانتز استفاده نکنیم و چیز خاصی نیست… چرا گفتین :

بخاطر قوانین و اصولیه که برای نوشتن کد تمیز درنظر گرفته شده یا فواید دیگه‌ای هم داره؟

1 Likes

راستش به نظر من خیلی وجودش ضروری نیست ولی بازم بر میگرده به نحوه استفاده تون
مثلا بدون استفاده ازش اسم تابع تون رو بهتره بنویسید: get_full_name
ولی با @property میتونید بنویسید: full_name

1 Likes