সাজসজ্জা কার্যকর করার আদেশ


96
def make_bold(fn):
    return lambda : "<b>" + fn() + "</b>"

def make_italic(fn):
    return lambda : "<i>" + fn() + "</i>"

@make_bold
@make_italic
def hello():
  return "hello world"

helloHTML = hello()

আউটপুট: "<b><i>hello world</i></b>"

আমি সজ্জিতদের সম্পর্কে মোটামুটিভাবে বুঝতে পারি এবং এটি বেশিরভাগ উদাহরণে এটির সাথে কীভাবে কাজ করে।

এই উদাহরণে এটির 2 টি রয়েছে। আউটপুট থেকে, মনে হয় এটি @make_italicপ্রথমে কার্যকর করে, তারপরে @make_bold

এর অর্থ কি এই যে সজ্জিত ফাংশনগুলির জন্য, এটি প্রথমে প্রথমে ফাংশনটি পরিচালনা করবে তারপরে অন্যান্য সাজসজ্জার ক্ষেত্রে শীর্ষের দিকে চলে যাবে? বিপরীতে পরিবর্তে @make_italicপ্রথম মত @make_bold

সুতরাং এর অর্থ এটি বেশিরভাগ প্রোগ্রামিং ল্যাং-এ টপ-ডাউন পদ্ধতির আদর্শ থেকে আলাদা? শুধু এই সাজসজ্জার ক্ষেত্রে? নাকি আমি ভুল করছি?


4
হ্যাঁ এটি নীচে থেকে পরবর্তীটিতে পাস করার ফলাফলটি শুরু করে
প্যাডেরিক কানিংহাম

4
@ প্যাড্রেইকিংহাম মন্তব্যটিও উত্তরের একটি গুরুত্বপূর্ণ অংশ। একটি সম্পর্কিত সমস্যা (ছিল stackoverflow.com/questions/47042196/... )
shookees

আমি বলব এটি এখনও উপরের নিচে, টপ-ডাউন যে অর্থে a(b(x))(যদি আপনি 3 লাইনের উপরের বিভাজনটি কল্পনা করেন)
জয়েল

উত্তর:


131

সাজসজ্জাকারীরা সজ্জিত ফাংশনটি তাকে জড়িয়ে রাখেন । তাই make_boldসাজসজ্জার ফল সজ্জিত make_italic, যা helloফাংশন সজ্জিত ।

@decoratorসিনট্যাক্স সত্যিই ঠিক অন্বিত চিনি; অনুসরণ:

@decorator
def decorated_function():
    # ...

সত্যই কার্যকর করা হয়:

def decorated_function():
    # ...
decorated_function = decorator(decorated_function)

আসল decorated_functionবস্তুটি যা-ই decorator()ফিরে আসবে তা প্রতিস্থাপন করা ।

স্ট্যাকিং সজ্জাকরণগুলি বাহ্যিকভাবে প্রক্রিয়া পুনরাবৃত্তি করে ।

সুতরাং আপনার নমুনা:

@make_bold
@make_italic
def hello():
  return "hello world"

এতে বাড়ানো যেতে পারে:

def hello():
  return "hello world"
hello = make_bold(make_italic(hello))

আপনি যখন hello()এখন কল করবেন তখন আপনি make_bold()সত্যিকার অর্থে অবজেক্টটিকে কল করেছেন । এমন make_bold()একটি ফিরিয়ে দিল যা lambdaফাংশনটিকে make_boldমোড়কে কল করে , এটির ফিরতি মান make_italic(), যা ল্যাম্বডা যা মূলটিকে কল করে hello()। এই কলগুলি আপনি প্রসারিত করছেন:

hello() = lambda : "<b>" + fn() + "</b>" #  where fn() ->
    lambda : "<i>" + fn() + "</i>" # where fn() -> 
        return "hello world"

সুতরাং আউটপুট হয়ে যায়:

"<b>" + ("<i>" + ("hello world") + "</i>") + "</b>"

আমি বুঝেছি. তবে এর অর্থ কি এই যে যখন এই ক্ষেত্রে 2 টি মোড়ক থাকে, তখন আইডিই স্বয়ংক্রিয়ভাবে প্রথম মোড়কের ফলাফলটি সনাক্ত করে এবং মোড়ায়? কারণ আমি ভেবেছি @make_bold #make_bold = make_bold(hello) @make_italic #make_italic = make_italic (hello)? আমি নিশ্চিত না যে এর ভিত্তিতে যদি এটি হয় তবে এটি প্রথম ফলাফলটি গুটিয়ে দেবে। অথবা 2 টি মোড়কের ক্ষেত্রে আইডিই make_bold(make_italic(hello))আমি যা ভাগ করেছি তার পরিবর্তে আপনি উল্লিখিত হিসাবে ব্যবহার করবেন ?
নবাবি

4
@ নিউবি: আপনার আইডিই এখানে কিছুই করে না; এটি পাইথন যা মোড়কে দেয়। আমি আপনাকে আমার সর্বশেষ নমুনায় দেখিয়েছি যা make_bold()আউটপুট make_italic()মোড়ানো hello, যা মোড়ানোর জন্য ব্যবহৃত হয়েছিল , তাই এর সমতুল্য make_bold(make_italic(hello))
মার্টিজন পিটারস

লাম্বদা ব্যবহার না করে আপনি এই কোডটির একটি সংস্করণ সরবরাহ করতে পারেন? আমি চেষ্টা করেছি। ফর্ম্যাট কিন্তু কাজ করে না। এবং লাম্বদা কেন এই উদাহরণে ব্যবহৃত হয়? আমি ল্যাম্বদা বোঝার চেষ্টা করছি এবং এটি এই উদাহরণে কীভাবে কাজ করে তবে এখনও সমস্যা আছে। আমি পেয়েছি যে ল্যাম্বদা একটি লাইন ফাংশনের মতো যা ডিএফ ফাংশনগুলির আদর্শের তুলনায় খুব সহজেই পাস করা যায়?
নবাবি

def inner: return "<b>" + fn() + "</b>"তারপরে, return innerএটি হবে 'নিয়মিত' ফাংশন সংস্করণ; বড় পার্থক্য না।
মার্টিজন পিটারস

আমি অর্ডার সম্পর্কে সর্বদা বিভ্রান্ত হই। "..." ডিএফ "স্টেটমেন্টের নিকটতমতম দিয়ে শুরু করে সজ্জকার প্রয়োগ করা হবে" আমি এটিকে "অভ্যন্তরীণ " বলি। আমি মনে করি মার্তিজন এটিকে "বাহ্যিক" বলে। এর অর্থ হল make_italic সাজসজ্জারের আগে make_bold ডেকরেটার কার্যকর করা হয় , কারণ make_italicএর নিকটতম def। যাইহোক, আমি ভুলে গেছি যে সজ্জিত কোড এক্সিকিউশন অর্ডার: make_bold সজ্জিত (অর্থাত্ বোল্ড ল্যাম্বদা) প্রথমে কার্যকর করা হয়, তার পরে make_italic সজ্জিত ল্যাম্বদা (অর্থাত্ ইটালিক ল্যাম্বদা)।
লাল মটর
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.