* আরগস এবং ** কোয়ার্গের সাথে ডিফল্ট আর্গুমেন্ট


87

ইন পাইথন 2.x (আমি 2.7 ব্যবহার করুন), যা সঙ্গে ডিফল্ট আর্গুমেন্ট ব্যবহার করতে সঠিক উপায় *argsএবং **kwargs?
আমি এই বিষয়ের সাথে সম্পর্কিত এসওতে একটি প্রশ্ন পেয়েছি, তবে এটি পাইথন 3 এর জন্য :
* আর্গস, ** কাওয়ার্গস এবং alচ্ছিক / ডিফল্ট যুক্তি দিয়ে পাইথন ফাংশন কল করা

সেখানে তারা বলে যে এই পদ্ধতিটি কাজ করে:

def func(arg1, arg2, *args, opt_arg='def_val', **kwargs):
    #...

2.7, এটা একটা ফলাফল SyntaxError। এই ধরনের ফাংশন সংজ্ঞায়িত করার জন্য কি কোনও প্রস্তাবিত উপায় আছে?
আমি এটি এইভাবে কাজ করতে পেরেছি, তবে আমি অনুমান করতে পারি যে এটির একটি ভাল সমাধান রয়েছে।

def func(arg1, arg2, *args, **kwargs):
    opt_arg ='def_val'
    if kwargs.__contains__('opt_arg'):
        opt_arg = kwargs['opt_arg']
    #...

এখনও সবচেয়ে সংক্ষিপ্ত ব্যাখ্যা আমি জুড়েছি
verbsintransit

4
স্পষ্টভাবে কখনও কল করবেন না __contains__। সর্বদা ব্যবহার in: 'opt_arg' in kwargs। (আরও ভাল: kwargs.get('opt_arg', 'def_val')মিলিগ্রামের উত্তর হিসাবে)।
নিউইনিয়েও

উত্তর:


82

কেবলমাত্র ডিফল্ট যুক্তিগুলি এর আগে রাখুন *args:

def foo(a, b=3, *args, **kwargs):

এখন, bআপনি কীওয়ার্ড আর্গুমেন্ট বা দ্বিতীয় অবস্থানগত আর্গুমেন্ট হিসাবে পাস করলে স্পষ্টভাবে সেট করা হবে।

উদাহরণ:

foo(x) # a=x, b=3, args=(), kwargs={}
foo(x, y) # a=x, b=y, args=(), kwargs={}
foo(x, b=y) # a=x, b=y, args=(), kwargs={}
foo(x, y, z, k) # a=x, b=y, args=(z, k), kwargs={}
foo(x, c=y, d=k) # a=x, b=3, args=(), kwargs={'c': y, 'd': k}
foo(x, c=y, b=z, d=k) # a=x, b=z, args=(), kwargs={'c': y, 'd': k}

মনে রাখবেন যে, বিশেষত, foo(x, y, b=z)কাজ করে না কারণ bসেই ক্ষেত্রে পজিশনে নির্ধারিত হয়েছে।


এই কোডটি পাইথন 3 এও কাজ করে। পাইথন 3- এ ডিফল্ট আর্গ স্থাপনের পরে *args এটি একটি "কীওয়ার্ড-কেবল" যুক্তি তৈরি করে যা কেবলমাত্র নাম দ্বারা নির্দিষ্ট করা যায়, অবস্থান অনুসারে নয়। আপনি যদি পাইথন 2-তে কোনও কী-ওয়ার্ড-যুক্তি চান তবে আপনি @ মিলিগ্রামের সমাধানটি ব্যবহার করতে পারেন।


4
হ্যাঁ, এটি অস্পষ্টতার কারণে *args। আপনি কীওয়ার্ড-কেবল যুক্তি চাইলে আপনার পথটি সঠিক।
নিনেও

এটি উপরের মন্তব্যে উত্তর পেয়েছে। (যদি আমি ফাংশনটিকে একটি ভিন্ন বি দিয়ে কল করতে চাই এবং আমি *

যাইহোক, জিজ্ঞাসার আগে, আমি এই সমাধানটি চেষ্টা করেছিলাম, তবে আমি এটিও খুঁজে পেয়েছি যে কেবলমাত্র অপার_আরগ সংজ্ঞায়িত করার পরে আমি কেবল কুয়ার্গ ব্যবহার করি।

@ ন্ননিও: আমি আপনার উদাহরণগুলি পেয়েছি, তবে লিঙ্কে বর্ণিত হিসাবে পাইথন ৩.x এর মতো একই সময়ে আমাদের একই সময়ে ডিফল্ট যুক্তি এবং * আরগগুলি নির্দিষ্ট করার স্বাধীনতা দেয় না; এটা কি পারে?

4
পূরণ করার সময় আপনি কোনও ডিফল্ট যুক্তি একা রাখতে পারবেন না *args, না। এজন্য কার্যকরীতাটি পাইথন 3-এ যুক্ত করা হয়েছিল সাধারণত, পাইথন 2-এ ডিফল্ট যুক্তিগুলি 0 এর মতো সুস্পষ্ট কিছু হিসাবে নির্দিষ্ট করা হয় Noneযাতে তারা স্পষ্টভাবে পাস করতে পারে
nneonneo

56

অন্যান্য প্রশ্নের বাক্য গঠনটি কেবল পাইথন 3.x এবং মূল শব্দটি কেবল আর্গুমেন্টকে নির্দিষ্ট করে। এটি পাইথন 2.x এ কাজ করে না।

পাইথন টু.এক্স-এর জন্য, আমি popএটি কাওয়ার্গসের বাইরে চাই:

def func(arg1, arg2, *args, **kwargs):
    opt_arg = kwargs.pop('opt_arg', 'def_val')

এটি ডিফল্ট আর্গুমেন্টের আগে * আরগগুলিও নির্দিষ্ট করে।

4

আপনি এই জাতীয় সজ্জা ব্যবহার করতে পারেন:

import functools
def default_kwargs(**defaultKwargs):
    def actual_decorator(fn):
        @functools.wraps(fn)
        def g(*args, **kwargs):
            defaultKwargs.update(kwargs)
            return fn(*args, **defaultKwargs)
        return g
    return actual_decorator

তারপরে কেবল করুন:

@default_kwargs(defaultVar1 = defaultValue 1, ...)
def foo(*args, **kwargs):
    # Anything in here

এই ক্ষেত্রে:

@default_kwargs(a=1)
def f(*args, **kwargs):
    print(kwargs['a']+ 1)

f() # Returns 2
f(3) # Returns 4

1

এটিকে আরও জেনেরিক এবং আরও কমপ্যাক্ট করার চেষ্টা করার সময় আপনার সমাধানের পদ্ধতির খুব কাছাকাছি থাকাকে আমি এই জাতীয় কিছু বিবেচনা করার পরামর্শ দেব:

>>> def func(arg1, arg2, *args, **kwargs):
...     kwargs_with_defaults = dict({'opt_arg': 'def_val', 'opt_arg2': 'default2'}, **kwargs)
...     #...
...     return arg1, arg2, args, kwargs_with_defaults

>>> func('a1', 'a2', 'a3', 'a5', x='foo', y='bar')
('a1', 'a2', ('a3', 'a5'), {'opt_arg2': 'default2', 'opt_arg': 'def_val', 'y': 'bar', 'x': 'foo'})

>>> func('a1', 'a2', 'a3', 'a5', opt_arg='explicit_value', x='foo', y='bar')
('a1', 'a2', ('a3', 'a5'), {'opt_arg2': 'default2', 'opt_arg': 'explicit_value', 'y': 'bar', 'x': 'foo'})

1

@ ইয়্যাককোব এর অনুরূপ পন্থা, তবে পরিষ্কার এবং সংক্ষিপ্ত:

ইন পাইথন 3.5 বা তার অধিক:

def foo(a, b=3, *args, **kwargs):
  defaultKwargs = { 'c': 10, 'd': 12 }
  kwargs = { **defaultKwargs, **kwargs }
  print(a, b, args, kwargs)
  
  # Do something    

foo(1) # 1 3 () {'c': 10, 'd': 12}
foo(1, d=5) # 1 3 () {'c': 10, 'd': 5}
foo(1, 2, 4, d=5) # 1 2 (4,) {'c': 10, 'd': 5}

দ্রষ্টব্য: আপনি পাইথন 2 ব্যবহার করতে পারেন

kwargs = merge_two_dicts(defaultKwargs, kwargs)

ইন পাইথন 3.5

kwargs = { **defaultKwargs, **kwargs }

ইন পাইথন 3.9

kwargs = defaultKwargs | kwargs  # NOTE: 3.9+ ONLY

0

পাইথন ২.x সহ হ্যান্ডেল করার আরেকটি উপায়:

def foo(*args, **kwargs):
    if 'kwarg-name' not in kwargs.keys():
        kwargs['kwarg-name'] = 'kwarg-name-default-value'
    return bar(*args, **kwargs)

এটি *args@ নিওনিওর জবাবের বিপরীতে অন্তর্নিহিত কলটিতে স্বেচ্ছাচারিত হয়ে চলে ।


4
আপনি যদি বৈধ কোড ব্যবহার করেন, তবে এর 'opt_arg'পরিবর্তে < kwarg-name >এবং এর 'def_val'পরিবর্তে< kwarg-name-default-value >
wjandrea

0

এই উত্তরটি ড্যানিয়েল আমরিকো তার পরামর্শের একটি বর্ধিতাংশ ।

এই সাজসজ্জারটি ডিফল্ট কোয়ার্গ মান নির্ধারণ করে যদি সেগুলি কঠোরভাবে সংজ্ঞায়িত না হয়।

from functools import wraps

def force_kwargs(**defaultKwargs):
    def decorator(f):
        @wraps(f)
        def g(*args, **kwargs):
            new_args = {}
            new_kwargs = defaultKwargs
            varnames = f.__code__.co_varnames
            new_kwargs.update(kwargs)
            for k, v in defaultKwargs.items():
                if k in varnames:
                    i = varnames.index(k)
                    new_args[(i, k)] = new_kwargs.pop(k)
            # Insert new_args into the correct position of the args.
            full_args = list(args)
            for i, k in sorted(new_args.keys()):
                if i <= len(full_args):
                    full_args.insert(i, new_args.pop((i, k)))
                else:
                    break
            # re-insert the value as a key-value pair
            for (i, k), val in new_args.items():
                new_kwargs[k] = val
            return f(*tuple(full_args), **new_kwargs)
        return g
    return decorator

ফলাফল

@force_kwargs(c=7)
def f(a, b='B', c='C', d='D', *args, **kw):
    return a, b, c, d, args, kw
#                               a    b  c    d  args      kwargs
f('r')                      # 'r', 'B', 7, 'D',   (),         {}
f(1,2,3)                    #   1,   2, 7,   3,   (),         {}
f(1, 2, 3, b=3, c=9, f='F') #   1,   3, 9,   2, (3,), {'f': 'F'}

বৈকল্পিক

আপনি যদি ফাংশন সংজ্ঞায় লিখিত হিসাবে ডিফল্ট মানগুলি ব্যবহার করতে চান তবে আপনি যুক্তিটি ডিফল্ট মানগুলি ব্যবহার করে অ্যাক্সেস করতে পারেন f.func_defaultsযা ডিফল্ট মানগুলি তালিকাভুক্ত করে। ভেরিয়েবলের নামের সাথে এই ডিফল্ট মানগুলি মেলে zipআপনার শেষের সাথে তাদের থাকতে হবে f.__code__.varnames

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.