حدد عنصر واحد من مجموعة :بيثون
سؤال
أنا خلقت وظيفة الأداة العودة المتوقعة بند واحد من مولد التعبير
print one(name for name in ('bob','fred') if name=='bob')
هذا هو وسيلة جيدة للذهاب عن ذلك ؟
def one(g):
try:
val = g.next()
try:
g.next()
except StopIteration:
return val
else:
raise Exception('Too many values')
except StopIteration:
raise Exception('No values')
المحلول
والحل الأبسط هو استخدام الصفوف (tuple) التفريغ. وهذا يحدث بالفعل كل ما تريد، بما في ذلك التحقق أنه يحتوي على عنصر واحد بالضبط.
وبند واحد:
>>> name, = (name for name in ('bob','fred') if name=='bob')
>>> name
'bob'
وعناصر كثيرة جدا:
>>> name, = (name for name in ('bob','bob') if name=='bob')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: too many values to unpack
وليس هناك أي عناصر:
>>> name, = (name for name in ('fred','joe') if name=='bob')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: need more than 0 values to unpack
نصائح أخرى
ونهج بسيط:
print (name for name in ('bob', 'fred') if name == 'bob').next()
إذا كنت تريد حقا خطأ عند وجود أكثر من قيمة واحدة، ثم كنت في حاجة الى وظيفة. أبسط أستطيع أن أفكر في غير (على تحرير لتعمل مع القوائم أيضا):
def one(iterable):
it = iter(iterable)
val = it.next()
try:
it.next()
except StopIteration:
return val
else:
raise Exception('More than one value')
لأولئك الذين يستخدمون أو المهتمين في طرف ثالث المكتبة ، more_itertools
تنفذ هذه الأداة مع الأم معالجة الأخطاء:
> pip install more_itertools
رمز
import more_itertools as mit
mit.one(name for name in ("bob", "fred") if name == "bob")
# 'bob'
mit.one(name for name in ("bob", "fred", "bob") if name == "bob")
# ValueError: ...
mit.one(name for name in () if name == "bob")
# ValueError: ...
انظر more_itertools
مستندات للحصول على التفاصيل.على كود المصدر الأساسي يشبه الجواب المقبول.
هل لديك نظرة على itertools.islice () طريقة .
>>> i2=itertools.islice((name for name in ('bob','fred') if name=='bob'),0,1,1)
>>> i2.next()
'bob'
>>> i2.next()
Traceback (most recent call last):
File "<interactive input>", line 1, in <module>
StopIteration
>>>
<اقتباس فقرة>
وهذه الوحدة تنفذ عددا من اللبنات مكرر مستوحاة من يبني من لغات البرمجة هاسكل وSML. تم إعادة صياغة كل في شكل مناسب لبيثون.
وحدة توحد مجموعة أساسية من أدوات سريعة، ذاكرة كفاءة التي هي مفيدة في حد ذاتها أو في تركيبة. توحيد يساعد على تجنب القراءة والموثوقية المشاكل التي تنشأ عندما خلق العديد من مختلف الأفراد الخاصة تطبيقات مختلفة قليلا، ولكل منها المراوغات الخاصة واصطلاحات التسمية.
تم تصميم أدوات لدمج بسهولة مع بعضها البعض. وهذا يجعل من السهل لبناء المزيد من الأدوات المتخصصة بإيجاز وكفاءة في بيثون النقي.
اقتباس فقرة>هل تقصد؟
def one( someGenerator ):
if len(list(someGenerator)) != 1: raise Exception( "Not a Singleton" )
وماذا تحاول تحقيقه مع كافة التعليمات البرمجية اضافية؟
وهنا هو بلدي محاولة في وظيفة one()
. وأود أن تجنب الدعوة .next()
صريحة واستخدام لحلقة بدلا من ذلك.
def one(seq):
counter = 0
for elem in seq:
result = elem
counter += 1
if counter > 1:
break
if counter == 0:
raise Exception('No values')
elif counter > 1:
raise Exception('Too many values')
return result
أولا، (للإجابة على السؤال الفعلي!) والحل تعمل بشكل جيد كما ان المتغيرات الأخرى المقترحة.
وأود أن أضيف أنه في هذه الحالة، IMO والمولدات هي مفرطة في التعقيد. إذا كنت تتوقع أن يكون قيمة واحدة، فسوف يكون من المحتمل أبدا أن يكون بما فيه الكفاية لاستخدام الذاكرة لتكون مصدر قلق، لذلك كنت قد استخدمت فقط ما هو واضح وأكثر وضوحا:
children = [name for name in ('bob','fred') if name=='bob']
if len(children) == 0:
raise Exception('No values')
elif len(children) > 1:
raise Exception('Too many values')
else:
child = children[0]
وماذا عن استخدام لبيثون ل.. في جملة مع عداد؟ على غرار الجواب دون علم و.
def one(items):
count = 0
value = None
for item in items:
if count:
raise Exception('Too many values')
count += 1
value = item
if not count:
raise Exception('No values')
return value