سؤال

في ما يلي طريقة التعاريف ماذا * و ** هل من أجل param2?

def foo(param1, *param2):
def bar(param1, **param2):
هل كانت مفيدة؟

المحلول

على *args و **kwargs هو لغة مشتركة تسمح التعسفي عدد من الحجج وظائف كما هو موضح في القسم أكثر على تحديد المهام في بيثون الوثائق.

على *args سوف أعطيك كل المعلمات وظيفة كما tuple:

In [1]: def foo(*args):
   ...:     for a in args:
   ...:         print a
   ...:         
   ...:         

In [2]: foo(1)
1


In [4]: foo(1,2,3)
1
2
3

على **kwargs سوف أعطيك كل الكلمة الحجج باستثناء تلك المقابلة معلمة رسمية القاموس.

In [5]: def bar(**kwargs):
   ...:     for a in kwargs:
   ...:         print a, kwargs[a]
   ...:         
   ...:         

In [6]: bar(name='one', age=27)
age 27
name one

كل التعابير يمكن أن تكون مختلطة مع العادي الحجج للسماح مجموعة من ثابت وبعضها متغير الحجج:

def foo(kind, *args, **kwargs):
   pass

آخر استخدام *l لغة هو فك حجة قوائم عند استدعاء دالة.

In [9]: def foo(bar, lee):
   ...:     print bar, lee
   ...:     
   ...:     

In [10]: l = [1,2]

In [11]: foo(*l)
1 2

في بيثون 3 فمن الممكن استخدام *l على الجانب الأيسر من مهمة (تمديد Iterable تفريغ) ، على الرغم من أنه يعطي قائمة بدلا من tuple في هذا السياق:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

أيضا بيثون 3 يضيف الجديد الدلالي (راجع بيب 3102):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

هذه الدالة يقبل سوى 3 الموضعية الحجج و كل شيء بعد * يمكن فقط تمرير الكلمة الحجج.

نصائح أخرى

ومن الجدير بالذكر أيضا أنه يمكنك استخدام * و ** عند الاتصال والمهام.هذا هو الاختصار الذي يسمح لك لتمرير حجج متعددة إلى وظيفة مباشرة باستخدام إما قائمة/tuple أو القاموس.على سبيل المثال, إذا كان لديك الدالة التالية:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

يمكنك أن تفعل أشياء مثل:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

ملاحظة:المفاتيح في mydict يجب أن يكون اسمه بالضبط مثل المعلمات من وظيفة foo.وإلا فإنه سوف رمي TypeError:

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'

واحد * يعني أنه لا يمكن أن يكون أي عدد إضافي الموضعية الحجج. foo() يمكن الاحتجاج بها مثل foo(1,2,3,4,5).في جسم فو() param2 هو سلسلة تحتوي 2-5.

مزدوج ** يعني يمكن أن يكون هناك أي عدد إضافي يدعى المعلمات. bar() يمكن الاحتجاج بها مثل bar(1, a=2, b=3).في جسم بار() param2 هو قاموس يحتوي {"أ": 2, "ب": 3 }

مع التعليمات البرمجية التالية:

def foo(param1, *param2):
    print(param1)
    print(param2)

def bar(param1, **param2):
    print(param1)
    print(param2)

foo(1,2,3,4,5)
bar(1,a=2,b=3)

الإخراج هو

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

ماذا ** (النجم المزدوج) ، * (نجم) هل معلمات

أنها تسمح المهام المحددة لقبول و المستخدمين لتمرير أي عدد من الحجج ، الموضعية (*) و كلمة (**).

تحديد المهام

*args يسمح لأي عدد من اختياري الموضعية الحجج (المعلمات) ، والتي سيتم تعيين tuple اسمه args.

**kwargs يسمح لأي عدد من اختياري الكلمة الحجج (المعلمات) ، والتي سوف تكون في ديكت اسمه kwargs.

يمكنك (ويجب) اختيار أي اسم مناسب ، ولكن إذا كان القصد هو حجج غير محددة دلالات ، args و kwargs هي الأسماء القياسية.

التوسع تمرير أي عدد من الحجج

يمكنك أيضا استخدام *args و **kwargs إلى تمرير المعلمات من القوائم (أو أي iterable) و dicts (أو أي رسم الخرائط) ، على التوالي.

وظيفة استلام المعلمات ليس من الضروري أن نعرف أن يجري توسيعها.

على سبيل المثال ، بيثون 2 xrange لا صراحة أتوقع *args, ولكن نظرا لأنه يأخذ 3 الصحيحه كما الحجج:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

وكمثال آخر, يمكننا استخدام ديكت التوسع في str.format:

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

الجديد في بيثون 3:تحديد المهام مع الكلمة فقط الحجج

هل يمكن أن يكون الكلمة الوحيدة الحجج بعد *args - على سبيل المثال ، هنا ، kwarg2 يجب أن تعطى الكلمة حجة - لا positionally:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

الاستخدام:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

أيضا ، * يمكن استخدامها من قبل نفسها تشير إلى أن الكلمة فقط الحجج متابعة ، دون السماح غير محدود الموضعية الحجج.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

هنا ، kwarg2 مرة أخرى يجب أن يكون اسمه صراحة ، الكلمة الحجة:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

ونحن لا نقبل غير محدود الموضعية الحجج لأننا لا نملك *args*:

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

مرة أخرى, ببساطة أكثر, نحن هنا تتطلب kwarg يعطى عن طريق الاسم, لا positionally:

def bar(*, kwarg=None): 
    return kwarg

في هذا المثال نرى أن لو كنا في محاولة لتمرير kwarg positionally ، ونحن على خطأ:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

يجب علينا صراحة تمرير kwarg المعلمة الكلمة الحجة.

>>> bar(kwarg='kwarg')
'kwarg'

بيثون 2 متوافق العروض

*args (عادة ما قال "نجوم-وسائط") ، **kwargs (النجوم يمكن أن يكون ضمنيا بالقول "kwargs" ، ولكن كن صريح مع "مزدوجة نجوم kwargs") هي التعابير المشتركة من بيثون استخدام * و ** التدوين.هذه أسماء المتغيرات ليست المطلوبة (على سبيل المثالهل يمكن استخدام *foos و **bars) ، ولكن خروجا من الاتفاقية من المرجح أن تثير غضب زملائك الثعبان المبرمجون.

ونحن عادة استخدام هذه عندما لا نعرف ما هي وظيفة سوف تتلقى أو كيف العديد من الحجج التي قد تكون عابرة ، وأحيانا حتى عند تسمية كل متغير على حدة سوف تحصل فوضوي جدا و المكرر (ولكن هذا هو حال عادة صريحة أفضل من ضمني).

مثال 1

الدالة التالية توضح كيف يمكن استخدامها يدل على السلوك.ملاحظة اسمه b الحجة سوف يستهلك الثانية الموضعية الحجة من قبل :

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

يمكننا التحقق من التعليمات الفورية للحصول على وظيفة التوقيع ، help(foo), الذي يخبرنا

foo(a, b=10, *args, **kwargs)

دعونا استدعاء هذه الدالة مع foo(1, 2, 3, 4, e=5, f=6, g=7)

الذي يطبع:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

مثال 2

يمكننا أيضا استدعاء باستخدام وظيفة أخرى ، إلى التي نحن نقدم فقط a:

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) طباعة:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

مثال 3:الاستخدام العملي في الديكور

ربما نحن لا نرى فائدة حتى الآن.لذا تخيل أن لديك العديد من المهام مع رمز زائدة عن الحاجة قبل و/أو بعد التفريق رمز.التالية اسمه الوظائف هي فقط الزائفة رمز لأغراض توضيحية.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

ونحن قد تكون قادرة على التعامل مع هذا بشكل مختلف, ولكن بالتأكيد يمكننا استخراج التكرار مع الديكور و لذلك لدينا المثال أدناه يوضح كيفية *args و **kwargs يمكن أن تكون مفيدة جدا:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

والآن كل ملفوفة وظيفة يمكن كتابة أكثر وضوحا ، كما قد يؤخذ من التكرار:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

و العوملة لدينا قانون ، *args و **kwargs يسمح لنا أن نفعل نحن الحد من الأسطر من التعليمات البرمجية ، تحسين القراءة و الصيانة و الوحيد الكنسي مواقع المنطق في برنامجنا.إذا نحن بحاجة إلى تغيير أي جزء من هذا الهيكل ، لدينا مكان واحد في كل تغيير.

دعونا نفهم أولا ما هي الموضعية الحجج الكلمة الحجج.وفيما يلي مثال على تعريف الدالة مع الموضعية الحجج.

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

لذلك هذا هو تعريف الدالة مع الموضعية الحجج.يمكنك أن تتصل مع الكلمة/اسمه الحجج أيضا:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

الآن دعونا دراسة مثال على تعريف الدالة مع الكلمة الحجج:

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

يمكنك استدعاء هذه الدالة مع الموضعية الحجج أيضا:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

نحن الآن نعرف تعريفات الدالة مع الموضعية فضلا عن الكلمات الرئيسية الحجج.

الآن دعونا دراسة '*' المشغل '**' المشغل.

يرجى ملاحظة أن هذه الشركات يمكن أن تستخدم في 2 مجالات:

أ) استدعاء دالة

ب) تعريف الدالة

استخدام '*' المشغل '**' المشغل في استدعاء دالة.

دعونا الحصول على التوالي على سبيل المثال ومن ثم مناقشته.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

لذلك تذكر

عندما '*' أو '**' المشغل يستخدم في استدعاء دالة -

'*' المشغل بفك بنية البيانات مثل قائمة أو tuple إلى الحجج اللازمة من خلال وظيفة التعريف.

'**' المشغل بفك القاموس إلى الحجج اللازمة من خلال وظيفة التعريف.

الآن دعونا دراسة '*' المشغل استخدام في تعريف الدالة.على سبيل المثال:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

في وظيفة تعريف إن '*' المشغل حزم تلقى الحجج في tuple.

الآن دعونا نرى مثالا '**' المستخدمة في تعريف الدالة:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

في وظيفة تعريف إن '**' المشغل حزم تلقى الحجج في القاموس.

لذلك تذكر:

في استدعاء دالة إن '*' بفك هيكل البيانات من المجموعة أو القائمة في الموضعية أو الكلمة الحجج التي سترد من خلال وظيفة التعريف.

في استدعاء دالة إن '**' بفك هيكل البيانات من القاموس في الموضعية أو الكلمة الحجج التي سترد من خلال وظيفة التعريف.

في تعريف الدالة إن '*' حزم الموضعية الحجج في tuple.

في تعريف الدالة إن '**' حزم الكلمة الحجج في القاموس.

* و ** خاصة في استخدام وظيفة الحجة قائمة. * يعني أن الحجة قائمة ، ** يعني أن الحجة هو القاموس.هذا يسمح وظائف اتخاذ عدد التعسفي من الحجج

في حين يستخدم النجم/تنبيه مشغلي توسيع في بيثون 3, أحب الجدول التالي حيث صلته استخدام هذه الشركات مع وظائف.الضجة المشغل(s) يمكن استخدامها على حد سواء من خلال وظيفة البناء و من خلال وظيفة الاتصال:

            In function construction         In function call
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

هذا حقا فقط يعمل على تلخيص Lorin Hochstein هو الجواب ولكن أجد أنه من المفيد.

لأولئك منكم الذين يتعلمون من خلال الأمثلة!

  1. الغرض من * هو أن تعطي لك القدرة على تحديد وظيفة التي يمكن أن تتخذ عدد التعسفي من الحجج المقدمة قائمة (على سبيل المثال f(*myList) ).
  2. الغرض من ** هو أن تعطيك القدرة على إطعام وظيفة حجج من خلال توفير قاموس (مثلا ، f(**{'x' : 1, 'y' : 2}) ).

دعونا نظهر هذا عن طريق تحديد وظيفة أن يأخذ اثنين من متغيرات طبيعية x, y, و يمكن أن تقبل المزيد من الحجج myArgs, و يمكن أن تقبل المزيد من الحجج myKW.في وقت لاحق سوف تظهر كيفية تغذية y باستخدام myArgDict.

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

المحاذير

  1. ** هو حصرا القواميس.
  2. غير الاختياري حجة الاحالة يحدث أولا.
  3. لا يمكنك استخدام غير اختياري الحجة مرتين.
  4. إذا أمكن ، ** يجب أن تأتي بعد *, دائما.

من بيثون الوثائق:

إذا كان هناك أكثر الموضعية الحجج من هناك معلمة رسمية فتحات ، TypeError "الاستثناء" إلا معلمة رسمية باستخدام بناء الجملة "*معرف" هو الحاضر ؛ في هذه الحالة, أن معلمة رسمية يتلقى tuple تحتوي الزائدة الموضعية الحجج (أو فارغة tuple إذا ما كان هناك فائض الموضعية الحجج).

إذا كان أي الكلمة الحجة لا تتوافق مع معلمة رسمية الاسم ، TypeError "الاستثناء" إلا معلمة رسمية باستخدام بناء الجملة "**المعرف" هو الحاضر ؛ في هذه الحالة, أن معلمة رسمية يتلقى قاموس يحتوي الزائدة الكلمة الحجج (باستخدام الكلمات الرئيسية مفاتيح الحجة القيم المقابلة القيم) ، أو (جديد) فارغة القاموس إذا ما كان هناك فائض الكلمة الحجج.

في بيثون 3.5, يمكنك أيضا استخدام بناء الجملة هذا في list, dict, tuple, ، set يعرض (كما تسمى أحيانا حرفية).انظر بيب 488:إضافية تفريغ التعميمات.

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

كما يسمح متعددة iterables أن يكون مفتوح في وظيفة واحدة المكالمة.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(شكرا إلى mgilson عن بيب الرابط.)

أريد أن أعطي مثال الآخرين لم يذكر

* يمكن أيضا فك مولد

مثال من Python3 الوثيقة

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x سيكون [1, 2, 3], unzip_y سيكون [4, 5, 6]

البريدي() يتلقى متعددة iretable وسائط, والعودة مولد.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

بالإضافة إلى وظيفة المكالمات *وسائط و **kwargs مفيدة في الطبقة الهرمية و أيضا تجنب الحاجة إلى كتابة __init__ طريقة في بيثون.استخدام مماثل يمكن ملاحظته في أطر مثل Django رمز.

على سبيل المثال ،

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

فئة فرعية يمكن أن تكون ثم

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

فرعية ثم إنشاء مثيل كما

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

كما فرعية مع سمة جديدة الأمر الذي يجعل الشعور فقط إلى أن فئة فرعية سبيل المثال يمكن أن نطلق قاعدة الطبقة __init__ افراغ سمات الإعداد.ويتم ذلك من خلال *وسائط و **kwargs.kwargs تستخدم أساسا بحيث رمز للقراءة باستخدام اسمه الحجج.على سبيل المثال ،

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

والتي يمكن instatiated كما

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '$6.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

رمز كاملة هنا

* يعني تلقي متغير الحجج القائمة

** يعني تلقي متغير الحجج القاموس

تستخدم مثل التالية:

1) واحد *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

الإخراج:

two
3

2) الآن **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

الإخراج:

dic1 two
dic2 3

مثال جيد لاستخدام سواء في الوظيفة:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}

هذا المثال سوف تساعدك على تذكر *args, **kwargs وحتى super والميراث في بيثون في آن واحد.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1

TL;DR

وحزم الوسيطات التي تم تمريرها إلى الدالة في list و dict على التوالي داخل الجسم وظيفة.عند تعريف دالة توقيع مثل هذا:

def func(*args, **kwds):
    # do stuff

يمكن أن يطلق عليه مع أي عدد من الحجج الكلمة الحجج.غير الكلمة الحجج الحصول على معبأة في قائمة تسمى args داخل الجسم وظيفة و الكلمة الحجج الحصول على معبأة في ديكت يسمى kwds داخل الدالة الجسم.

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

الآن داخل الجسم وظيفة ، عندما يتم استدعاء الدالة, هناك نوعان من المتغيرات المحلية ، args وهي قائمة بعد القيمة ["this", "is a list of", "non-keyword", "arguments"] و kwds وهو dict وجود قيمة {"keyword" : "ligma", "options" : [1,2,3]}


هذا يعمل أيضا في الاتجاه المعاكس ، أيمن المتصل الجانب.على سبيل المثال إذا كان لديك وظيفة محددة مثل:

def f(a, b, c, d=1, e=10):
    # do stuff

يمكنك أن تتصل مع طريق تفريغ iterables أو تعيينات في الدعوة-نطاق:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

*args و **kwargs:تسمح لك لتمرير عدد متغير من الحجج إلى وظيفة.

*args:يستخدم لإرسال غير keyworded طول متغير حجة قائمة إلى الدالة:

def args(normal_arg, *argv):
    print("normal argument:", normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals', 'fish', 'duck', 'bird')

سوف تنتج:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs يسمح لك لتمرير keyworded طول متغير من الحجج إلى وظيفة.يجب عليك استخدام **kwargs إذا كنت ترغب في التعامل مع اسمه الحجج في وظيفة.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print("Your %s is %s." % (key, value))

who(name="Nikola", last_name="Tesla", birthday="7.10.1856", birthplace="Croatia")  

سوف تنتج:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
  • def foo(param1, *param2): هو أسلوب لا يمكن أن يقبل عدد التعسفي من القيم *param2,
  • def bar(param1, **param2): هو أسلوب لا يمكن أن يقبل عدد التعسفي من القيم مع مفاتيح *param2
  • param1 هو بسيط المعلمة.

على سبيل المثال ، بناء الجملة من أجل تنفيذ varargs في جافا على النحو التالي:

accessModifier methodName(datatype… arg) {
    // method body
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top