Assignment to None - python

I have a function which returns 3 numbers, e.g.:
def numbers():
return 1,2,3
usually I call this function to receive all three returned numbers e.g.:
a, b, c = numbers()
However, I have one case in which I only need the first returned number.
I tried using:
a, None, None = numbers()
But I receive "SyntaxError: assignment to None".
I know, of course, that I can use the first option I mentioned and then simply not use the "b" and "c" variables. However, this seems like a "waste" of two vars and feels like wrong programming.

a, _, _ = numbers()
is a pythonic way to do this. In Python 3, you could also use:
a, *_ = numbers()
To clarify _ is a normal variable name in Python, except it is conventionally used to refer to non-important variables.

Another way is of course a=numbers()[0], if you do not want to declare another variable. Having said this though, I generally use _ myself.

The way I do it:
a = numbers()[0]
Seeing as the type returned is a tuple, you can access it via index.
This solution keeps you from having to declare unused/meaningless variables such as "_". Most people don't mind unused variables, however my pylint is setup to warn me of such things as they could indicate potentially unused code, etc.

Related

Python Skipping a Parameter in a Function

Beginner Here and I just want to know how to skip a parameter in python for example
def function(a, b):
pass
function(5)
I want to only assign 5 to b. How can I do it?
You can do this:
def function(a=None, b=None):
pass
function(b=5)
This makes the values that don't get assigned None (in this case a is gonna be None).
If you don't add =None to the two parameters, it will throw an error because I didn't assign anything to a.
If in the last line you don't say b=5 and instead say just 5, it will think that is for the a parameter since the a parameter is before the b parameter in the parenthesis.
Simply, You can set a default value to a in that case.
def function(b,a=None):
pass
function(5)
Please note that the default parameters are supposed to follow the non-defualt ones.

Do Python functions know how many outputs are requested? [duplicate]

This question already has answers here:
nargout in Python
(6 answers)
Closed 7 years ago.
In Python, do functions know how many outputs are requested? For instance, could I have a function that normally returns one output, but if two outputs are requested, it does an additional calculation and returns that too?
Or is this not the standard way to do it? In this case, it would be nice to avoid an extra function argument that says to provide a second input. But I'm interested in learning the standard way to do this.
The real and easy answer is: No.
Python functions/methods does not know about how many outputs are requested, as unpacking of a returned tuple happens after the function call.
What's quite a best practice to do though is to use underscore (_) as a placeholder for unused args that are returned from functions when they're not needed, example:
def f():
return 1, 2, 3
a, b, c = f() # if you want to use all
a, _, _ = f() # use only first element in the returned tuple, 'a'
_, b, _ = f() # use only 'b'
For example, when using underscore (_) pylint will suppress any unused argument warnings.
Python functions always return exactly 1 value.
In this case:
def myfunc():
return
that value is None. In this case:
def myfunc():
return 1, 2, 3
that value is the tuple (1, 2, 3).
So there is nothing for the function to know, really.
As for returning different outputs controlled by parameters, I'm always on the fence about that. It would depend on the actual use case. For a public API that is used by others, it is probably best to provide two separate functions with different return types, that call private code that does take the parameter.

Pythonic way to initialise function parameters

Which is more pythonic?
A
def my_function(arg, p=0):
while arg:
# do something
value = arg.pop()
# save value with a name which uses p for indexing
p+=1
or B
def my_function(arg):
p = 0
while arg:
# do something
value = arg.pop()
# save value with a name which uses p for indexing
p+=1
A part of me think its silly to include p as an argument to the function incase someone sets it to a weird a value. But at the same time I don't like having p=0 clutter up a function which is already very complicated.
Don't clutter up function parameters with locals. If it is not a parameter the caller should use, don't add it to your function signature.
In other words, you don't want anyone using help(my_function) and be surprised at what p might be for.
This isn't a hard and fast rule, of course; some critical-path functions can be made faster by using locals, so sometimes you'll see something like:
some_global = expensive_function()
def foo(bar, baz, _some_local=some_global):
# code using _some_local instead of some_global
to make use of faster local name lookups. The _ at the start of the argument then tells you that the name is really an internal implementation detail you should not rely on.
It depends on if p always has to start at 0 or not. If it does, then definitely go with option B. Don't give users an opportunity to mess with your code if it's not necessary.

How to assign a value to variable while extending a list?

it is possible to assign a value to a variable, in the command "extend"?
for example:
ele1=[]
ele2=[]
list=[ele1,ele2]
list[0].extend([a=1,b="bla"])
instead of:
ele1=[]
ele2=[]
list=[ele1,ele2]
a=1
b="bla"
list[0].extend([a,b])
Python distinguishes between "expressions", which have a value and can be generally used wherever a value is needed, and "statements", which perform some action, do not have a value, and cannot be placed in a spot where a value is needed.
Assignment is a statement, and cannot be embedded as a value anywhere, including in a list literal.
(This often comes as surprise to people coming from C-like languages, which do make assignment an expression, but which can often lead to hard-to-find bugs when people, e.g., confuse = and == in conditionals.)
No, Python doesn't allow assignment inside expressions (because it's a great source of bugs) but there are other ways to write your example without the repetition. eg.
a, b = ele1 = [1, "bla"]
ele2 = []
lst = [ele1, ele2]

Wildcards in Python?

Over the years I have noticed the 'wildcard' variable in various bits and pieces of Python I've come across. I assumed it worked like Haskell: allowing you to put a variable where one was required in the formal parameters, but not binding it.
I've used this on, for example, the left hand side of an tuple-unpacking assignment when I don't need one of the variables.
For example:
_, extension = os.path.splitext(filename)
So when I wrote something similar to this today:
(lambda (x,_,_): x)((1,2,3))
I.E. I tried to bind the underscore twice, I received a syntax error. I was surprised to see that _ is indeed a real variable:
(lambda (x,_,z): _)((1,2,3))
> 2
Looks like _ is just a variable name like any other.
Is there a bona fide wildcard variable that I can use as I would like (i.e. able to use more than one in a tuple unpacking assignment), as per the first example?
There is no wildcard variable in Python.
I try to dissuade people from using _ as a variable name for quite some time now. You are not the first person mistaking _ as some kind of special syntax, so it's better not to use _ as a variable name at all to avoid this kind of confusion. If there ever was a "convention" to use _ as a throw-away variable name, this convention was misguided.
There are more problems than just the confusion it causes. For example, _ clashes with _ in the interactive interpreter and the common gettext alias.
Regarding the lambda expression, I'd just use lambda x, *args: ... to ignore all arguments except for the first one. In other cases, I'd use names explicitly stating I don't want to use them, like dummy. In case of loops of range()s, I usually use for i in range(n) and simply don't use i.
Edit: I just noticed (by looking at the other answers) that you use tuple unpacking in the argument list, so lambda x, *args: ... doesn't solve your problem. Tuple unpacking in parameter lists has been removed in Python 3.x because it was considered too obscure a feature. Better go with mipadi's answer instead.
Not really. Python is not Haskell. Map, apply, reduce, and lambda are kind of second-class citizens, though there is some interesting stuff in itertools.
Unless you have some need to use one-line lambdas, the correct way is this:
def f(x, *args, **kwargs):
return x
The *args argument lets you use any number of unnamed arguments (which will be available as a tuple called args). Extra named arguments will be in a dictionary called kwargs.
I don't think there's any way to do this in a lambda, but there's usually no need. A function declaration can go anywhere. Note, you do interesting / evil stuff if you put the function definition inside another function (or loop):
def make_func(s):
def f(*trash, **more_trash):
print s
return f
f1 = make_func('hello')
f2 = make_func('world')
f1(1,2,'ham','spam')
f2(1,2,a=1,b=2)
will output:
>>> hello
>>> world
As #rplnt pointed out, this won't be the same for loops:
funcs = []
for s in ('hello','world'):
def f():
print s
funcs.append(f)
for f in funcs:
f()
will output:
>>> world
>>> world
because loops only have one namespace.
No, Python doesn't have any equivalent to Haskell's _. The convention in Python is to use _ for "throwaway" variables, but it's an actual variable name, and as you found, you can't use it twice in the same context (like a lambda parameter list).
In the examples you gave, I'd just use indexing:
lambda tup: tup[0]
or
lambda tup: tup[1]
Not as pretty, but one of the better ways to do it.
It is possible, with a little trick:
class _:
def __eq__(x,y): return true
_=_() #always create a new _ instance if used, the class name itself is not needed anymore
[(a,b) for (a,_,_,b) in [(1,2,3,4),(5,6,7,8)]]
gives
[(1, 4), (5, 8)]
I'm using it often, because it makes code more elegant,
a part of Haskells beauty in Python.
Short answer is no. Could just follow your existing convention. That is
(lambda (x, _1, _2): x)((1,2,3))

Categories

Resources