Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
W
win-pytreat
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
FSL
win-pytreat
Commits
63df73d6
Commit
63df73d6
authored
7 years ago
by
Paul McCarthy
Browse files
Options
Downloads
Patches
Plain Diff
Finished args/kwargs practical.
parent
bd5b0e09
No related branches found
Branches containing commit
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
advanced_topics/function_inputs_and_outputs.ipynb
+125
-4
125 additions, 4 deletions
advanced_topics/function_inputs_and_outputs.ipynb
advanced_topics/function_inputs_and_outputs.md
+97
-4
97 additions, 4 deletions
advanced_topics/function_inputs_and_outputs.md
with
222 additions
and
8 deletions
advanced_topics/function_inputs_and_outputs.ipynb
+
125
−
4
View file @
63df73d6
...
...
@@ -72,7 +72,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"You can think of the star operator as
'
unpacking
'
the contents of the\n",
"You can think of the star operator as
_
unpacking
_
the contents of the\n",
"sequence.\n",
"\n",
"\n",
...
...
@@ -98,7 +98,7 @@
"metadata": {},
"source": [
"Python has another operator - the double-star (`**`), which will unpack\n",
"keyword arguments from `dict`. For example:"
"keyword arguments from
a
`dict`. For example:"
]
},
{
...
...
@@ -149,7 +149,7 @@
"metadata": {},
"outputs": [],
"source": [
"myfunc(a=1, b=2, c=3):\n",
"
def
myfunc(a=1, b=2, c=3):\n",
" print('First argument: ', a)\n",
" print('Second argument:', b)\n",
" print('Third argument: ', c)"
...
...
@@ -239,7 +239,128 @@
"defined, and will persist for the duration of your program. So in this\n",
"example, the default value for `a`, a Python `list`, gets created when\n",
"`badfunc` is defined, and hangs around for the lifetime of the `badfunc`\n",
"function!"
"function!\n",
"\n",
"\n",
"## Variable numbers of arguments - `args` and `kwargs`\n",
"\n",
"\n",
"The `*` and `**` operators can also be used in function definitions - this\n",
"indicates that a function may accept a variable number of arguments.\n",
"\n",
"\n",
"Let's redefine `myfunc` to accept any number of positional arguments - here,\n",
"all positional arguments will be passed into `myfunc` as a tuple called\n",
"`args`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def myfunc(*args):\n",
" print('myfunc({})'.format(args))\n",
" print(' Number of arguments: {}'.format(len(args)))\n",
" for i, arg in enumerate(args):\n",
" print(' Argument {:2d}: {}'.format(i, arg))\n",
"\n",
"myfunc()\n",
"myfunc(1)\n",
"myfunc(1, 2, 3)\n",
"myfunc(1, 'a', [3, 4])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Similarly, we can define a function to accept any number of keyword\n",
"arguments. In this case, the keyword arguments will be packed into a `dict`\n",
"called `kwargs`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def myfunc(**kwargs):\n",
" print('myfunc({})'.format(kwargs))\n",
" for k, v in kwargs.items():\n",
" print(' Argument {} = {}'.format(k, v))\n",
"\n",
"myfunc()\n",
"myfunc(a=1, b=2)\n",
"myfunc(a='abc', foo=123)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"This is a useful technique in many circumstances. For example, if you are\n",
"writing a function which calls another function that takes many arguments, you\n",
"can use ``**kwargs`` to pass-through arguments to the second function. As an\n",
"example, let's say we have functions `flirt` and `fnirt`, which respectively\n",
"perform linear and non-linear registration:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def flirt(infile,\n",
" ref,\n",
" outfile=None,\n",
" init=None,\n",
" omat=None,\n",
" dof=12):\n",
" # TODO get MJ to fill this bit in\n",
" pass\n",
"\n",
"def fnirt(infile,\n",
" ref,\n",
" outfile=None,\n",
" aff=None,\n",
" interp='nn',\n",
" refmask=None,\n",
" minmet='lg',\n",
" subsamp=4):\n",
" # TODO get Jesper to fill this bit in\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We want to write our own registration function which uses the `flirt` and\n",
"`fnirt` functions, while also allowing the `fnirt` parameters to be\n",
"customised. We can use `**kwargs` to do this:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def do_nonlinear_reg(infile, ref, outfile, **kwargs):\n",
" \"\"\"Aligns infile to ref using non-linear registration. All keyword\n",
" arguments are passed through to the fnirt function.\n",
" \"\"\"\n",
"\n",
" affmat = '/tmp/aff.mat'\n",
"\n",
" # calculate a rough initial linear alignemnt\n",
" flirt(infile, ref, omat=affmat)\n",
"\n",
" fnirt(infile, ref, outfile, aff=affmat, **kwargs)"
]
}
],
...
...
%% Cell type:markdown id: tags:
# Function inputs and outputs
In Python, arguments to a function can be specified in two different ways - by
using _positional_ arguments, or by using _keyword_ arguments.
## Positional arguments
Let's say we have a function that looks like this
%% Cell type:code id: tags:
```
def myfunc(a, b, c):
print('First argument: ', a)
print('Second argument:', b)
print('Third argument: ', c)
```
%% Cell type:markdown id: tags:
If we call this function like so:
%% Cell type:code id: tags:
```
myfunc(1, 2, 3)
```
%% Cell type:markdown id: tags:
The values
`1`
,
`2`
and
`3`
get assigned to arguments
`a`
,
`b`
, and
`c`
respectively, based on the position in which they are passed.
Python allows us to pass positional arguments into a function from a sequence,
using the star (
`*`
) operator. So we could store our arguments in a list or
tuple, and then pass the list straight in:
%% Cell type:code id: tags:
```
args = [3, 4, 5]
myfunc(*args)
```
%% Cell type:markdown id: tags:
You can think of the star operator as
'
unpacking
'
the contents of the
You can think of the star operator as
_
unpacking
_
the contents of the
sequence.
## Keyword arguments
Using keyword arguments allows us to pass arguments to a function in any order
we like. We could just as easily call our
`myfunc`
function like so, and get
the same result that we did earlier when using positional arguments:
%% Cell type:code id: tags:
```
myfunc(c=3, b=2, a=1)
```
%% Cell type:markdown id: tags:
Python has another operator - the double-star (
`**`
), which will unpack
keyword arguments from
`dict`
. For example:
keyword arguments from
a
`dict`
. For example:
%% Cell type:code id: tags:
```
kwargs = {'a' : 4, 'b' : 5, 'c' : 6}
myfunc(**kwargs)
```
%% Cell type:markdown id: tags:
## Combining positional and keyword arguments
In fact, we can use both of these techniques at once, like so:
%% Cell type:code id: tags:
```
args = (100, 200)
kwargs = {'c' : 300}
myfunc(*args, **kwargs)
```
%% Cell type:markdown id: tags:
## Default argument values
Function arguments can be given default values, like so:
%% Cell type:code id: tags:
```
myfunc(a=1, b=2, c=3):
def
myfunc(a=1, b=2, c=3):
print('First argument: ', a)
print('Second argument:', b)
print('Third argument: ', c)
```
%% Cell type:markdown id: tags:
Now we can call
`myfunc`
, only passing the arguments that we need to. The
arguments which are unspecified in the function call will be assigned their
default value:
%% Cell type:code id: tags:
```
myfunc()
myfunc(10)
myfunc(10, b=30)
myfunc(c=300)
```
%% Cell type:markdown id: tags:
__WARNING:__
_Never_ define a function with a mutable default value, such as a
`list`
,
`dict`
or other non-primitive type. Let's see what happens when we do:
%% Cell type:code id: tags:
```
def badfunc(a=[]):
a.append('end of sequence')
output = ', '.join([str(elem) for elem in a])
print(output)
```
%% Cell type:markdown id: tags:
With this function, all is well and good if we pass in our own value for
`a`
:
%% Cell type:code id: tags:
```
badfunc([1, 2, 3, 4])
badfunc([2, 4, 6])
```
%% Cell type:markdown id: tags:
But what happens when we let
`badfunc`
use the default value for
`a`
?
%% Cell type:code id: tags:
```
badfunc()
badfunc()
badfunc()
```
%% Cell type:markdown id: tags:
This happens because default argument values are created when the function is
defined, and will persist for the duration of your program. So in this
example, the default value for
`a`
, a Python
`list`
, gets created when
`badfunc`
is defined, and hangs around for the lifetime of the
`badfunc`
function!
## Variable numbers of arguments - `args` and `kwargs`
The
`*`
and
`**`
operators can also be used in function definitions - this
indicates that a function may accept a variable number of arguments.
Let's redefine
`myfunc`
to accept any number of positional arguments - here,
all positional arguments will be passed into
`myfunc`
as a tuple called
`args`
:
%% Cell type:code id: tags:
```
def myfunc(*args):
print('myfunc({})'.format(args))
print(' Number of arguments: {}'.format(len(args)))
for i, arg in enumerate(args):
print(' Argument {:2d}: {}'.format(i, arg))
myfunc()
myfunc(1)
myfunc(1, 2, 3)
myfunc(1, 'a', [3, 4])
```
%% Cell type:markdown id: tags:
Similarly, we can define a function to accept any number of keyword
arguments. In this case, the keyword arguments will be packed into a
`dict`
called
`kwargs`
:
%% Cell type:code id: tags:
```
def myfunc(**kwargs):
print('myfunc({})'.format(kwargs))
for k, v in kwargs.items():
print(' Argument {} = {}'.format(k, v))
myfunc()
myfunc(a=1, b=2)
myfunc(a='abc', foo=123)
```
%% Cell type:markdown id: tags:
This is a useful technique in many circumstances. For example, if you are
writing a function which calls another function that takes many arguments, you
can use
``**kwargs``
to pass-through arguments to the second function. As an
example, let's say we have functions
`flirt`
and
`fnirt`
, which respectively
perform linear and non-linear registration:
%% Cell type:code id: tags:
```
def flirt(infile,
ref,
outfile=None,
init=None,
omat=None,
dof=12):
# TODO get MJ to fill this bit in
pass
def fnirt(infile,
ref,
outfile=None,
aff=None,
interp='nn',
refmask=None,
minmet='lg',
subsamp=4):
# TODO get Jesper to fill this bit in
pass
```
%% Cell type:markdown id: tags:
We want to write our own registration function which uses the
`flirt`
and
`fnirt`
functions, while also allowing the
`fnirt`
parameters to be
customised. We can use
`**kwargs`
to do this:
%% Cell type:code id: tags:
```
def do_nonlinear_reg(infile, ref, outfile, **kwargs):
"""Aligns infile to ref using non-linear registration. All keyword
arguments are passed through to the fnirt function.
"""
affmat = '/tmp/aff.mat'
# calculate a rough initial linear alignemnt
flirt(infile, ref, omat=affmat)
fnirt(infile, ref, outfile, aff=affmat, **kwargs)
```
...
...
This diff is collapsed.
Click to expand it.
advanced_topics/function_inputs_and_outputs.md
+
97
−
4
View file @
63df73d6
...
...
@@ -40,7 +40,7 @@ args = [3, 4, 5]
myfunc(*args)
```
You can think of the star operator as
'
unpacking
'
the contents of the
You can think of the star operator as
_
unpacking
_
the contents of the
sequence.
...
...
@@ -58,7 +58,7 @@ myfunc(c=3, b=2, a=1)
Python has another operator - the double-star (
`**`
), which will unpack
keyword arguments from
`dict`
. For example:
keyword arguments from
a
`dict`
. For example:
```
kwargs = {'a' : 4, 'b' : 5, 'c' : 6}
...
...
@@ -86,7 +86,7 @@ Function arguments can be given default values, like so:
```
myfunc(a=1, b=2, c=3):
def
myfunc(a=1, b=2, c=3):
print('First argument: ', a)
print('Second argument:', b)
print('Third argument: ', c)
...
...
@@ -141,4 +141,97 @@ This happens because default argument values are created when the function is
defined, and will persist for the duration of your program. So in this
example, the default value for
`a`
, a Python
`list`
, gets created when
`badfunc`
is defined, and hangs around for the lifetime of the
`badfunc`
function!
\ No newline at end of file
function!
## Variable numbers of arguments - `args` and `kwargs`
The
`*`
and
`**`
operators can also be used in function definitions - this
indicates that a function may accept a variable number of arguments.
Let's redefine
`myfunc`
to accept any number of positional arguments - here,
all positional arguments will be passed into
`myfunc`
as a tuple called
`args`
:
```
def myfunc(*args):
print('myfunc({})'.format(args))
print(' Number of arguments: {}'.format(len(args)))
for i, arg in enumerate(args):
print(' Argument {:2d}: {}'.format(i, arg))
myfunc()
myfunc(1)
myfunc(1, 2, 3)
myfunc(1, 'a', [3, 4])
```
Similarly, we can define a function to accept any number of keyword
arguments. In this case, the keyword arguments will be packed into a
`dict`
called
`kwargs`
:
```
def myfunc(**kwargs):
print('myfunc({})'.format(kwargs))
for k, v in kwargs.items():
print(' Argument {} = {}'.format(k, v))
myfunc()
myfunc(a=1, b=2)
myfunc(a='abc', foo=123)
```
This is a useful technique in many circumstances. For example, if you are
writing a function which calls another function that takes many arguments, you
can use
``**kwargs``
to pass-through arguments to the second function. As an
example, let's say we have functions
`flirt`
and
`fnirt`
, which respectively
perform linear and non-linear registration:
```
def flirt(infile,
ref,
outfile=None,
init=None,
omat=None,
dof=12):
# TODO get MJ to fill this bit in
pass
def fnirt(infile,
ref,
outfile=None,
aff=None,
interp='nn',
refmask=None,
minmet='lg',
subsamp=4):
# TODO get Jesper to fill this bit in
pass
```
We want to write our own registration function which uses the
`flirt`
and
`fnirt`
functions, while also allowing the
`fnirt`
parameters to be
customised. We can use
`**kwargs`
to do this:
```
def do_nonlinear_reg(infile, ref, outfile, **kwargs):
"""Aligns infile to ref using non-linear registration. All keyword
arguments are passed through to the fnirt function.
"""
affmat = '/tmp/aff.mat'
# calculate a rough initial linear alignemnt
flirt(infile, ref, omat=affmat)
fnirt(infile, ref, outfile, aff=affmat, **kwargs)
```
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment