self question

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Schüle Daniel

    #1

    self question

    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.randomize Edges(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
  • dan.gass@gmail.com

    #2
    Re: self question

    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

    Comment

    • Schüle Daniel

      #3
      Re: self question

      dan.gass@gmail. com 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

      Comment

      • Schüle Daniel

        #4
        Re: self question

        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"])

        Comment

        • Chris Lambacher

          #5
          Re: self question

          On Tue, Jul 25, 2006 at 08:08:32PM +0200, Sch?le Daniel wrote:
          dan.gass@gmail. com 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

          Comment

          • Mike

            #6
            Re: self question


            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.randomize Edges(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

            Comment

            • Duncan Booth

              #7
              Re: self question

              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.Fu nctionType)
              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.

              Comment

              Working...