Reputation: 12672
From the docs, all
is equivalent to:
def all(iterable):
for element in iterable:
if not element:
return False
return True
Then why do I get this output:
# expecting: False
$ python -c "print( all( (isinstance('foo', int), int('foo')) ) )"
Traceback (most recent call last):
File "<string>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'
When:
# expecting: False
$ python -c "print( isinstance('foo', int) )"
False
Upvotes: 4
Views: 1096
Reputation: 155296
Your intuition regarding all
is correct; you only need to work a little harder to set up a lazy sequence. For example:
def lazy():
yield isinstance("foo", int) # False
yield int("foo") # raises an error, but we won't get here
>>> all(lazy())
False
>>> list(lazy())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in lazy
ValueError: invalid literal for int() with base 10: 'foo'
Upvotes: 2
Reputation: 12672
If the desire to stop evaluation after the first False
condition is specifically to perform type checking, something like this will work better:
if not isinstance(other, MyClass):
return False
else:
return all((self.attr1 == other.attr2,
self.attr2 == other.attr2)) # etc.
Simplified version from @catchmeifyoutry:
return isinstance(other, MyClass) and all((self.attr1 == other.attr2,
self.attr2 == other.attr2)) # etc.
Upvotes: 1
Reputation: 599866
One (fairly ugly) way to get the behaviour you want is via lambdas:
all(f() for f in (lambda: isinstance('foo', int), lambda: int('foo')))
Upvotes: 7
Reputation: 96286
Arguments are evaluated before calling a function. In this case first you have to create the tuple you pass to all
.
all
never had a chance to check them, the exception was thrown before that.
>>> int('foo')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'foo'
Upvotes: 5