Bare Asterisk in Function Arguments

Bare asterisk in function arguments?

Bare * is used to force the caller to use named arguments - so you cannot define a function with * as an argument when you have no following keyword arguments.

See this answer or Python 3 documentation for more details.

What is the purpose of a bare asterisk in function arguments?

PEP 3102 explains the rationale pretty clearly: the point is to allow functions to accept various "options" that are essentially orthogonal in nature. Specifying these positionally is awkward both on the defining and calling side, since they don't have any obvious "priority" that would translate into a positional order.

There are lots of example of functions that would benefit from this in various libraries. For instance, the call signature of pandas.read_csv is:

def parser_f(filepath_or_buffer,
sep=sep,
dialect=None,
compression=None,

doublequote=True,
escapechar=None,
quotechar='"',
quoting=csv.QUOTE_MINIMAL,
skipinitialspace=False,
lineterminator=None,

header='infer',
index_col=None,
names=None,
prefix=None,
skiprows=None,
skipfooter=None,
skip_footer=0,
na_values=None,
na_fvalues=None,
true_values=None,
false_values=None,
delimiter=None,
converters=None,
dtype=None,
usecols=None,

engine='c',
delim_whitespace=False,
as_recarray=False,
na_filter=True,
compact_ints=False,
use_unsigned=False,
low_memory=_c_parser_defaults['low_memory'],
buffer_lines=None,
warn_bad_lines=True,
error_bad_lines=True,

keep_default_na=True,
thousands=None,
comment=None,
decimal=b'.',

parse_dates=False,
keep_date_col=False,
dayfirst=False,
date_parser=None,

memory_map=False,
nrows=None,
iterator=False,
chunksize=None,

verbose=False,
encoding=None,
squeeze=False,
mangle_dupe_cols=True,
tupleize_cols=False,
infer_datetime_format=False):

Except for the filepath, most of these are orthogonal options that specify different aspects of how a CSV file is to be parsed. There's no particular reason why they would be passed in any particular order. You'd go nuts keeping track of any positional order for these. It makes more sense to pass them as keywords.

Now, you can see that pandas doesn't actually define them as keyword-only arguments, presumably to maintain compatibility with Python 2. I would imagine that many libraries have refrained from using the syntax for the same reason. I don't know offhand which libraries (if any) have started using it.

Python method/function arguments starting with asterisk and dual asterisk

The *args and **keywordargs forms are used for passing lists of arguments and dictionaries of arguments, respectively. So if I had a function like this:

def printlist(*args):
for x in args:
print(x)

I could call it like this:

printlist(1, 2, 3, 4, 5)  # or as many more arguments as I'd like

For this

def printdict(**kwargs):
print(repr(kwargs))

printdict(john=10, jill=12, david=15)

*args behaves like a list, and **keywordargs behaves like a dictionary, but you don't have to explicitly pass a list or a dict to the function.

See this for more examples.

What does the asterisk * mean as the first argument in the signature of a function/class/method?

Any arguments specified after the * "argument" (so in this case, all of them) are keyword-only arguments. They can only be supplied by keyword, rather than positionally; this means your example should be:

from tensorforce.core.layers import Dense
d = Dense(size=4)

That error message you got is not terribly intuitive, is it? This is a consequence of the fact that in Python, an object's method is essentially a function that automatically receives the object itself as the first argument (which is why you normally write self in a method definition, but don't supply it when calling the method).

In this case, the __init__ method takes one and exactly one positional argument: its own object instance. Since you also provided size positionally, Python complains that it got two arguments—even though you only explicitly gave it one.

What do * (single star) and / (slash) do as independent parameters?

There is a new function parameter syntax / to indicate that some function parameters must be specified positionally and cannot be used as keyword arguments.[This is new in Python 3.8]

Documentation specifies some of the use cases/benefits of positional-only parameters

  1. It allows pure Python functions to fully emulate behaviors of
    existing C coded functions. For example, the built-in pow()
    function does not accept keyword arguments:

    def pow(x, y, z=None, /):
    "Emulate the built in pow() function"
    r = x ** y
    return r if z is None else r%z
  2. Another use case is to preclude keyword arguments when the parameter
    name is not helpful. For example, the builtin len() function has
    the signature len(obj, /). This precludes awkward calls such as:

    len(obj='hello')  # The "obj" keyword argument impairs readability
  3. A further benefit of marking a parameter as positional-only is that
    it allows the parameter name to be changed in the future without
    risk of breaking client code. For example, in the statistics module,
    the parameter name dist may be changed in the future. This was made
    possible with the following function specification:

    def quantiles(dist, /, *, n=4, method='exclusive')
    ...

Where as * is used to force the caller to use named arguments. This is one of the use case of named arguments.

So, given the method,

def func(self, param1, param2, /, param3, *, param4, param5):
print(param1, param2, param3, param4, param5)

It must called with

obj.func(10, 20, 30, param4=50, param5=60)

or

obj.func(10, 20, param3=30, param4=50, param5=60)

ie,

  1. param1, param2 must be specified positionally.
  2. param3 can be called either with positional or keyword.
  3. param4 and param5 must be called with keyword argument.

DEMO:

>>> class MyClass(object):
... def func(self, param1, param2, /, param3, *, param4, param5):
... return param1, param2, param3, param4, param5
...
>>> obj = MyClass()
>>>
>>> assert obj.func(10, 20, 30, param4=40, param5=50), obj.func(
... 10, 20, param3=30, param4=40, param5=50
... )

What does asterisk * mean in Python?

See Function Definitions in the Language Reference.

If the form *identifier is
present, it is initialized to a tuple
receiving any excess positional
parameters, defaulting to the empty
tuple. If the form **identifier is
present, it is initialized to a new
dictionary receiving any excess
keyword arguments, defaulting to a new
empty dictionary.

Also, see Function Calls.

Assuming that one knows what positional and keyword arguments are, here are some examples:

Example 1:

# Excess keyword argument (python 2) example:
def foo(a, b, c, **args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args

foo(a="testa", d="excess", c="testc", b="testb", k="another_excess")

As you can see in the above example, we only have parameters a, b, c in the signature of the foo function. Since d and k are not present, they are put into the args dictionary. The output of the program is:

a = testa
b = testb
c = testc
{'k': 'another_excess', 'd': 'excess'}

Example 2:

# Excess positional argument (python 2) example:
def foo(a, b, c, *args):
print "a = %s" % (a,)
print "b = %s" % (b,)
print "c = %s" % (c,)
print args

foo("testa", "testb", "testc", "excess", "another_excess")

Here, since we're testing positional arguments, the excess ones have to be on the end, and *args packs them into a tuple, so the output of this program is:

a = testa
b = testb
c = testc
('excess', 'another_excess')

You can also unpack a dictionary or a tuple into arguments of a function:

def foo(a,b,c,**args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)

argdict = dict(a="testa", b="testb", c="testc", excessarg="string")
foo(**argdict)

Prints:

a=testa
b=testb
c=testc
args={'excessarg': 'string'}

And

def foo(a,b,c,*args):
print "a=%s" % (a,)
print "b=%s" % (b,)
print "c=%s" % (c,)
print "args=%s" % (args,)

argtuple = ("testa","testb","testc","excess")
foo(*argtuple)

Prints:

a=testa
b=testb
c=testc
args=('excess',)


Related Topics



Leave a reply



Submit