Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #74807 > unrolled thread
| Started by | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| First post | 2014-07-19 03:52 -0700 |
| Last post | 2014-07-20 06:41 +0000 |
| Articles | 14 — 6 participants |
Back to article view | Back to comp.lang.python
Confused with Functions and decorators Jerry lu <nicholascannon1@gmail.com> - 2014-07-19 03:52 -0700
Re: Confused with Functions and decorators Chris Angelico <rosuav@gmail.com> - 2014-07-19 21:03 +1000
Re: Confused with Functions and decorators Jerry lu <nicholascannon1@gmail.com> - 2014-07-19 04:40 -0700
Re: Confused with Functions and decorators Chris Angelico <rosuav@gmail.com> - 2014-07-19 21:50 +1000
Re: Confused with Functions and decorators Wojciech Giel <wojtekgiel@gmail.com> - 2014-07-19 13:44 +0100
Re: Confused with Functions and decorators CHIN Dihedral <dihedral88888@gmail.com> - 2014-07-21 00:30 -0700
Re: Confused with Functions and decorators Steven D'Aprano <steve@pearwood.info> - 2014-07-21 07:45 +0000
Re: Confused with Functions and decorators Jerry lu <nicholascannon1@gmail.com> - 2014-07-19 05:01 -0700
Re: Confused with Functions and decorators Wojciech Giel <wojtekgiel@gmail.com> - 2014-07-19 13:06 +0100
Re: Confused with Functions and decorators Wojciech Giel <wojtekgiel@gmail.com> - 2014-07-19 13:10 +0100
Re: Confused with Functions and decorators Jerry lu <nicholascannon1@gmail.com> - 2014-07-19 19:24 -0700
Re: Confused with Functions and decorators Chris Angelico <rosuav@gmail.com> - 2014-07-20 12:27 +1000
Re: Confused with Functions and decorators Jerry lu <nicholascannon1@gmail.com> - 2014-07-19 19:33 -0700
Re: Confused with Functions and decorators Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2014-07-20 06:41 +0000
| From | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| Date | 2014-07-19 03:52 -0700 |
| Subject | Confused with Functions and decorators |
| Message-ID | <99846e1f-1ec1-4ed4-9ad4-5c8377b2e1f6@googlegroups.com> |
Ok so i am trying to learn this and i do not understand some of it. I also tried to searched the web but i couldnt find any answers.
1. I dont understand when i will need to use a function that returns another function.
eg
def outer():
def inner():
x = 5
return inner
why not just use inner and forget about the whole outer function?
2. This is more yes or no question when you pass in a func into another func as a parameter do you need to specify the parameter that the func is being passed into as func?
eg
def passinto(func)
pass
def param():
x = 5
p = passinto(param)
also is this above statement correct?????
[toc] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-07-19 21:03 +1000 |
| Message-ID | <mailman.12039.1405767838.18130.python-list@python.org> |
| In reply to | #74807 |
On Sat, Jul 19, 2014 at 8:52 PM, Jerry lu <nicholascannon1@gmail.com> wrote:
> Ok so i am trying to learn this and i do not understand some of it. I also tried to searched the web but i couldnt find any answers.
>
> 1. I dont understand when i will need to use a function that returns another function.
> eg
> def outer():
> def inner():
> x = 5
> return inner
>
> why not just use inner and forget about the whole outer function?
>
> 2. This is more yes or no question when you pass in a func into another func as a parameter do you need to specify the parameter that the func is being passed into as func?
> eg
> def passinto(func)
> pass
>
> def param():
> x = 5
>
> p = passinto(param)
>
> also is this above statement correct?????
In Python, a function is a real thing, on par with integers, lists,
modules, files, etc. You can create them, dispose of them, pass them
as parameters, receive them as return values, store them in lists,
everything. When you call outer(), it creates a function (which does
nothing useful, and then returns None) and returns a reference to it.
And yes, in that case, there's no particular value in that setup; but
an inner function can be a "closure" (you can look that up later):
def outer(x):
def inner(y):
return x + y
return inner
The x inside inner() will refer to the x that was in scope when it was
created, so you can call outer() several times with different
arguments and get back different functions that do different things.
Since functions are objects of equal standing to any other (called
"first-class" objects - look that up too), you can pass them as
parameters just the same as you would any other type of object.
There's no reason to call an integer 'i', so there's no reason to call
a function 'func'. You can if you like, but it'll work the same
regardless. There is no magic happening here.
None of this has anything to do with decorators, though.
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| Date | 2014-07-19 04:40 -0700 |
| Message-ID | <d45c2447-4dc8-47f1-b6fd-df5e1618fc77@googlegroups.com> |
| In reply to | #74807 |
oh yeah i forgot about the decorators. Um say that you wanted to decorate a function with the outer() func you would just put @outer on top of it? And this is the same as passing another func into the outer func? and also with the first example you say x is in the scope when is was created can you define x in the outer func and refer to it in the inner func?
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-07-19 21:50 +1000 |
| Message-ID | <mailman.12040.1405770644.18130.python-list@python.org> |
| In reply to | #74809 |
On Sat, Jul 19, 2014 at 9:40 PM, Jerry lu <nicholascannon1@gmail.com> wrote:
> oh yeah i forgot about the decorators. Um say that you wanted to decorate a function with the outer() func you would just put @outer on top of it? And this is the same as passing another func into the outer func?
>
> and also with the first example you say x is in the scope when is was created can you define x in the outer func and refer to it in the inner func?
Firstly, please don't use Google Groups, or if you must, please clean
up its messes. It's conventional on mailing lists and newsgroups to
quote a bit of text to give context; so, for instance, you mention one
of my examples, without quoting it.
Secondly: Don't worry about decorators. You almost never need them,
and they're very simple. (Python avoids magic whenever it can!) These
two are equivalent:
def inner():
pass
inner = outer(inner)
@outer
def inner():
pass
That's all the decorator does. It's that simple.
As to scoping... read up on closures. There's a lot that I could say,
but you'll find some excellent articles on the internet about it.
Also, you'll learn how to find information, which is a skill you are
going to need in this life :)
ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Wojciech Giel <wojtekgiel@gmail.com> |
|---|---|
| Date | 2014-07-19 13:44 +0100 |
| Message-ID | <mailman.12044.1405775046.18130.python-list@python.org> |
| In reply to | #74809 |
On 19/07/14 12:40, Jerry lu wrote:
> oh yeah i forgot about the decorators. Um say that you wanted to decorate a function with the outer() func you would just put @outer on top of it? And this is the same as passing another func into the outer func?
yes.
syntax was added because with very long function definitions it was
dificult to track reassignment to the name when it followed definition
of the function. decorators is just abbreviation.
>>> def outer(f):
... def inner(*args, **kwargs):
... print("inner function")
... return f(*args, **kwargs)
... return inner
...
>>> @outer
... def myfunc(x):
... print("Myfunc", x)
...
>>> myfunc("test")
inner function
Myfunc test
it is exactly equivalent to:
>>> def outer(f):
... def inner(*args, **kwargs):
... print("inner function")
... return f(*args, **kwargs)
... return inner
...
>>> def myfunc(x):
... print("Myfunc", x)
...
>>> myfunc = outer(myfunc)
>>> myfunc("test")
inner function
Myfunc test
cheers
Wojciech
>
> and also with the first example you say x is in the scope when is was created can you define x in the outer func and refer to it in the inner func?
check nonlocal.
[toc] | [prev] | [next] | [standalone]
| From | CHIN Dihedral <dihedral88888@gmail.com> |
|---|---|
| Date | 2014-07-21 00:30 -0700 |
| Message-ID | <49a2e178-62e7-4186-a32c-488a2fa530a6@googlegroups.com> |
| In reply to | #74816 |
On Saturday, July 19, 2014 8:44:25 PM UTC+8, Wojciech Giel wrote:
> On 19/07/14 12:40, Jerry lu wrote:
>
> > oh yeah i forgot about the decorators. Um say that you wanted to decorate a function with the outer() func you would just put @outer on top of it? And this is the same as passing another func into the outer func?
>
> yes.
>
> syntax was added because with very long function definitions it was
>
> dificult to track reassignment to the name when it followed definition
>
> of the function. decorators is just abbreviation.
>
>
>
> >>> def outer(f):
>
> ... def inner(*args, **kwargs):
>
> ... print("inner function")
>
> ... return f(*args, **kwargs)
>
> ... return inner
>
> ...
>
> >>> @outer
>
> ... def myfunc(x):
>
> ... print("Myfunc", x)
>
> ...
>
> >>> myfunc("test")
>
> inner function
>
> Myfunc test
>
>
>
> it is exactly equivalent to:
>
>
>
> >>> def outer(f):
>
> ... def inner(*args, **kwargs):
>
> ... print("inner function")
>
> ... return f(*args, **kwargs)
>
> ... return inner
>
> ...
>
> >>> def myfunc(x):
>
> ... print("Myfunc", x)
>
> ...
>
> >>> myfunc = outer(myfunc)
>
> >>> myfunc("test")
>
> inner function
>
> Myfunc test
>
>
>
> cheers
>
> Wojciech
>
> >
>
> > and also with the first example you say x is in the scope when is was created can you define x in the outer func and refer to it in the inner func?
>
> check nonlocal.
Uhn, a local object inside a function
can be passed back in Python.
Of course, a local function is treated
as an object in Python,and the GC is
built-in.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve@pearwood.info> |
|---|---|
| Date | 2014-07-21 07:45 +0000 |
| Message-ID | <53ccc50e$0$29897$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #74909 |
On Mon, 21 Jul 2014 00:30:00 -0700, CHIN Dihedral wrote: > Uhn, a local object inside a function can be passed back in Python. > > Of course, a local function is treated as an object in Python,and the GC > is built-in. Sigh, the Dihedral bot is not what it used to be... -- Steven
[toc] | [prev] | [next] | [standalone]
| From | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| Date | 2014-07-19 05:01 -0700 |
| Message-ID | <9f07f9b5-df7e-467f-8db1-f9fa294dc922@googlegroups.com> |
| In reply to | #74807 |
Ok thanks man I have never used forums and stuff before but it is great help thank you so much.
[toc] | [prev] | [next] | [standalone]
| From | Wojciech Giel <wojtekgiel@gmail.com> |
|---|---|
| Date | 2014-07-19 13:06 +0100 |
| Message-ID | <mailman.12042.1405775046.18130.python-list@python.org> |
| In reply to | #74807 |
On 19/07/14 11:52, Jerry lu wrote:
> Ok so i am trying to learn this and i do not understand some of it. I also tried to searched the web but i couldnt find any answers.
>
> 1. I dont understand when i will need to use a function that returns another function.
> eg
> def outer():
> def inner():
> x = 5
> return inner
>
> why not just use inner and forget about the whole outer function?
function compositing is one possible use. Functions are first class
objects so they can be passed as arguments to other functions. in math
you can define function composition f(x) * g(x) by saying that (f * g
)(x) = f(g(x)).
so composition of two functions gives you a new function with behaviour
the same as applying fist function to the output of the second.
ex.
you are give two functions f and g to construct their composition:
>>> def outer(f, g):
... def inner(x):
... return f(g(x))
... return inner
...
>>> def f(x):
... print("f ({}) called".format(x))
... return x
...
>>> def g(x):
... print("g ({}) called".format(x))
... return x
...
>>> h = outer(f, g)
>>> h("test")
g (test) called
f (test) called
'test'
> 2. This is more yes or no question when you pass in a func into another func as a parameter do you need to specify the parameter that the func is being passed into as func?
> eg
> def passinto(func)
> pass
>
> def param():
> x = 5
>
> p = passinto(param)
>
> also is this above statement correct?????
>
[toc] | [prev] | [next] | [standalone]
| From | Wojciech Giel <wojtekgiel@gmail.com> |
|---|---|
| Date | 2014-07-19 13:10 +0100 |
| Message-ID | <mailman.12043.1405775046.18130.python-list@python.org> |
| In reply to | #74807 |
On 19/07/14 11:52, Jerry lu wrote:
> Ok so i am trying to learn this and i do not understand some of it. I also tried to searched the web but i couldnt find any answers.
>
> 1. I dont understand when i will need to use a function that returns another function.
> eg
> def outer():
> def inner():
> x = 5
> return inner
>
> why not just use inner and forget about the whole outer function?
function compositing is one possible use. Functions are first class
objects so they can be passed as arguments to other functions. in math
you can define function composition f(x) * g(x) by saying that (f * g
)(x) = f(g(x)).
so composition of two functions gives you a new function with behaviour
the same as applying fist function to the output of the second.
ex.
you are give two functions f and g to construct their composition:
>>> def outer(f, g):
... def inner(x):
... return f(g(x))
... return inner
...
>>> def f(x):
... print("f ({}) called".format(x))
... return x
...
>>> def g(x):
... print("g ({}) called".format(x))
... return x
...
>>> h = outer(f, g)
>>> h("test")
g (test) called
f (test) called
'test'
cheers
Wojciech
[toc] | [prev] | [next] | [standalone]
| From | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| Date | 2014-07-19 19:24 -0700 |
| Message-ID | <140fdf49-b4db-45a5-a52d-1b5ae89e7bd3@googlegroups.com> |
| In reply to | #74807 |
ok I seem to very confused about this. Is there like a page or web page that like completely sums this up so i can study. I am going to look up 'functions in python'. I am not sure if this is what we a talking about as a whole here but I'am sure that I'll find something. I am all good with decorators just I can't wrap my head around why we need a function within a function? like the outer and inner thing. for example if we have like:
>>> def multi_squared(func):
def multi():
return (func)**2
return math
>>>
>>>@math #does decorator go here or when we call the function???
>>>def number(x, y):
return x*y
is this above example valid? like this is the stuff i am stuck on like i know what todo or i think i know but not sure if it is perfectly valid. I am going to search for something now but if you know where i could find something like this or if you could sort it out that would be great.
[toc] | [prev] | [next] | [standalone]
| From | Chris Angelico <rosuav@gmail.com> |
|---|---|
| Date | 2014-07-20 12:27 +1000 |
| Message-ID | <mailman.12081.1405823241.18130.python-list@python.org> |
| In reply to | #74859 |
On Sun, Jul 20, 2014 at 12:24 PM, Jerry lu <nicholascannon1@gmail.com> wrote: > ok I seem to very confused about this. Is there like a page or web page that like completely sums this up so i can study. I am going to look up 'functions in python'. Yep, look up stuff like that. I gave you some keywords to search for (web search - Google, Bing, Yahoo, whatever you're comfortable with) in my last email. They'll start you off with some of the important topics. ChrisA
[toc] | [prev] | [next] | [standalone]
| From | Jerry lu <nicholascannon1@gmail.com> |
|---|---|
| Date | 2014-07-19 19:33 -0700 |
| Message-ID | <6a3acf78-a7d8-4bb4-b6d7-0f08ce70613a@googlegroups.com> |
| In reply to | #74860 |
Ok thanks so much i really want to get good. I also found this MIT open course lectures for python. Is this good to use as a source of learning? I think it would because it is MIT.
[toc] | [prev] | [next] | [standalone]
| From | Steven D'Aprano <steve+comp.lang.python@pearwood.info> |
|---|---|
| Date | 2014-07-20 06:41 +0000 |
| Message-ID | <53cb6484$0$6574$c3e8da3$5496439d@news.astraweb.com> |
| In reply to | #74807 |
On Sat, 19 Jul 2014 03:52:18 -0700, Jerry lu wrote:
> Ok so i am trying to learn this and i do not understand some of it. I
> also tried to searched the web but i couldnt find any answers.
>
> 1. I dont understand when i will need to use a function that returns
> another function. eg
> def outer():
> def inner():
> x = 5
> return inner
>
> why not just use inner and forget about the whole outer function?
For the example given, there's no point in using an inner function.
(Especially since the inner function does nothing useful.) But there are
three common reasons for writing inner functions:
#1 Encapsulation and information hiding.
If you've ever programmed in Pascal, this may be familiar to you. You use
inner functions to hide them away from code outside of the function. Here
is a toy example that shows the basic idea:
def function(x):
def increment(x):
return x + 1
y = increment(x)
print x, y
In Python, I would rarely bother to write code like that. I'd just make
the increment function a top-level function, marked as "private" with a
leading underscore: _increment.
One place where the Pascal-style nested function may be useful is with
recursive functions:
def factorial(n):
if not isinstance(n, int):
raise TypeError("n must be an integer")
if not n >= 0:
raise ValueError("n must be zero or positive")
def inner_fact(n):
if n <= 1:
return 1
return n*inner_fact(n-1)
return inner_fact(n)
This has three advantages:
* The caller cannot (easily) bypass the outer function and call the inner
function directly.
* The outer function performs all the argument checking and any pre-
processing once only, the inner function can safely assume the argument
is valid and eschew pointless error checking.
* The outer function can be renamed without breaking the recursion.
#2 Don't Repeat Yourself (DRY)
Sometimes you may have a big function that performs the same chunk of
code in two places. For example, you might write a function which
processes a file, and you want to accept either an open file object or a
file name:
def process(the_file):
def do_stuff(fp):
for line in fp:
print line
if isinstance(the_file, str):
with open(the_file, 'r') as f:
do_stuff(f)
else:
do_stuff(the_file)
Again, it is common to put do_stuff as a private top-level function, but
if you want to hide it away as an internal function, you can.
#3 Closures and factory functions
But now we come to the most important reason to use internal functions.
All of the inner functions I've shown so far have been ordinary functions
that merely happened to be nested inside another function. But when we
come to closures, that is not the case.
A closure is an inner function which "remembers" the state of its
environment when called. Here's a basic example:
def make_incrementer(inc):
"""Make an new function which increments its argument by inc.
Examples of use:
>>> add_one = make_incrementer(1)
>>> add_two = make_incrementer(2)
>>> add_one(7)
8
>>> add_two(7)
9
"""
def incrementer(x):
return x + inc
return incrementer
This takes more effort to explain than to write!
The "make_incrementer" function is a *factory function*. It builds a new
function each time it is called, then returns it. What does this new,
inner, function do? It takes a single argument, x, and returns x + inc.
Where does the inner function get the value of inc from? This is what
makes it a closure -- it gets the value of inc from the outer function,
the factory. How it works is something like like this:
make_incrementer(3)
=> build a function "incrementer" which takes a single argument x
=> take a snap-shot of the state of make_incrementer function
which includes inc=3
=> stuff that snap-shot into the incrementer function
=> return the incrementer function
Now, whenever you call that newly returned function, it will always see
its own private snap-shot that includes inc=3.
The use of closures and factory functions is the most common, and
powerful, use for inner functions. 9 times out of 10, if you see a
decoratored function:
@decorator
def func(arg):
pass
the decorator is a factory function which takes an function as argument,
and returns a new function which which includes the old function inside
the closure. But that's now getting into more advanced territory.
> 2. This is more yes or no question when you pass in a func into another
> func as a parameter do you need to specify the parameter that the func
> is being passed into as func?
No.
You can pass functions around from place to place until the cows come
how, stuff them into lists and dicts, extract them again, and not care
one iota about its arguments until you actually call it.
--
Steven
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web