سؤال

في C# يوجد عامل الدمج الخالي (مكتوب ك ??) الذي يسمح بالتحقق السهل (القصير) من القيمة الفارغة أثناء المهمة:

string s = null;
var other = s ?? "some default value";

هل هناك ما يعادل بيثون؟

أعلم أنه يمكنني القيام بما يلي:

s = None
other = s if s else "some default value"

ولكن هل هناك طريقة أقصر (حيث لا أحتاج إلى التكرار s)?

هل كانت مفيدة؟

المحلول

other = s or "some default value"

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

نلاحظ أن or المشغل لا يعود إلا True أو False.بدلاً من ذلك، تقوم بإرجاع المعامل الأول إذا تم تقييم المعامل الأول إلى صحيح، وتقوم بإرجاع المعامل الثاني إذا تم تقييم المعامل الأول إلى خطأ.

في هذه الحالة التعبير x or y عائدات x اذا كانت True أو يتم تقييمه على أنه صحيح عند تحويله إلى منطقي.وإلا فإنه يعود y.في معظم الحالات، سيخدم هذا نفس الغرض من عامل الدمج الفارغ لـ C♯، لكن ضع في اعتبارك:

42    or "something"    # returns 42
0     or "something"    # returns "something"
None  or "something"    # returns "something"
False or "something"    # returns "something"
""    or "something"    # returns "something"

إذا كنت تستخدم المتغير الخاص بك s للاحتفاظ بشيء يكون إما إشارة إلى مثيل الفصل الدراسي أو None (طالما أن صفك لا يحدد الأعضاء __nonzero__() و __len__())، من الآمن استخدام نفس الدلالات مثل عامل الدمج الفارغ.

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

في بعض اللغات يشار إلى هذا السلوك باسم عامل الفيس.

نصائح أخرى

بشكل صارم،

other = s if s is not None else "default value"

خلاف ذلك، s = False سيصبح "default value", ، وهو ما قد لا يكون هو المقصود.

إذا كنت تريد أن تجعل هذا أقصر، حاول:

def notNone(s,d):
    if s is None:
        return d
    else:
        return s

other = notNone(s, "default value")

إليك دالة ستعيد الوسيطة الأولى التي ليست كذلك None:

def coalesce(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

# Prints "banana"
print coalesce(None, "banana", "phone", None)

reduce() قد يتكرر بلا داعٍ على جميع الوسائط حتى لو لم تكن الحجة الأولى كذلك None, ، لذا يمكنك أيضًا استخدام هذا الإصدار:

def coalesce(*arg):
  for el in arg:
    if el is not None:
      return el
  return None

أدرك أن هذا قد تمت الإجابة عليه، ولكن هناك خيار آخر عندما تتعامل مع الأشياء.

إذا كان لديك كائن قد يكون:

{
   name: {
      first: "John",
      last: "Doe"
   }
}

يمكنك استخدام:

obj.get(property_name, value_if_null)

يحب:

obj.get("name", {}).get("first", "Name is missing") 

بإضافة {} كقيمة افتراضية، إذا كان "الاسم" مفقودًا، فسيتم إرجاع كائن فارغ وتمريره إلى الحصول التالي.هذا مشابه لـ null-safe-navigation في C#، والذي قد يكون كذلك obj?.name?.first.

بالإضافة إلى إجابة Juliano حول سلوك "أو": انها "سريعة" giveacodicetagpre.

لذلك في بعض الأحيان قد يكون اختصار مفيد للأشياء مثل giveacodicetagpre.

بخصوص الإجابات @هيو بوثويل, @mortehu و @glglgl.

إعداد البيانات للاختبار

import random

dataset = [random.randint(0,15) if random.random() > .6 else None for i in range(1000)]

تحديد تطبيقات

def not_none(x, y=None):
    if x is None:
        return y
    return x

def coalesce1(*arg):
  return reduce(lambda x, y: x if x is not None else y, arg)

def coalesce2(*args):
    return next((i for i in args if i is not None), None)

إجراء اختبار وظيفة

def test_func(dataset, func):
    default = 1
    for i in dataset:
        func(i, default)

النتائج على ماك i7 @2.7 Ghz باستخدام بايثون 2.7

>>> %timeit test_func(dataset, not_none)
1000 loops, best of 3: 224 µs per loop

>>> %timeit test_func(dataset, coalesce1)
1000 loops, best of 3: 471 µs per loop

>>> %timeit test_func(dataset, coalesce2)
1000 loops, best of 3: 782 µs per loop

بوضوح not_none وظيفة إجابات OP سؤال بشكل صحيح يعالج "falsy" المشكلة.بل هو أيضا أسرع وأسهل للقراءة.إذا كان تطبيق المنطق في كثير من الأماكن ، فمن الواضح أن أفضل طريقة للذهاب.

إذا كان لديك مشكلة حيث كنت ترغب في العثور على 1 قيمة غير فارغة في iterable ، ثم @mortehu رد هو الطريق للذهاب.وإنما هو الحل مشكلة مختلفة من العملية ، على الرغم من أنه يمكن جزئيا التعامل مع هذه الحالة.لا تأخذ iterable و القيمة الافتراضية.الحجة الأخيرة أن تكون القيمة الافتراضية عاد ولكنك لن تكون عابرة في iterable في هذه الحالة فضلا عن أنها ليست صريحة في أن الحجة الأخيرة هي الافتراضية إلى قيمة.

ثم هل يمكن القيام أدناه ، ولكن كنت لا تزال تستخدم not_null على قيمة واحدة في حالة استخدام.

def coalesce(*args, **kwargs):
    default = kwargs.get('default')
    return next((a for a in arg if a is not None), default)
Python has a get function that its very useful to return a value of an existent key, if the key exist;
if not it will return a default value.

def main():
    names = ['Jack','Maria','Betsy','James','Jack']
    names_repeated = dict()
    default_value = 0

    for find_name in names:
        names_repeated[find_name] = names_repeated.get(find_name, default_value) + 1

if you cannot find the name inside the dictionary, it will return the default_value, if the name exist then it will add any existing value with 1.

hope this can help

The two functions below I have found to be very useful when dealing with many variable testing cases.

def nz(value, none_value, strict=True):
    ''' This function is named after an old VBA function. It returns a default
        value if the passed in value is None. If strict is False it will
        treat an empty string as None as well.

        example:
        x = None
        nz(x,"hello")
        --> "hello"
        nz(x,"")
        --> ""
        y = ""   
        nz(y,"hello")
        --> ""
        nz(y,"hello", False)
        --> "hello" '''

    if value is None and strict:
        return_val = none_value
    elif strict and value is not None:
        return_val = value
    elif not strict and not is_not_null(value):
        return_val = none_value
    else:
        return_val = value
    return return_val 

def is_not_null(value):
    ''' test for None and empty string '''
    return value is not None and len(str(value)) > 0
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top