python - هل لدى بايثون مشغل شرطي ثلاثي؟


إذا لم يكن لدى بايثون مشغل شرطي ثلاثي، فهل من الممكن محاكاة واحدة باستخدام منشآت لغة أخرى؟



Answers



نعم، تمت إضافته في الإصدار 2.5.
بناء الجملة هو:

a if condition else b

يتم تقييم condition الأول، ثم يتم إرجاع a أو b استنادا إلى قيمة منطقية condition
إذا تم تقييم condition إلى ترو يتم إرجاع، وإلا يتم إرجاع b .

فمثلا:

>>> 'true' if True else 'false'
'true'
>>> 'true' if False else 'false'
'false'

نضع في اعتبارنا أنه قد غضب من قبل بعض بيثونيستاس لعدة أسباب:

  • ترتيب الحجج يختلف عن العديد من اللغات الأخرى (مثل C، روبي، جافا، الخ)، والتي قد تؤدي إلى الخلل عندما يكون الناس غير مألوف مع سلوك بايثون "المستغرب" استخدامه (قد عكس الترتيب).
  • يجد البعض أنه "غير عملي"، لأنه يذهب يتعارض مع التدفق الطبيعي للفكر (التفكير في الحالة أولا ثم الآثار).
  • الأسباب الأسلوبية.

إذا كنت تواجه مشكلة في تذكر النظام، ثم تذكر أنه إذا كنت تقرأ بصوت عال، وكنت (تقريبا) يقول ما تقصده. على سبيل المثال، x = 4 if b > 8 else 9 تمت قراءة x = 4 if b > 8 else 9 بصوت عال حيث أن x will be 4 if b is greater than 8 otherwise 9 .

الوثائق الرسمية:




يمكنك فهرسة إلى مجموعة:

(falseValue, trueValue)[test]

يحتاج test للعودة صواب أو خطأ .
قد يكون أكثر أمانا لتنفيذها دائما على النحو التالي:

(falseValue, trueValue)[test == True]

أو يمكنك استخدام bool() المدمج في bool() لضمان قيمة منطقية :

(falseValue, trueValue)[bool(<expression>)]



بالنسبة للإصدارات السابقة ل 2.5، هناك خدعة:

[expression] and [on_true] or [on_false]

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

1. هل هناك ما يعادل C؟؟: "المشغل الثلاثي؟




expression1 إذا حالة أخرى التعبير 2

>>> a = 1
>>> b = 2
>>> 1 if a > b else -1 
-1
>>> 1 if a > b else -1 if a < b else 0
-1



من الوثائق :

التعبيرات الشرطية (التي تسمى أحيانا "مشغل ثلاثي") لها الأولوية الدنيا لجميع عمليات بايثون.

التعبير x if C else y أولا يقيم الشرط، C ( ليس x )؛ إذا كان C صحيحا، يتم تقييم x ويتم إرجاع قيمته؛ وإلا، يتم تقييم y ويتم إرجاع قيمته.

انظر بيب 308 للحصول على مزيد من التفاصيل حول التعبيرات المشروطة.

جديد منذ الإصدار 2.5.




تمت إضافة مشغل للتعبير المشروط في بيثون في عام 2006 كجزء من اقتراح تحسين بايثون 308 . شكله يختلف عن المشترك ?: المشغل وانها:

<expression1> if <condition> else <expression2>

وهو ما يعادل:

if <condition>: <expression1> else: <expression2>

هنا مثال:

result = x if a > b else y

بناء الجملة الأخرى التي يمكن استخدامها (متوافقة مع الإصدارات قبل 2.5):

result = (lambda:y, lambda:x)[a > b]()

حيث يتم تقييم العمليات بهدوء .

طريقة أخرى هي عن طريق فهرسة تيوبل (التي لا تتفق مع المشغل الشرطي لمعظم اللغات الأخرى):

result = (y, x)[a > b]

أو بناء القاموس صراحة:

result = {True: x, False: y}[a > b]

طريقة أخرى (أقل موثوقية)، ولكن أبسط هي استخدام and و or المشغلين:

result = (a > b) and x or y

ولكن هذا لن يعمل إذا كان x سيكون False .

الحل البديل هو جعل x و y القوائم أو تيوب كما في ما يلي:

result = ((a > b) and [x] or [y])[0]

أو:

result = ((a > b) and (x,) or (y,))[0]

إذا كنت تعمل مع القواميس، بدلا من استخدام الشرطي الثلاثي، يمكنك الاستفادة من get(key, default) ، على سبيل المثال:

shell = os.environ.get('SHELL', "/bin/sh")

المصدر: ؟: في بيثون في ويكيبيديا




@فوق:

لسوء الحظ، ال

(falseValue, trueValue)[test]

الحل ليس لديها دائرة قصر السلوك؛ وبالتالي يتم تقييم كل من فالسفالو و ترويفالو بغض النظر عن الشرط. هذا يمكن أن يكون دون المستوى الأمثل أو حتى عربات التي تجرها الدواب (أي كل من ترويفالو و فالسفالو يمكن أن تكون أساليب ولها آثار جانبية).

وسيكون أحد الحلول لهذا

(lambda: falseValue, lambda: trueValue)[test]()

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

وهكذا فإن القصة تذهب - اختيار بين 3 الحلول المذكورة هو مفاضلة بين وجود ميزة قصر الدائرة، وذلك باستخدام على الأقل الثعبان 2.5 (إمهو ليست مشكلة بعد الآن) وعدم التعرض لل "ترويفالو-يقيم إلى الكاذبة" أخطاء.




ل بيثون 2.5 وأحدث هناك بنية محددة:

[on_true] if [cond] else [on_false]

في بيثونس القديمة لا يتم تنفيذ مشغل الثلاثي ولكن من الممكن لمحاكاة ذلك.

cond and on_true or on_false

على الرغم من ذلك، هناك مشكلة محتملة، والتي إذا cond يقيم ل True و on_true يقيم إلى False ثم يتم إرجاع on_true بدلا من on_true . إذا كنت تريد هذا السلوك الطريقة على ما يرام، وإلا استخدام هذا:

{True: on_true, False: on_false}[cond is True] # is True, not == True

والتي يمكن أن تكون ملفوفة من قبل:

def q(cond, on_true, on_false)
    return {True: on_true, False: on_false}[cond is True]

واستخدمت هذه الطريقة:

q(cond, on_true, on_false)

وهو متوافق مع جميع إصدارات بيثون.




قد تجد في كثير من الأحيان

cond and on_true or on_false

ولكن هذا يؤدي إلى مشكلة عندما on_true == 0

>>> x = 0
>>> print x == 0 and 0 or 1 
1
>>> x = 1
>>> print x == 0 and 0 or 1 
1

حيث كنت تتوقع لمشغل الثلاثي العادي هذه النتيجة

>>> x = 0
>>> print 0 if x == 0 else 1 
0
>>> x = 1
>>> print 0 if x == 0 else 1 
1



الثلاثي المشغل في لغات البرمجة المختلفة

هنا أنا مجرد محاولة لإظهار بعض الفرق المهم في ternary operator بين اثنين من لغات البرمجة.

مشغل ثلاثي في ​​جافاسكريبت

var a = true ? 1 : 0;
# 1
var b = false ? 1 : 0;
# 0

المشغل الثلاثي في ​​روبي

a = true ? 1 : 0
# 1
b = false ? 1 : 0
# 0

المشغل الثلاثي في ​​سكالا

val a = true ? 1 | 0
# 1
val b = false ? 1 | 0
# 0

المشغل الثلاثي في ​​البرمجة R

a <- if (TRUE) 1 else 0
# 1
b <- if (FALSE) 1 else 0
# 0

المشغل الثلاثي في ​​بيثون

a = 1 if True else 0
# 1
b = 1 if False else 0
# 0

الآن يمكنك ان ترى جمال لغة الثعبان. وقراءة عالية وقابلة للحفظ.




تماما، وأنه من السهل بشكل لا يصدق أن نفهم.

general syntax : first_expression if bool_expression_is_true else second_expression

Example: x= 3 if 3 > 2 else 4 
# assigns 3 to x if the boolean expression evaluates to true or 4 if it is false



هل لدى بايثون مشغل شرطي ثلاثي؟

نعم فعلا. من الملف النحوي :

test: or_test ['if' or_test 'else' test] | lambdef

الجزء من الاهتمام هو:

or_test ['if' or_test 'else' test]

لذلك، فإن عملية مشروطة ثلاثية هي من الشكل التالي:

expression1 if expression2 else expression3

expression3 سيتم تقييمها بهدوء (أي، يتم تقييمها فقط إذا كان expression2 خاطئة في سياق منطقي). وبسبب التعريف المتكرر، يمكنك تسلسلها إلى أجل غير مسمى (على الرغم من أنها قد تعتبر أسلوب سيء.)

expression1 if expression2 else expression3 if expression4 else expression5 # and so on

ملاحظة حول الاستخدام:

لاحظ أن كل if يجب أن يتبع مع else . قد يجد الناس مفاهيم قائمة التعلم وتعبيرات المولدات هذا درسا صعبا للتعلم - ما يلي لن يعمل، حيث تتوقع بيثون تعبيرا ثالثا عن آخر:

[expression1 if expression2 for element in iterable]
#                          ^-- need an else here

الذي يثير SyntaxError: invalid syntax . وبالتالي فإن ما سبق هو إما قطعة غير مكتملة من المنطق (ربما يتوقع المستخدم عدم وجود أي خطأ في الشرط الكاذب) أو ما قد يكون المقصود هو استخدام التعبير 2 كفلتر - تلاحظ أن ما يلي هو بيثون قانوني:

[expression1 for element in iterable if expression2]

expression2 يعمل كمرشح لفهم القائمة، وليس عامل شرطي ثلاثي.

بنية بديلة لحالة أكثر ضيقا:

قد تجد أنه من المؤلم إلى حد ما كتابة ما يلي:

expression1 if expression1 else expression2

expression1 يجب أن يتم تقييم مرتين مع استخدام أعلاه. ويمكن أن تحد من التكرار إذا كان مجرد متغير محلي. ومع ذلك، فإن لغة بيثونيك الشائعة والأداء لهذا الاستخدام هو استخدام سلوك الاختصار or :

expression1 or expression2

وهو ما يعادل في الدلالات. لاحظ أن بعض أدلة الأسلوب قد تحد من هذا الاستخدام على أساس الوضوح - فإنه لا حزمة الكثير من المعنى في بناء الجملة قليلا جدا.




محاكاة المشغل الثلاثي الثعبان.

فمثلا

a, b, x, y = 1, 2, 'a greather than b', 'b greater than a'
result = (lambda:y, lambda:x)[a > b]()

انتاج:

'b greater than a'



In [1]: a = 1 if False else 0

In [2]: a
Out[2]: 0

In [3]: b = 1 if True else 0

In [4]: b
Out[4]: 1



أكثر من تلميح من إجابة (لا تحتاج إلى تكرار واضح للوقت هوندريث)، ولكن أنا أحيانا استخدامه بمثابة اختصار أونيلينر في هذه التشييدات:

if conditionX:
    print('yes')
else:
    print('nah')

، يصبح:

print('yes') if conditionX else print('nah')

بعض (العديد :) قد عبوس عليه كما أونبيثونيك (حتى، روبي العش :)، ولكن أنا شخصيا العثور عليه أكثر طبيعية - أي كيف كنت التعبير عن ذلك بشكل طبيعي، بالإضافة إلى أكثر قليلا جذابة بصريا في كتل كبيرة من التعليمات البرمجية.







انت تستطيع فعل ذالك :-

[condition] and [expression_1] or [expression_2] ;

مثال:-

print(number%2 and "odd" or "even")

وهذا من شأنه أن يطبع "الغريب" إذا كان الرقم غريبا أو "حتى" إذا كان عدد حتى.

والنتيجة: - إذا تم تنفيذ الشرط الصحيح exp_1 يتم تنفيذ آخر exp_2.

ملاحظة: - 0، لا شيء، فالس، إمبليليست، إمبسترينغ تقييم كاذبة. وأية بيانات أخرى من 0 يقيم ل ترو.

وإليك كيف يعمل:

إذا كان الشرط [الشرط] يصبح "صحيح" ثم، سيتم تقييم التعبير_1 ولكن ليس التعبير_2. إذا كنا "و" شيء مع 0 (صفر)، فإن النتيجة دائما أن يكون فاسل. حتى في العبارة أدناه،

0 and exp

لن يتم تقييم التعبير إكس على الإطلاق لأن "و" مع 0 سوف تقيم دائما إلى الصفر وليس هناك حاجة لتقييم التعبير. هذه هي الطريقة التي يعمل بها مترجم نفسه، في جميع اللغات.

في

1 or exp

لن يتم تقييم التعبير إكسب على الإطلاق منذ "أو" مع 1 سيكون دائما 1. لذلك لن يكلف نفسه عناء لتقييم التعبير إكس منذ النتيجة ستكون 1 على أي حال. (أساليب الأمثل المترجم).

ولكن في حالة

True and exp1 or exp2

لن يتم تقييم التعبير الثاني True and exp1 أن True and exp1 سيكونان ترو عندما لا يكون إكس 1 فالس.

وبالمثل في

False and exp1 or exp2

لن يتم تقييم التعبير ex1 لأن فالس يعادل الكتابة 0 والقيام "و" مع 0 سيكون 0 نفسها ولكن بعد exp1 منذ استخدام "أو"، سيتم تقييم التعبير EX2 بعد "أو".

ملاحظة: - لا يمكن استخدام هذا النوع من المتفرعات باستخدام "أو" و "و" إلا عندما لا يحتوي التعبير_1 على قيمة تروث من فالس (أو 0 أو نون أو إمبليليست [] أو إمبليسترينغ ''.) لأنه إذا أصبح التعبير_1 خطأ، سيتم تقييم التعبير_2 بسبب وجود "أو" بين exp_1 و exp_2.

في حال كنت لا تزال تريد أن تجعل من العمل لجميع الحالات بغض النظر عن ما exp_1 و exp_2 القيم الحقيقة، القيام بذلك: -

[condition] and ([expression_1] or 1) or [expression_2] ;




نعم فعلا.

>>> b = (True if 5 > 4 else False)
>>> print b
True



هناك خيار ثالث كما هو موضح في إجابات أخرى، ولكن يمكنك أيضا محاكاة ذلك باستخدام "أو" إذا كنت تحقق ضد قيمة منطقية أو لا شيء:

>>> a = False
>>> b = 5
>>> a or b
5

>>> a = None
>>> a or b
5