This must be simple, but as an only occasional python user, fighting some syntax.
This works:
def perms (xs):
for x in itertools.permutations(xs): yield list(x)
But this won't parse:
def perms (xs): for x in itertools.permutations(xs): yield list(x)
Is there some restriction on the one-line function syntax?
The body definition (for...) can be either two or one line by itself, and the def: can be one or two lines with a simple body, but combining the two fails.
Is there a syntax rule that excludes this?
If you must have one line just make it a lambda:
perms = lambda xs: (list(x) for x in itertools.permutations(xs))
Quite often, when you have a short for loop for generating data you can replace it with either list comprehension or a generator expression for approximately the same legibility in slightly less space.
Yes, there are restrictions. No, you can't do that. Simply put, you can skip one line feed but not two.
See here.
The reason for this is that it would allow you to do
if test1: if test2: print x
else:
print y
Which is ambiguous.
In your case, I am not sure. But with some functions you can achive this by using semicolons.
>>> def hey(ho): print(ho); print(ho*2); return ho*3
...
>>> hey('you ')
you
you you
'you you you '
def perms (xs):
for x in itertools.permutations(xs): yield list(x)
You can use exec() to help this problem
exec('def perms (xs):\n for x in itertools.permutations(xs):\n yield list(x)\n')
beware to insert indented spacing or chr(9) after \n
Example for if Python in one line
for i in range(10):
if (i==1):
print(i)
exec('for i in range(10)\n if (i==1):\n print(i)\n')
This is My project on GitHub to use exec to run Python program in interactive console mode
*note multiple line exec run only when end with '\n'
Related
I have a function I'm using to test in an if/then.
The issue is that I'm executing the function BOTH in the if conditional, and then again after the if statement because the function returns two items.
This just seems wasteful and I'm trying to think of ways to improve this. Here's a really basic version of what I'm trying to avoid: "True" is returned to allow the condition to pass, but then then "coolstuff()" is executed again to get more information from the function.
"coolstuff()" could possibly return false, so I can't use the returned string "stuff" as the test.
def coolstuff():
return True, "stuff"
if coolstuff()[0]:
coolthing = coolstuff()[1]
print coolthing
There's gotta be a better way to do this, no? My brain is melting a little as I try to hash it out.
I basically want to do something like this (invalid) syntax:
def coolstuff():
return True, "stuff"
if a, b == coolstuff() and a:
print b
Just collect both results into variables
a, b = fn()
if a:
# work with b
def coolstuff():
if valid:
return "stuff"
return None
data = coolstuff()
if data:
print(data)
Call the function and capture the entire returned value:
x = coolstuff()
Now you have access to both parts of the returned value, in x[0] and x[1].
Store it:
state, coolvar = coolstuff()
if state:
do_whatever(coolvar)
If in newer Python, you could use the dreaded walrus (but I prefer ti7's approach of just assigning in a separate line):
if (x := coolstuff())[0]:
print(x[1])
I am a complete newbie in python.
I start doing lambda functions and they end up a bit longer than my initial goal:
Can I split it in different lines for better readability?, like this:
parts.map(lambda p: (p[0]\
,p[1]\
,int(p[1].split("-")[0])\
,int(p[1].split("-")[1])\
,p[2]\
,float(p[3])\
,p[4]))
or it defeats the purpose of using a lambda function?
I feel when I write it is ok to use lambda function in one line, is quick and good, but when I check again my code later I feel is not legible all of it in one line...
If it's not clearly readable as a simple one-liner, then it's not a good candidate for a lambda. Remember that the lambda statement is just syntactic sugar, technically it IS a function:
>>> def foo(): pass
...
>>> bar = lambda: None
>>>
>>> type(foo)
<class 'function'>
>>> type(bar)
<class 'function'>
>>>
So yes, in your example it does definitly "defeat the purpose of using a lambda function". As far as I'm concerned, if I had to maintain this code, I'd rather find something like:
def prepare(p):
p1a, p1b = (int(x) for x in p[1].split("-"))
p3f = float(p3)
return p[0], p[1], p1a, p1b, p[2], p3f, p[4]
whatever = [prepare(part) for part in parts]
If you are interested in style and readability I can't recommend the PEP8 style guide enough. Overall, it explains the best practices to write readable Python.
It will in particular give you advice on where to put commas when you start a new line, when to use parenthesis and how and when to write to a new line.
On lambda functions in particular it states:
Always use a def statement instead of an assignment statement that
binds a lambda expression directly to an identifier.
Yes:
def f(x): return 2*x
No:
f = lambda x: 2*x
In your case, I would use a function instead.
You could define a normal function and just use it in the map function if it gets too long.
def foo(p):
'''your code'''
result = list(map(foo, your_list)) # the list wrapper to convert map object to a list
I've been working on a "learning project" which involves several short single-parameter functions, where the parameter might be either a numeric type or a list of numerics. E.g.,
def magnitude_of(v):
try:
return math.sqrt(sum([vi**2 for vi in v]))
except:
return abs(v)
This of course is necessary because if I did this:
def magnitude_of(v):
return math.sqrt(sum([vi**2 for vi in list(v)]))
...the code would fail because list() only accepts an iterable as an argument.
My question is: has there ever been consideration given at PSW to letting list() work with any argument? If so, what prevented the change from being implemented?
I would just create my own list function and use it for this particular purpose.
Ex:
def mlist(v):
try:
return list(v)
except(TypeError):
return [v]
Now you use mlist instead of list
l1 = mlist(1)
l2 = mlist([1])
Both will give [1] as the result
I cannot comment on whether this has come up at PSW, but I generally prefer using a ternary here instead of try... catch
e.g.
def magnitude_of(v):
return math.sqrt(sum([vi*vi for vi in (v if isinstance(v,list) else [v])]))
Granted, as others have mentioned it would probably be best if the function simply requires a list to be passed
I find that in lots of different projects I'm writing a lot of code where I need to evaluate a (moderately complex, possibly costly-to-evaluate) expression and then do something with it (e.g. use it for string formatting), but only if the expression is True/non-None.
For example in lots of places I end up doing something like the following:
result += '%s '%( <complexExpressionForGettingX> ) if <complexExpressionForGettingX> else ''
... which I guess is basically a special-case of the more general problem of wanting to return some function of an expression, but only if that expression is True, i.e.:
f( e() ) if e() else somedefault
but without re-typing the expression (or re-evaluating it, in case it's a costly function call).
Obviously the required logic can be achieved easily enough in various long-winded ways (e.g. by splitting the expression into multiple statements and assigning the expression to a temporary variable), but that's a bit grungy and since this seems like quite a generic problem, and since python is pretty cool (especially for functional stuff) I wondered if there's a nice, elegant, concise way to do it?
My current best options are either defining a short-lived lambda to take care of it (better than multiple statements, but a bit hard to read):
(lambda e: '%s ' % e if e else '')( <complexExpressionForGettingX> )
or writing my own utility function like:
def conditional(expr, formatStringIfTrue, default='')
... but since I'm doing this in lots of different code-bases I'd much rather use a built-in library function or some clever python syntax if such a thing exists
I like one-liners, definitely. But sometimes they are the wrong solution.
In professional software development, if the team size is > 2, you spent more time on understanding code someone else wrote than on writing new code. The one-liners presented here are definitely confusing, so just do two lines (even though you mentioned multiple statements in your post):
X = <complexExpressionForGettingX>
result += '%s '% X if X else ''
This is clear, concise, and everybody immediately understands what's going on here.
Python doesn't have expression scope (Is there a Python equivalent of the Haskell 'let'), presumably because the abuses and confusion of the syntax outweigh the advantages.
If you absolutely have to use an expression scope, the least worst option is to abuse a generator comprehension:
result += next('%s '%(e) if e else '' for e in (<complexExpressionForGettingX>,))
You could define a conditional formatting function once, and use it repeatedly:
def cond_format(expr, form, alt):
if expr:
return form % expr
else:
return alt
Usage:
result += cond_format(<costly_expression>, '%s ', '')
After hearing the responses (thanks guys!) I'm now convinced there's no way to achieve what I want in Python without defining a new function (or lambda function) since that's the only way to introduce a new scope.
For best clarity I decided this needed to be implemented as a reusable function (not lambda) so for the benefit of others, I thought I'd share the function I finally came up with - which is flexible enough to cope with multiple additional format string arguments (in addition to the main argument used to decide whether it's to do the formatting at all); it also comes with pythondoc to show correctness and illustrate usage (if you're not sure how the **kwargs thing works just ignore it, it's just an implementation detail and was the only way I could see to implement an optional defaultValue= kwarg following the variable list of format string arguments).
def condFormat(formatIfTrue, expr, *otherFormatArgs, **kwargs):
""" Helper for creating returning the result of string.format() on a
specified expression if the expressions's bool(expr) is True
(i.e. it's not None, an empty list or an empty string or the number zero),
or return a default string (typically '') if not.
For more complicated cases where the operation on expr is more complicated
than a format string, or where a different condition is required, use:
(lambda e=myexpr: '' if not e else '%s ' % e)
formatIfTrue -- a format string suitable for use with string.format(), e.g.
"{}, {}" or "{1}, {0:d}".
expr -- the expression to evaluate. May be of any type.
defaultValue -- set this keyword arg to override
>>> 'x' + condFormat(', {}.', 'foobar')
'x, foobar.'
>>> 'x' + condFormat(', {}.', [])
'x'
>>> condFormat('{}; {}', 123, 456, defaultValue=None)
'123; 456'
>>> condFormat('{0:,d}; {2:d}; {1:d}', 12345, 678, 9, defaultValue=None)
'12,345; 9; 678'
>>> condFormat('{}; {}; {}', 0, 678, 9, defaultValue=None) == None
True
"""
defaultValue = kwargs.pop('defaultValue','')
assert not kwargs, 'unexpected kwargs: %s'%kwargs
if not bool(expr): return defaultValue
if otherFormatArgs:
return formatIfTrue.format( *((expr,)+otherFormatArgs) )
else:
return formatIfTrue.format(expr)
Presumably, you want to do this repeatedly to build up a string. With a more global view, you might find that filter (or itertools.ifilter) does what you want to the collection of values.
You'll wind up with something like this:
' '.join(map(str, filter(None, <iterable of <complexExpressionForGettingX>>)))
Using None as the first argument for filter indicates to accept any true value. As a concrete example with a simple expression:
>>> ' '.join(map(str, filter(None, range(-3, 3))))
'-3 -2 -1 1 2'
Depending on how you're calculating the values, it may be that an equivalent list or generator comprehension would be more readable.
Every so often on here I see someone's code and what looks to be a 'one-liner', that being a one line statement that performs in the standard way a traditional 'if' statement or 'for' loop works.
I've googled around and can't really find what kind of ones you can perform? Can anyone advise and preferably give some examples?
For example, could I do this in one line:
example = "example"
if "exam" in example:
print "yes!"
Or:
for a in someList:
list.append(splitColon.split(a))
Well,
if "exam" in "example": print "yes!"
Is this an improvement? No. You could even add more statements to the body of the if-clause by separating them with a semicolon. I recommend against that though.
I've found that in the majority of cases doing block clauses on one line is a bad idea.
It will, again as a generality, reduce the quality of the form of the code. High quality code form is a key language feature for python.
In some cases python will offer ways todo things on one line that are definitely more pythonic. Things such as what Nick D mentioned with the list comprehension:
newlist = [splitColon.split(a) for a in someList]
although unless you need a reusable list specifically you may want to consider using a generator instead
listgen = (splitColon.split(a) for a in someList)
note the biggest difference between the two is that you can't reiterate over a generator, but it is more efficient to use.
There is also a built in ternary operator in modern versions of python that allow you to do things like
string_to_print = "yes!" if "exam" in "example" else ""
print string_to_print
or
iterator = max_value if iterator > max_value else iterator
Some people may find these more readable and usable than the similar if (condition): block.
When it comes down to it, it's about code style and what's the standard with the team you're working on. That's the most important, but in general, i'd advise against one line blocks as the form of the code in python is so very important.
More generally, all of the following are valid syntactically:
if condition:
do_something()
if condition: do_something()
if condition:
do_something()
do_something_else()
if condition: do_something(); do_something_else()
...etc.
an example of a language feature that isn't just removing line breaks, although still not convinced this is clearer than the more verbose version
a = 1 if x > 15 else 2
for a in someList:
list.append(splitColon.split(a))
You can rewrite the above as:
newlist = [splitColon.split(a) for a in someList]
Python lets you put the indented clause on the same line if it's only one line:
if "exam" in example: print "yes!"
def squared(x): return x * x
class MyException(Exception): pass
You could do all of that in one line by omitting the example variable:
if "exam" in "example": print "yes!"
Older versions of Python would only allow a single simple statement after for ...: if ...: or similar block introductory statements.
I see that one can have multiple simple statements on the same line as any of these. However, there are various combinations that don't work. For example we can:
for i in range(3): print "Here's i:"; print i
... but, on the other hand, we can't:
for i in range(3): if i % 2: print "That's odd!"
We can:
x=10
while x > 0: print x; x-=1
... but we can't:
x=10; while x > 0: print x; x-=1
... and so on.
In any event all of these are considered to be extremely NON-pythonic. If you write code like this then experience Pythonistas will probably take a dim view of your skills.
It's marginally acceptable to combine multiple statements on a line in some cases. For example:
x=0; y=1
... or even:
if some_condition(): break
... for simple break continue and even return statements or assigments.
In particular if one needs to use a series of elif one might use something like:
if keystroke == 'q': break
elif keystroke == 'c': action='continue'
elif keystroke == 'd': action='delete'
# ...
else: action='ask again'
... then you might not irk your colleagues too much. (However, chains of elif like that scream to be refactored into a dispatch table ... a dictionary that might look more like:
dispatch = {
'q': foo.break,
'c': foo.continue,
'd': foo.delete
}
# ...
while True:
key = SomeGetKey()
dispatch.get(key, foo.try_again)()
Dive into python has a bit where he talks about what he calls the and-or trick, which seems like an effective way to cram complex logic into a single line.
Basically, it simulates the ternary operater in c, by giving you a way to test for truth and return a value based on that. For example:
>>> (1 and ["firstvalue"] or ["secondvalue"])[0]
"firstvalue"
>>> (0 and ["firstvalue"] or ["secondvalue"])[0]
"secondvalue"
This is an example of "if else" with actions.
>>> def fun(num):
print 'This is %d' % num
>>> fun(10) if 10 > 0 else fun(2)
this is 10
OR
>>> fun(10) if 10 < 0 else 1
1