python - ماذا يعني مشغل النجمة؟




syntax parameter-passing (4)

أجد هذا مفيدًا بشكل خاص عندما تريد "تخزين" مكالمة وظيفية.

على سبيل المثال ، لنفترض أن لدي بعض اختبارات الوحدة لوظيفة "إضافة":

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

لا توجد طريقة أخرى للاتصال بإضافة ، بخلاف القيام يدويًا بشيء مثل إضافة (اختبار [0] ، اختبار [1]) ، وهو أمر قبيح. أيضا ، إذا كان هناك عدد متغير من المتغيرات ، يمكن أن تحصل على رمز قبيح جدا مع جميع البيانات ، إذا كنت في حاجة.

مكان آخر مفيد هذا هو تعريف كائنات المصنع (الكائنات التي تنشئ كائنات من أجلك). افترض أن لديك بعض مصنع الصف ، الذي يجعل كائنات السيارات ويعيدها. يمكنك أن تجعل من myFactory.make_car ('red' ، 'bmw' ، '335ix') سيارة ('red' ، 'bmw' ، '335ix') ، ثم تقوم بإرجاعها.

def make_car(*args):
   return Car(*args)

هذا مفيد أيضاً عندما تريد استدعاء مُنشئ superclass '.

ممكن تكرار:
ماذا يفعل * arg و ** kwargs يعني؟

ماذا يعني المشغل * في بايثون ، كما هو الحال في الكود مثل zip(*x) أو f(**k) ؟

  1. كيف يتم التعامل داخليا في المترجم؟
  2. هل يؤثر على الأداء على الإطلاق؟ هل هو سريع أم بطيء؟
  3. متى يكون ذلك مفيدًا ومتى لا يكون كذلك؟
  4. هل يجب استخدامه في تصريح الوظيفة أم في المكالمة؟

في استدعاء دالة ، يحول النجم الواحد قائمة إلى حجج منفصلة (على سبيل المثال ، zip(*x) هو نفس zip(x1,x2,x3) إذا كان x=[x1,x2,x3] ) والنجم المزدوج يتحول إلى قاموس إلى وسيطات الكلمة الرئيسية f(x=my_x, y=my_y) (على سبيل المثال f(**k) هي نفس f(x=my_x, y=my_y) إذا كان k = {'x':my_x, 'y':my_y} .

في تعريف الدوال ، يكون العكس هو التالي: يقوم النجم المفرد بتحويل عدد عشوائي من الوسيطات إلى قائمة ، ويؤدي البدء المزدوج إلى تحويل عدد عشوائي من وسيطات الكلمات الرئيسية إلى قاموس. مثال def foo(*x) يعني "foo يأخذ عددًا عشوائيًا من الحجج وسيتم الوصول إليها من خلال القائمة x (أي إذا كان المستخدم يتصل بـ foo(1,2,3) ، x سيكون [1,2,3] ) " def bar(**k) يعني" شريط يأخذ عددًا عشوائيًا من وسيطات الكلمات الرئيسية وسيتم الوصول إليه من خلال القاموس k (أي إذا كان bar(x=42, y=23) المكالمات للمستخدم bar(x=42, y=23) ، سيكون k هو {'x': 42, 'y': 23} ) ".


يطلق عليه بناء الجملة الموسعة. من documentation :

إذا ظهر تعبير * syntax * في استدعاء الدالة ، يجب أن يتم تقييم التعبير إلى تسلسل. عناصر من هذا التسلسل تعامل كما لو كانت حججا موضعية إضافية ؛ إذا كان هناك وسيطات موضعية x1 و ... و xN وعبارات يتم تقييمها إلى y1 تسلسل ، ... ، yM ، هذا يكافئ استدعاء مع الوسيطات الموضعية M + N x1 ، ... ، xN ، y1 ،. .. ، نعم.

و:

في حالة ظهور تعبير صياغة الجملة ** في استدعاء الدالة ، يجب أن يتم تقييم التعبير إلى التعيين ، حيث يتم التعامل مع محتوياته كوسائط كلمات رئيسية إضافية. في حالة ظهور كلمة رئيسية في كل من التعبير وكوسيطة كلمات مفتاحية صريحة ، يظهر استثناء TypeError.


يقوم النجم المفرد * بتفكيك التسلسل / التجميع إلى وسيطات موضعية ، بحيث يمكنك القيام بذلك:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

سيؤدي ذلك إلى فك مجموعة البيانات بحيث يتم تنفيذها فعليًا على النحو التالي:

s = sum(1, 2)

النجم المزدوج ** يفعل نفس الشيء ، فقط باستخدام قاموس ومن ثمَّ يتم ذكره في الوسائط:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

يمكنك أيضًا الجمع بين:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

سوف تنفذ على النحو التالي:

s = sum(1, 2, c=10, d=15)

انظر أيضا القسم 4.7.4 - تفريغ حجة قوائم وثائق بيثون.

بالإضافة إلى ذلك ، يمكنك تحديد وظائف لأخذ وسيطات *x و **y ، وهذا يسمح للوظيفة بقبول أي عدد من الوسيطات الموضعية و / أو المسماة التي لم يتم تسميتها بشكل محدد في التعريف.

مثال:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

أو مع ** :

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

هذا يمكن أن يسمح لك بتحديد عدد كبير من المعلمات الاختيارية دون الحاجة إلى إعلانها.

ومرة أخرى ، يمكنك الجمع بين:

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15




kwargs