Why would I get a TypeEror?

I

It's me

For this code snip:

a=3
.....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

Thanks,
 
P

Peter Hansen

It's me said:
For this code snip:

a=3
....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

What did you expect the "length" of the integer 3 to be?

-Peter
 
H

harold fellermann

For this code snip:

a=3
....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

because len() works only for sequence and mapping objects:
Help on built-in function len in module __builtin__:

len(...)
len(object) -> integer

Return the number of items of a sequence or mapping.

- harold -
 
H

harold fellermann

For this code snip:

a=3
....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

the problem is, that (1,len(a)) is evaluated, neither what type a
actually has
(python has no builtin lazy evaluation like ML). You have to do it this
way
instead:

a=3
....
b = isinstance(a,(list,tuple,dict)) and len(a) or 1

- harold -
 
I

It's me

Sorry if my question was a little "lazy" and yes, I was asking about the
"lazy evaluation". :=)

I am surprised about this (and this can be dangerous, I guess).

If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

and that's not good.

Something to keep in mind. :-(


harold fellermann said:
For this code snip:

a=3
....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

the problem is, that (1,len(a)) is evaluated, neither what type a
actually has
(python has no builtin lazy evaluation like ML). You have to do it this
way
instead:

a=3
...
b = isinstance(a,(list,tuple,dict)) and len(a) or 1

- harold -
 
S

Steve Holden

It's me said:
For this code snip:

a=3
.....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

Thanks,
because the interpreter evaluates the tuple (1, len(a)) before applying
the indexing to it.

You are trying to be far too clever. The standard way to write this
would be:

a = 3
.....
b = 1
if isinstance(a,(list,tuple,dict)):
b = len(a)

Is code length *really* so important? Think carefully ...

regards
Steve
 
T

Terry Reedy

Peter Hansen said:
What did you expect the "length" of the integer 3 to be?

Perhaps 2 (bits in a minimal binary representation).

I once, for maybe a minute, considered proposing this as an overloaded
meaning of len, but realized that that would more often mask errors than
save time.

If case bits(i) is what the OP wants:

def bits(i):
i = abs(i)
b = 0
while i:
i >>= 1
b += 1
return b

Terry J. Reedy
 
S

Steven Bethard

It's me said:
For this code snip:

a=3
....
b=(1,len(a))[isinstance(a,(list,tuple,dict))]

Why would I get a TypeError from the len function?

You're looking for lazy evaluation or short-circuiting behavior. Python
provides one form of short circuiting behavior with 'and' and 'or',
though you need to be careful. In your particular circumstances, you
could write this code as:

b = not isinstance(a, (list, tuple, dict)) and 1 or len(a)

Some example code:

py> def b(a):
.... return not isinstance(a, (list, tuple, dict)) and 1 or len(a)
....
py> b(3)
1
py> b([])
0
py> b([3, 4])
2

Note however that, due to how 'and' and 'or' short-circuit, you cannot
write your code as:

b = isinstance(a, (list, tuple, dict)) and len(a) or 1

because when len(a) is 0, 1 will be returned instead of 0:

py> def b(a):
.... return isinstance(a, (list, tuple, dict)) and len(a) or 1
....
py> b(3)
1
py> b([])
1
py> b([3, 4])
2

If you want lazy evaluation, you can do this with lambdas (though I
wouldn't advise it):

b = (lambda: 1, lambda: len(a))[isinstance(a,(list,tuple,dict))]()

Note that I select which function using isinstance as you have before,
and then invoke the selected function with the final ().

Steve
 
R

Reinhold Birkenfeld

It's me said:
Sorry if my question was a little "lazy" and yes, I was asking about the
"lazy evaluation". :=)

I am surprised about this (and this can be dangerous, I guess).

If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

and that's not good.

Something to keep in mind. :-(

Lazy evaluation: use the (x==0 and 1e99 or 1/x) form!

Reinhold
 
I

It's me

Say again???

Reinhold Birkenfeld said:
It's me said:
Sorry if my question was a little "lazy" and yes, I was asking about the
"lazy evaluation". :=)

I am surprised about this (and this can be dangerous, I guess).

If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

and that's not good.

Something to keep in mind. :-(

Lazy evaluation: use the (x==0 and 1e99 or 1/x) form!

Reinhold
 
R

Reinhold Birkenfeld

It's me said:
Say again???

Reinhold Birkenfeld said:
It's me said:
Sorry if my question was a little "lazy" and yes, I was asking about the
"lazy evaluation". :=)

I am surprised about this (and this can be dangerous, I guess).

If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

and that's not good.

Something to keep in mind. :-(

Lazy evaluation: use the (x==0 and 1e99 or 1/x) form!

Reinhold

Say what again?

Reinhold

PS: Please do not produce top-posting!
 
S

Steven Bethard

It's me said:
Say again???

Please stop top-posting -- it makes it hard to reply in context.
It's me said:
If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

Lazy evaluation: use the (x==0 and 1e99 or 1/x) form!

If you want short-circuting behavior, where only one of the two branches
gets executed, you should use Python's short-circuiting boolean
operators. For example,

(x == 0 and 1.0e99 or 1/x)

says something like:

Check if x == 0.
If so, check if 1.0e99 is non-zero. It is, so return it.
If x != 0, see if 1/x is non-zero. It is, so return it.

Note that if you're not comfortable with short-circuiting behavior, you
can also code this using lazy evaluation:

(lambda: 1/x, lambda: 1.0e99)[x==0]()

This says something like:

Create two functions, one to produce 1/x and one to produce 1.0e99.
Select one of these functions depending on whether or not x==0
Invoke the chosen function.

HTH,

Steve
 
R

Reinhold Birkenfeld

Steven said:
It's me said:
Say again???

Please stop top-posting -- it makes it hard to reply in context.
It's me wrote:
If this is true, I would run into trouble real quick if I do a:

(1/x,1.0e99)[x==0]

Lazy evaluation: use the (x==0 and 1e99 or 1/x) form!

If you want short-circuting behavior, where only one of the two branches
gets executed, you should use Python's short-circuiting boolean
operators. For example,

(x == 0 and 1.0e99 or 1/x)

says something like:

Check if x == 0.
If so, check if 1.0e99 is non-zero. It is, so return it.
If x != 0, see if 1/x is non-zero. It is, so return it.

Note that if you're not comfortable with short-circuiting behavior, you
can also code this using lazy evaluation:

(lambda: 1/x, lambda: 1.0e99)[x==0]()

Or even

(x==0 and lambda: 1e99 or lambda: 1/x)()

Or ...


Reinhold
 
S

Stian Soiland

På 14. jan 2005 kl. 22:58 skrev Steven Bethard:

(Any mac users? How do I fix this to appear in Norwegian? =)
Note that if you're not comfortable with short-circuiting behavior,
you can also code this using lazy evaluation:

(lambda: 1/x, lambda: 1.0e99)[x==0]()

... and people wonder why so many Python people want to get rid of
Lambda =)
 
S

Steven Bethard

Stian said:
På 14. jan 2005 kl. 22:58 skrev Steven Bethard:

(Any mac users? How do I fix this to appear in Norwegian? =)
Note that if you're not comfortable with short-circuiting behavior,
you can also code this using lazy evaluation:

(lambda: 1/x, lambda: 1.0e99)[x==0]()


.. and people wonder why so many Python people want to get rid of Lambda =)

Heh heh. No I don't. ;)

In fact, I don't ever use lambdas in any of my own "real" code. But I
don't mind being a little dirty when I post to c.l.py. ;) I guess I
could have written this as:

def inverse():
return 1/x
def largenum():
return 1.0e99
b = (inverse, largenum)[x==0]()

but I'm usually too lazy, and it's an ugly solution anyway, compared to
the simple one which the OP was apparently trying to avoid:

if x != 0:
b = 1/x
else:
b = 1.0e99

=)

Steve
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,216
Messages
2,571,116
Members
47,720
Latest member
mohdkaif002

Latest Threads

Top