Re: self question

2006-07-27 Thread Duncan Booth
Mike wrote:

> I think the answer is that 'def' is an executable statement in python
> rather than a definition that the compiler interprets at compile time.
> 
> As a result the compiler can evaluate 'foo()' when it defines 'bar', so
> it does.
> 
> The following works as expected:
> def bar():
>   print foo()
> 
> Hopefully somebody more knowledgable will also respond
> 

The def statement is, as you say, an executable statement. It creates a new 
function object, so it is quite useful to look directly at the function 
type to see what arguments its constructor takes:

>>> import types
>>> help(types.FunctionType)
Help on class function in module __builtin__:

class function(object)
 |  function(code, globals[, name[, argdefs[, closure]]])
 |  
 |  Create a function object from a code object and a dictionary.
 |  The optional name string overrides the name from the code object.
 |  The optional argdefs tuple specifies the default argument values.
 |  The optional closure tuple supplies the bindings for free variables.
...

The arguments passed to the constructor when the def statement is executed 
are:

a code object. This object is created once when the module containing the 
function is compiled. The def doesn't have to do anything with the actual 
code, so it will take the same time whether you def a function of 1 line or 
1000 lines.

globals is the same value as you get by calling the builtin globals().

name is the function name. It's a string constant.

argdefs is the interesting one here. It is a tuple of the default argument 
values and is created every time the def statement is executed.

closure is another tuple which is created every time the def statement is 
executed. This allows a def nested inside another function to reference the 
current local variables which are in scope when the def executes. This 
tuple can only contain cell objects which are an internal object type used 
for scoped variables.

So, argdefs and closure are the two things which are different each time 
you def a function, everything else is constant and shared between 
definitions of the same function.
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: self question

2006-07-26 Thread Mike

Schüle Daniel wrote:
> Hi all,
>
> given python description below
>
> import random
>
> class Node:
>  def __init__(self):
>  self.nachbarn = []
>
> class Graph(object):
>   # more code here
>  def randomizeEdges(self, low=1, high=self.n):
>  pass
>
>
> graph = Graph(20)
> graph.randomizeEdges(2,5)
>
> I am burned by high=self.n
> quick test with
>
> cnt = 1
> def foo():
>   global cnt
>   cnt += 1
>   return cnt
>
> def bar(x=foo()):
>   print x
>
> bar() # 2
> bar() # 2
> bar() # 2
>
> this is not behaviour C++ programmer would expect
> does someone know why this kind of behaviour is/was choosen?
>
> Regards, Daniel

I think the answer is that 'def' is an executable statement in python
rather than a definition that the compiler interprets at compile time.

As a result the compiler can evaluate 'foo()' when it defines 'bar', so
it does.

The following works as expected:
def bar():
  print foo()

Hopefully somebody more knowledgable will also respond

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: self question

2006-07-26 Thread Chris Lambacher
On Tue, Jul 25, 2006 at 08:08:32PM +0200, Sch?le Daniel wrote:
> [EMAIL PROTECTED] schrieb:
> >> cnt = 1
> >> def foo():
> >>global cnt
> >>cnt += 1
> >>return cnt
> >>
> >> def bar(x=foo()):
> >>print x
> >>
> >> bar()  # 2
> >> bar()  # 2
> >> bar()  # 2
> > 
> > Looks to me like you want to use the following programming pattern to
> > get dynamic default arguments:
> > 
> > cnt = 1
> > def foo():
> > global cnt
> > cnt += 1
> > return cnt
> > 
> > def bar(x=None):
> > if x is None:
> > x = foo()
> > print x
> >  
> > bar()   # 2
> > bar()   # 3
> > bar()   # 4
> 
> yes, I haven't thought of that
> nowI changed my class to
> 
> class Graph:
>   settings = {
>   "NumNodes" : 10,
>   "MinNodes" : 2,
>   "MaxNodes" : 5
>   }
>   def randomizeEdges(self,
>   lowhigh = (settings["MinNodes"], settings["MaxNodes"])):
Note that this is a change in behaviour from what you originally stated you
wanted.  settings is a dictionary that is shared between all instances of
Graph.  The previous poster was suggesting the correct pattern for the
behaviour you requested.  Generally if you want a parameter to have a dynamic
default argument you set the default value to None, test for None in the body
of the function/method and set the value appropriately.
>   low, high = lowhigh
>   for node in self.nodes:
>   x = random.randint(low, high)
>   # link the nodes
> 
> 
> maybe the only minor point is that no relationship
> can be expressed
> 
> settings = {
>   "NumNode" : 10,
>   "MinNode" : settings["NumNode"] / 2,
>   "MaxNode" : settings["NumNode"]
> }
> 
> but I think the solution is nevertheless ok
> 
> 
> Regards, Daniel
> -- 
> http://mail.python.org/mailman/listinfo/python-list
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: self question

2006-07-25 Thread Schüle Daniel
correction :)

> class Graph:
> settings = {
> "NumNodes" : 10,
> "MinNodes" : 2,
> "MaxNodes" : 5
> }
> def randomizeEdges(self,
> lowhigh = (settings["MinNodes"], settings["MaxNodes"])):

of course this should be
  Graph.settings["MinNodes"], Graph.settings["MaxNodes"])
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: self question

2006-07-25 Thread Schüle Daniel
[EMAIL PROTECTED] schrieb:
>> cnt = 1
>> def foo():
>>  global cnt
>>  cnt += 1
>>  return cnt
>>
>> def bar(x=foo()):
>>  print x
>>
>> bar()# 2
>> bar()# 2
>> bar()# 2
> 
> Looks to me like you want to use the following programming pattern to
> get dynamic default arguments:
> 
> cnt = 1
> def foo():
>   global cnt
>   cnt += 1
>   return cnt
> 
> def bar(x=None):
>   if x is None:
>   x = foo()
>   print x
>  
> bar() # 2
> bar() # 3
> bar() # 4

yes, I haven't thought of that
nowI changed my class to

class Graph:
settings = {
"NumNodes" : 10,
"MinNodes" : 2,
"MaxNodes" : 5
}
def randomizeEdges(self,
lowhigh = (settings["MinNodes"], settings["MaxNodes"])):
low, high = lowhigh
for node in self.nodes:
x = random.randint(low, high)
# link the nodes


maybe the only minor point is that no relationship
can be expressed

settings = {
"NumNode" : 10,
"MinNode" : settings["NumNode"] / 2,
"MaxNode" : settings["NumNode"]
}

but I think the solution is nevertheless ok


Regards, Daniel
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: self question

2006-07-25 Thread dan . gass
> cnt = 1
> def foo():
>   global cnt
>   cnt += 1
>   return cnt
>
> def bar(x=foo()):
>   print x
>
> bar() # 2
> bar() # 2
> bar() # 2

Looks to me like you want to use the following programming pattern to
get dynamic default arguments:

cnt = 1
def foo():
global cnt
cnt += 1
return cnt

def bar(x=None):
if x is None:
x = foo()
print x
 
bar()   # 2
bar()   # 3
bar()   # 4

-- 
http://mail.python.org/mailman/listinfo/python-list