পাইথন সাজসজ্জার জন্য কিছু সাধারণ ব্যবহার কি? [বন্ধ]


336

যদিও আমি নিজেকে যুক্তিসঙ্গতভাবে যোগ্য পাইথন কোডার হিসাবে ভাবতে চাই, আমি যে ভাষাটি কখনই কুঁকড়ে উঠতে পারি না সেগুলির একটি দিক হ'ল সাজসজ্জা।

আমি জানি তারা কী (অতিমাত্রায়), আমি স্ট্যাক ওভারফ্লোতে টিউটোরিয়াল, উদাহরণ, প্রশ্নগুলি পড়েছি এবং সিনট্যাক্সটি বুঝতে পারি, নিজের লেখা লিখতে পারি, মাঝে মাঝে @ ক্লাসমেডোথ এবং @ স্ট্যাটিকমেডোর ব্যবহার করতে পারি তবে এটি কখনও আমার ব্যবহারের জন্য হয় না আমার নিজের পাইথন কোডটিতে একটি সমস্যা সমাধান করার জন্য ডেকোরেটর। আমি কখনই এমন সমস্যার মুখোমুখি হই না যেখানে আমি মনে করি, "হুম ... এটি সাজসজ্জার জন্য একটি কাজের মতো দেখাচ্ছে!"

সুতরাং, আমি ভাবছি যে আপনি যদি নিজের প্রোগ্রামগুলিতে সজ্জাগুলি ব্যবহার করেছেন এমন কিছু উদাহরণ আপনি উপস্থাপন করতে পারেন এবং আশা করি আমার একটি "এ-হা!" মুহূর্ত এবং তাদের পেতে


5
এছাড়াও, সজ্জাকারীরা মেমোজাইজিংয়ের জন্য দরকারী - এটি কোনও ফাংশনের ধীর-গুনের ফলাফলকে ক্যাশে করছে। সাজসজ্জাকারী কোনও ফাংশন ফিরিয়ে আনতে পারে যা ইনপুটগুলি পরীক্ষা করে এবং যদি তারা ইতিমধ্যে উপস্থাপন করা হয় তবে একটি ক্যাশেড ফলাফলটি ফিরিয়ে দিতে পারে।
পিটার 21

1
দ্রষ্টব্য, পাইথনের একটি অন্তর্নির্মিত সজ্জা রয়েছে, functools.lru_cacheযা পিটার বলেছিলেন ঠিক তাই করেন, পাইথন ৩.২ থেকে ফেব্রুয়ারী ২০১১-এ প্রকাশিত।
তাইগ্যং

এর সূচিপত্র পাইথন প্রসাধক লাইব্রেরী আপনি তাদের জন্য অন্য ব্যবহারের একটি ভাল ধারণা দিতে হবে।
মার্টিনিউ

উত্তর:


126

আমি মূলত সময়কালীন উদ্দেশ্যে সজ্জকার ব্যবহার করি

def time_dec(func):

  def wrapper(*arg):
      t = time.clock()
      res = func(*arg)
      print func.func_name, time.clock()-t
      return res

  return wrapper


@time_dec
def myFunction(n):
    ...

13
ইউনিক্সের অধীনে time.clock()সিপিইউ সময় পরিমাপ করে। আপনি time.time()যদি প্রাচীর-ঘড়ির সময় পরিমাপ করতে চান তবে পরিবর্তে আপনি ব্যবহার করতে চাইতে পারেন ।
জবাবা

20
দুর্দান্ত উদাহরণ! যদিও এটি কি কোন ধারণা। আপনি সেখানে কী করছেন এবং ডেকোরেটার কীভাবে সমস্যা সমাধান করে তা একটি ব্যাখ্যা খুব সুন্দর হবে।
মেইলাইট

7
ঠিক আছে, এটি myFunctionচালানোর জন্য যা সময় নেয় তা পরিমাপ করে ...
আরএসবেট

98

আমি এগুলি সিঙ্ক্রোনাইজেশনের জন্য ব্যবহার করেছি।

import functools

def synchronized(lock):
    """ Synchronization decorator """
    def wrap(f):
        @functools.wraps(f)
        def newFunction(*args, **kw):
            lock.acquire()
            try:
                return f(*args, **kw)
            finally:
                lock.release()
        return newFunction
    return wrap

মন্তব্যে নির্দেশিত হিসাবে, পাইথন ২.২ থেকে আপনি সাজসজ্জার প্রয়োগ কার্যকর করার জন্য withকোনও threading.Lock(বা multiprocessing.Lockসংস্করণ ২.6 থেকে) অবজেক্টের সাথে একযোগে একটি বিবৃতি ব্যবহার করতে পারেন :

import functools

def synchronized(lock):
    """ Synchronization decorator """
    def wrap(f):
        @functools.wraps(f)
        def newFunction(*args, **kw):
            with lock:
                return f(*args, **kw)
        return newFunction
    return wrap

নির্বিশেষে, আপনি এটির পরে এটি ব্যবহার করুন:

import threading
lock = threading.Lock()

@synchronized(lock)
def do_something():
  # etc

@synchronzied(lock)
def do_something_else():
  # etc

মূলত এটি কেবল ফাংশন কলের উভয় পাশে lock.acquire()/ রাখে lock.release()


17
সম্ভবত ন্যায্য, কিন্তু সাজসজ্জা অন্তর্নিহিত বিভ্রান্তিকর, esp। প্রথম বছরের নুব যারা আপনার পিছনে আসে এবং আপনার কোডটি মোড করার চেষ্টা করে। এটিকে সরলতার সাথে এড়িয়ে চলুন: কেবলমাত্র 'লক সহ:' এর অধীনে একটি কোডে ডো_সামিং () এর কোডটি আবদ্ধ করুন এবং প্রত্যেকে আপনার উদ্দেশ্য স্পষ্ট দেখতে পাবে। লোকেরা স্মার্ট বলে মনে করে (এবং অনেকগুলি প্রকৃতই হ'ল) ​​দ্বারা বিস্তৃতভাবে ব্যবহার করা হয় তবে কোডটি নিখুঁতভাবে আসে এবং তা কার্যকর হয়।
কেভিন জে রাইস

18
@ কেভিনজে.আরাইস আপনার কোডটি সীমিত করছেন যাতে 'প্রথম-বছরের নুবস' আরও ভালভাবে বুঝতে পারে যে এটি ভয়ানক অনুশীলন। ডেকোরেটর সিনট্যাক্স পড়তে অনেক সহজ এবং কোডটি ব্যাপকভাবে ডিকোপল করে।
টেলারজোনস

18
@ টেলারজোনস, লেখার সময় কোড পাঠযোগ্যতা আমার সর্বোচ্চ অগ্রাধিকার সম্পর্কে। কোডটি প্রতিবার পরিবর্তিত হওয়ার জন্য 7+ বার পঠিত হয়। কোড বুঝতে অসুবিধা (নুবসের জন্য বা সময়ের চাপে কাজ করা বিশেষজ্ঞদের পক্ষে) প্রযুক্তিগত debtণ যা প্রতিবার যখন কেউ উত্স ট্রিটিতে দেখা হয় তখন তাকে প্রদান করতে হয়।
কেভিন জে রাইস

@ টেলর জোনস একজন প্রোগ্রামারের পক্ষে সর্বাধিক গুরুত্বপূর্ণ কাজ হল স্পষ্টতা সরবরাহ করা।
JDOaktown

71

আমি টাইপ চেকিং পরামিতিগুলির জন্য সজ্জকার ব্যবহার করি যা আমার পাইথন পদ্ধতিতে কিছু আরএমআই এর মাধ্যমে পাস করা হয়। সুতরাং একই পরামিতি গণনা পুনরাবৃত্তি করার পরিবর্তে বার বার ব্যতিক্রম উত্থাপন মাম্বো-জাম্বো।

উদাহরণস্বরূপ, পরিবর্তে:

def myMethod(ID, name):
    if not (myIsType(ID, 'uint') and myIsType(name, 'utf8string')):
        raise BlaBlaException() ...

আমি শুধু ঘোষণা:

@accepts(uint, utf8string)
def myMethod(ID, name):
    ...

এবং accepts()আমার জন্য সমস্ত কাজ করে।


15
আগ্রহী প্রত্যেকের জন্য, @acceptsপিইপি 318 এর একটি বাস্তবায়ন রয়েছে
মার্টিনিউ

2
আমার মনে হয় টাইপো আছে .. প্রথম পদ্ধতিটি গ্রহণ করা উচিত .. আপনি উভয়কে "মাইমাথোদ" হিসাবে ঘোষণা করেছেন
DevC

1
@ ডিভিসি না, এটি টাইপোর মতো দেখাচ্ছে না। যেহেতু এটি স্পষ্টভাবে "গ্রহণ করে (..)" এর বাস্তবায়ন নয়, এবং এখানে "মাইমেথোদ (..)" এর শুরুতে দুটি লাইন দ্বারা যে কাজটি করা হবে তা এখানে "গ্রহণ করে (..)" করে - এটিই খাপ খায় এমন ব্যাখ্যাই।
এভেজেনি সার্জিভ

1
দ্বন্দ্বের জন্য দুঃখিত, আমি কেবল এটি উল্লেখ করতে চেয়েছিলাম যে আর্গুমেন্টগুলির প্রকারটি যাচাইয়ের জন্য পরীক্ষা করা এবং একটি টাইপ এরির বাড়াতে অন্যথায় এটি একটি খারাপ অভ্যাস হিসাবে বিবেচিত হয় কারণ এটি কেবল কোনও ফ্লোটের জন্য যাচাই করে যদি কোনও ইন্টি গ্রহণ করে না এবং কারণ সাধারণত কোডটি নিজেই সর্বাধিক নমনীয়তার জন্য পাস করা বিভিন্ন ধরণের মানগুলির জন্য মানিয়ে নেওয়া উচিত।
গুস্তাভো 6046

2
পাইথনে টাইপ চেকিংয়ের প্রস্তাবিত উপায়টি বিল্ট-ইন isinstance()ফাংশনটির মাধ্যমে হয় , যেমন এটি ডেকরেটারের পিইপি 318 বাস্তবায়নে সম্পন্ন হয়েছে । যেহেতু এর classinfoযুক্তি এক বা একাধিক প্রকারের হতে পারে, এটি ব্যবহার করে @ গুস্তাভো 6046 এর (বৈধ) আপত্তি প্রশমিত হবে। পাইথনের একটি Numberবিমূর্ত বেস শ্রেণি রয়েছে, সুতরাং খুব জেনেরিক পরীক্ষা যেমন isinstance(42, numbers.Number)সম্ভব হয়।
মার্টিনিউ

48

আপনি অতিরিক্ত কার্যকারিতা সহ স্বচ্ছভাবে "মোড়ানো" করতে চান এমন কোনও কিছুর জন্য সজ্জাগুলি ব্যবহার করা হয়।

জ্যাঙ্গো তাদের ভিউ ফাংশনে "লগইন প্রয়োজনীয়" কার্যকারিতা মোড়ানোর জন্য , পাশাপাশি ফিল্টার ফাংশনগুলি নিবন্ধকরণের জন্য ব্যবহার করে

ক্লাসে নামযুক্ত লগ যুক্ত করার জন্য আপনি শ্রেণি সজ্জা ব্যবহার করতে পারেন ।

বিদ্যমান শ্রেণি বা ফাংশনের আচরণের জন্য আপনি যে "যথেষ্ট পরিমাণে জেনেরিক কার্যকারিতা" করতে পারেন তা হ'ল সাজসজ্জার জন্য ন্যায্য খেলা।

পিইপি 318 - ফাংশন এবং পদ্ধতিগুলির জন্য সজ্জাকারী দ্বারা নির্দেশিত পাইথন-দেব নিউজগ্রুপে ব্যবহারের মামলাগুলির বিষয়েও আলোচনা রয়েছে


চেরিপি কোন ক্রিয়াকলাপ সর্বজনীন এবং কোনটি লুকানো ফাংশন তা সরল রাখার জন্য @ cherrypy.expose ব্যবহার করে। এটি আমার প্রথম পরিচয় ছিল এবং আমি এটির সাথে অভ্যস্ত হয়ে গেলাম।
মার্ক ম্যাক্সমিস্টার

26

নস্টিস্টের জন্য, আপনি একটি ডেকরেটার লিখতে পারেন যা পরামিতিগুলির কয়েকটি সেট সহ ইউনিট টেস্ট ফাংশন বা পদ্ধতি সরবরাহ করে:

@parameters(
   (2, 4, 6),
   (5, 6, 11),
)
def test_add(a, b, expected):
    assert a + b == expected

23

ট্যুইস্টেড লাইব্রেরি জেনারেটরের সাথে সম্মিলিত সজ্জা ব্যবহার করে এই বিভ্রান্তি দেয় যে একটি অ্যাসিঙ্ক্রোনাস ফাংশন সিঙ্ক্রোনাস। উদাহরণ স্বরূপ:

@inlineCallbacks
def asyncf():
    doStuff()
    yield someAsynchronousCall()
    doStuff()
    yield someAsynchronousCall()
    doStuff()

এটি ব্যবহার করে, কোড যা একটি টন কলব্যাক ফাংশনের মধ্যে বিভক্ত হয়ে গেছে তা একটি প্রাকৃতিকভাবে একক ব্লক হিসাবে লিখিত হতে পারে, এটি বোঝা ও বজায় রাখা আরও সহজ করে তোলে।


14

একটি সুস্পষ্ট ব্যবহার অবশ্যই লগিংয়ের জন্য:

import functools

def log(logger, level='info'):
    def log_decorator(fn):
        @functools.wraps(fn)
        def wrapper(*a, **kwa):
            getattr(logger, level)(fn.__name__)
            return fn(*a, **kwa)
        return wrapper
    return log_decorator

# later that day ...
@log(logging.getLogger('main'), level='warning')
def potentially_dangerous_function(times):
    for _ in xrange(times): rockets.get_rocket(NUCLEAR=True).fire()

10

আমি এগুলি মূলত ডিবাগিংয়ের জন্য ব্যবহার করি (কোনও ফাংশনের চারপাশে মোড়ানো যা তার আর্গুমেন্ট এবং ফলাফল মুদ্রণ করে) এবং যাচাইকরণ (উদাহরণস্বরূপ কোনও যুক্তি সঠিক টাইপের কিনা তা পরীক্ষা করতে বা ওয়েব অ্যাপ্লিকেশনের ক্ষেত্রে যদি ব্যবহারকারীর নির্দিষ্ট কল করার যথেষ্ট সুযোগ থাকে) পদ্ধতি)।


6

ফাংশন থ্রেডসেফ তৈরি করার জন্য আমি নীচের সাজসজ্জা ব্যবহার করছি। এটি কোডটিকে আরও পঠনযোগ্য করে তোলে। এটি জন ফুহির প্রস্তাবিত একটির সাথে প্রায় একই রকম তবে পার্থক্যটি হ'ল একক ফাংশনে এক কাজ এবং স্পষ্টভাবে লক অবজেক্ট তৈরি করার দরকার নেই।

def threadsafe_function(fn):
    """decorator making sure that the decorated function is thread safe"""
    lock = threading.Lock()
    def new(*args, **kwargs):
        lock.acquire()
        try:
            r = fn(*args, **kwargs)
        except Exception as e:
            raise e
        finally:
            lock.release()
        return r
    return new

class X:
    var = 0

    @threadsafe_function     
    def inc_var(self):
        X.var += 1    
        return X.var

1
এর অর্থ কি প্রতিটি ফাংশন, তাই সজ্জিত, এর নিজস্ব লক রয়েছে?
শোক করুন

1
@ দুঃখিত হ্যাঁ, প্রতিটি সময় ডেকোরেটর ব্যবহার করা হয় (বলা হয়) এটি সজ্জিত ফাংশন / পদ্ধতিটির জন্য একটি নতুন লক অবজেক্ট তৈরি করে।
মার্টিনিউ

5
এটা সত্যিই বিপজ্জনক। Inc_var () পদ্ধতিটি হ'ল "থ্রেডসেফ" যাতে একবারে কেবল একজন ব্যক্তি কল করতে পারে। এটি বলেছিল যেহেতু এই পদ্ধতিটি সদস্য ভেরিয়েবল "var" তে কাজ করে এবং সম্ভবত অন্যান্য পদ্ধতিগুলি সদস্য ভেরিয়েবল "var" এও পরিচালনা করতে পারে এবং লকটি ভাগ না করা হওয়ায় এই অ্যাক্সেসগুলি থ্রেডসেফ নয়। এইভাবে জিনিসগুলি করা দশম শ্রেণির ব্যবহারকারীকে সুরক্ষার ভ্রান্ত ধারণা দেয়।
বব ভ্যান জ্যান্ট

একক লক ব্যবহৃত না হওয়া পর্যন্ত থ্রেড নিরাপদ নয়।
চান্দু

5

সাজসজ্জারগুলি ফাংশনের বৈশিষ্ট্যগুলি সংজ্ঞায়িত করতে বা এটির পরিবর্তিত বয়লারপ্লেট হিসাবে ব্যবহৃত হয়; এটি সম্পূর্ণ পৃথক ফাংশন ফিরিয়ে দেওয়া সম্ভব তবে পাল্টা স্বজ্ঞাত। এখানে অন্যান্য প্রতিক্রিয়াগুলির দিকে তাকিয়ে দেখে মনে হচ্ছে যে সর্বাধিক সাধারণ ব্যবহারগুলির মধ্যে একটি হ'ল অন্য কিছু প্রক্রিয়ার সুযোগ সীমাবদ্ধ করা - এটি লগিং, প্রোফাইলিং, সুরক্ষা চেক ইত্যাদি etc.

চেরিপ্যাই অবজেক্ট-প্রেরণ ব্যবহার করে ইউআরএলগুলি অবজেক্টগুলিতে এবং শেষ পর্যন্ত পদ্ধতিগুলির সাথে মেলে। এই পদ্ধতিগুলির সজ্জাকারকরা চেরিপাইকে এমনকি এই পদ্ধতিগুলি ব্যবহার করার অনুমতি দেয় কিনা তা ইঙ্গিত দেয় । উদাহরণস্বরূপ, টিউটোরিয়াল থেকে অভিযোজিত :

class HelloWorld:

    ...

    def secret(self):
        return "You shouldn't be here."

    @cherrypy.expose
    def index(self):
        return "Hello world!"

cherrypy.quickstart(HelloWorld())

এটি সত্য নয়। সাজসজ্জাকারী কোনও ফাংশনের আচরণ পুরোপুরি পরিবর্তন করতে পারে।
পুনরাবৃত্তি

ঠিক আছে. তবে কতক্ষণ না কোনও সাজসজ্জা "কোনও ফাংশনের আচরণের সম্পূর্ণ পরিবর্তন করে?" আমি যা দেখেছি, সেগুলি থেকে যখন তারা বৈশিষ্ট্য নির্দিষ্ট করতে ব্যবহৃত হয় না, সেগুলি কেবল বয়লারপ্লেট কোডের জন্য ব্যবহৃত হয়। আমি আমার প্রতিক্রিয়া সম্পাদনা করেছি।
নিখিল চেলিয়াহ

5

সামাজিক নেটওয়ার্কিং ওয়েব অ্যাপ্লিকেশনটিতে কাজ করার সময় আমি সেগুলি সম্প্রতি ব্যবহার করেছি। সম্প্রদায় / গোষ্ঠীগুলির জন্য, নতুন আলোচনা তৈরি করতে এবং আপনাকে সেই নির্দিষ্ট গোষ্ঠীর সদস্য হতে হবে এমন কোনও বার্তার জবাব দেওয়ার জন্য আমার সদস্যপদ অনুমোদনের কথা ছিল। সুতরাং, আমি একটি সাজসজ্জা লিখেছিলাম @membership_requiredএবং আমার দৃষ্টিতে যেখানে প্রয়োজন সেখানে রেখেছি।


1

আমি পরামিতি ঠিক করতে এই ডেকরেটার ব্যবহার করি

def fill_it(arg):
    if isinstance(arg, int):
        return "wan" + str(arg)
    else:
        try:
            # number present as string
            if str(int(arg)) == arg:
                return "wan" + arg
            else:
                # This should never happened
                raise Exception("I dont know this " + arg)
                print "What arg?"
        except ValueError, e:
            return arg

def fill_wanname(func):
    def wrapper(arg):
        filled = fill_it(arg)
        return func(filled)
    return wrapper

@fill_wanname
def get_iface_of(wanname):
    global __iface_config__
    return __iface_config__[wanname]['iface']

আমি যখন কিছু ফাংশনগুলিকে "WNN" দিয়ে আর্গুমেন্টটি পাস করতে পারি তবে এটি পুরানো কোডগুলিতে আমি কেবল N বা 'N' পাশ করেছি


1

সহজেই ফাংশন পদ্ধতি ভেরিয়েবলগুলি তৈরি করতে ডেকরেটার ব্যবহার করা যেতে পারে।

def static_var(varname, value):
    '''
    Decorator to create a static variable for the specified function
    @param varname: static variable name
    @param value: initial value for the variable
    '''
    def decorate(func):
        setattr(func, varname, value)
        return func
    return decorate

@static_var("count", 0)
def mainCallCount():
    mainCallCount.count += 1

6
আপনার উদাহরণের জন্য আপনাকে ধন্যবাদ, তবে (অ্যাপলজিগুলি) আমাকে ডব্লিউটিএফ বলতে হবে - আপনি এটি কেন ব্যবহার করবেন? এটি মানুষকে বিভ্রান্ত করার জন্য বিশাল সম্ভাবনা রয়েছে। অবশ্যই, আমি এজ-কেস ব্যবহারের প্রয়োজনগুলির প্রতি সম্মান জানাই, তবে আপনি একটি অনাবাদী পাইথন ডেভসদের একটি সাধারণ সমস্যাটিকে লক্ষ্য করছেন - যথেষ্ট ক্লাস ব্যবহার করছেন না। এটি হ'ল একটি সাধারণ শ্রেণীর বিভিন্ন গণনা রয়েছে, এটি আরম্ভ করুন এবং এটি ব্যবহার করুন। নুবস ড্রপ-থ্রু (নন-ক্লাস-ভিত্তিক কোড) লেখার প্রবণতা দেখায় এবং শ্রেণিবদ্ধ কার্যকারিতার অভাবকে প্রশস্ত করে তোলার চেষ্টা করে work দয়া করে না? অনুগ্রহ? বীণার জন্য দুঃখিত, আপনার উত্তরের জন্য আপনাকে ধন্যবাদ, তবে আপনি আমার জন্য হট-বোতামটি চাপলেন।
কেভিন জে রাইস

কোড পর্যালোচনা করার জন্য এটি যদি আমার কাছে টানার অনুরোধ হিসাবে উপস্থিত হয় তবে আমি এটিতে -1 হব এবং তাই আমি এটি অজগর হিসাবেও -1 হব।
টেকড্রাগন

চতুর। নির্বোধ, কিন্তু সুন্দর। :) আমি মাঝে মাঝে ফাংশন বৈশিষ্ট্যটি কিছু মনে করি না তবে তারা পাইথন কোডটিতে এমন একটি বিরল জিনিস যে আমি যদি এটি ব্যবহার করতে চাই তবে আমি এটি স্পষ্টভাবে করব না, বরং এটি কোনও সজ্জনকারীর নীচে লুকিয়ে রাখি।
পিএম 2Ring
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.