singletons

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Craig Allen

    singletons

    Hey, forgive me for just diving in, but I have a question I was
    thinking of asking on another list but it really is a general question
    so let me ask it here. It's about how to approach making singletons.
    Background: I've been programming in python seriously for about a year
    now, maybe a little longer depending how you count, and the system I
    am making is sophisticated enough that I've had to enter into a few
    idioms which were beyond my knowledge of python, and I had to do quick
    research and test my ideas with test code (which of course can miss
    subtle problems). Otoh, I have decades of programming experience now
    and wasn't totally without footing. I think I have a solution I like
    for creating something to act as a singleton but I'm curious what
    other's think.

    I have several classes in our system which need to act like
    singletons, they are libraries of data classifications , and other such
    libraries of configurations for the system which need to be global.

    The first thing I found searching for singleton, early in this
    project, trying to be a good citizen and find a decent idiom from the
    python community itself, knowing someone had mentioned "singleton" and
    "python" together at some point, was a recommendation to do this:

    (option 1)

    class TehLibrary(obje ct):
    __single = None
    def __init__(self):
    if (TehLibrary.__s ingle):
    raise AlreadyExistsEx ception # or whatever

    This sucks because that means creation of the object has to be in a
    try block as a matter of course, something I promptly hid in a factory
    function, but still.

    But the way this worked made me realize that the Class itself is a
    full fledged object, quite instance-like from my C++ addled (I love
    you C++) perspective and it's single. If I can store that instance, I
    can make a class that shares member at the class level. The class
    doesn't even have to be a singleton exactly.

    (option 2)
    Therefore option two is a family of options where class level members
    can be used to share whatever needs to be shared, though strictly the
    class is not a singleton since multiple instances are created which
    merely share the data that should be single (say a big dictionary of
    configuration information the class manages).

    (option 3)
    I still wanted actual singletons and realized that since I had to
    create a factory function even in option 1, that I could use module
    level variables to control the behavior of those factories, which led
    me to realize I'm basically just using the module itself as a
    singleton. And this is sort of where I have arrived... when I import
    the modules it runs code to build up it's basic services, much like an
    object construction. It only runs once no matter how many times it's
    imported. When client code asks for the library that should be a
    singleton, it gets a singleton which has been stored in a module level
    variable.

    Anyone have any comments? Is there anything wrong, evil, or ugly
    about using a module this way, or am I correct to think that actually,
    this is a common approach in python.

    Is it pythonic?
  • castironpi

    #2
    Re: singletons

    On Jul 16, 5:20 pm, Craig Allen <callen...@gmai l.comwrote:
    Hey, forgive me for just diving in, but I have a question I was
    thinking of asking on another list but it really is a general question
    so let me ask it here.  It's about how to approach making singletons.
    Background: I've been programming in python seriously for about a year
    now, maybe a little longer depending how you count, and the system I
    am making is sophisticated enough that I've had to enter into a few
    idioms which were beyond my knowledge of python, and I had to do quick
    research and test my ideas with test code (which of course can miss
    subtle problems).  Otoh, I have decades of programming experience now
    and wasn't totally without footing.  I think I have a solution I like
    for creating something to act as a singleton but I'm curious what
    other's think.
    >
    I have several classes in our system which need to act like
    singletons, they are libraries of data classifications , and other such
    libraries of configurations for the system which need to be global.
    >
    The first thing I found searching for singleton, early in this
    project, trying to be a good citizen and find a decent idiom from the
    python community itself, knowing someone had mentioned "singleton" and
    "python" together at some point, was a recommendation to do this:
    >
    (option 1)
    >
    class TehLibrary(obje ct):
       __single = None
       def __init__(self):
          if (TehLibrary.__s ingle):
             raise AlreadyExistsEx ception # or whatever
    >
    This sucks because that means creation of the object has to be in a
    try block as a matter of course, something I promptly hid in a factory
    function, but still.
    >
    But the way this worked made me realize that the Class itself is a
    full fledged object, quite instance-like from my C++ addled (I love
    you C++) perspective and it's single.  If I can store that instance, I
    can make a class that shares member at the class level. The class
    doesn't even have to be a singleton exactly.
    >
    (option 2)
    Therefore option two is a family of options where class level members
    can be used to share whatever needs to be shared, though strictly the
    class is not a singleton since multiple instances are created which
    merely share the data that should be single (say a big dictionary of
    configuration information the class manages).
    >
    (option 3)
    I still wanted actual singletons and realized that since I had to
    create a factory function even in option 1, that I could use module
    level variables to control the behavior of those factories, which led
    me to realize I'm basically just using the module itself as a
    singleton. And this is sort of where I have arrived... when I import
    the modules it runs code to build up it's basic services, much like an
    object construction.  It only runs once no matter how many times it's
    imported. When client code asks for the library that should be a
    singleton, it gets a singleton which has been stored in a module level
    variable.
    >
    Anyone have any comments?  Is there anything wrong, evil, or ugly
    about using a module this way, or am I correct to think that actually,
    this is a common approach in python.
    >
    Is it pythonic?
    In option 1, you could use the __new__ method, and return the existing
    instance if there is one, or, I believe, call __init__ on the
    superclass. Alternatively, define your own 'create' method with the
    @classmethod decorator, instantiate with ClassA.create( ), and return
    any existing instance from there. The catch is you need to rely on
    the discipline of not using the default instantiation syntax.

    In option 2, you would have to wrap the functions with the
    @staticmethod decorator, and all instance methods would act on the
    same object.

    Each of these have different consequences for inheritance, if that is
    on the horizon in your project.

    Comment

    • Craig Allen

      #3
      Re: singletons

      I don't intend to do much subclassing of this, but of course, I'd
      rather not second guess the future and it's not hard to imagine we
      will come to some point that we need to do just that. Thanks for the
      ideas about repairing option one, which I'd given up, though the ideal
      is still that

      tl = TehLibrary() would always return the same object.

      -craig

      On Jul 16, 2:00 pm, castironpi <castiro...@gma il.comwrote:
      On Jul 16, 5:20 pm, Craig Allen <callen...@gmai l.comwrote:
      >
      >
      >
      Hey, forgive me for just diving in, but I have a question I was
      thinking of asking on another list but it really is a general question
      so let me ask it here. It's about how to approach making singletons.
      Background: I've been programming in python seriously for about a year
      now, maybe a little longer depending how you count, and the system I
      am making is sophisticated enough that I've had to enter into a few
      idioms which were beyond my knowledge of python, and I had to do quick
      research and test my ideas with test code (which of course can miss
      subtle problems). Otoh, I have decades of programming experience now
      and wasn't totally without footing. I think I have a solution I like
      for creating something to act as a singleton but I'm curious what
      other's think.
      >
      I have several classes in our system which need to act like
      singletons, they are libraries of data classifications , and other such
      libraries of configurations for the system which need to be global.
      >
      The first thing I found searching for singleton, early in this
      project, trying to be a good citizen and find a decent idiom from the
      python community itself, knowing someone had mentioned "singleton" and
      "python" together at some point, was a recommendation to do this:
      >
      (option 1)
      >
      class TehLibrary(obje ct):
      __single = None
      def __init__(self):
      if (TehLibrary.__s ingle):
      raise AlreadyExistsEx ception # or whatever
      >
      This sucks because that means creation of the object has to be in a
      try block as a matter of course, something I promptly hid in a factory
      function, but still.
      >
      But the way this worked made me realize that the Class itself is a
      full fledged object, quite instance-like from my C++ addled (I love
      you C++) perspective and it's single. If I can store that instance, I
      can make a class that shares member at the class level. The class
      doesn't even have to be a singleton exactly.
      >
      (option 2)
      Therefore option two is a family of options where class level members
      can be used to share whatever needs to be shared, though strictly the
      class is not a singleton since multiple instances are created which
      merely share the data that should be single (say a big dictionary of
      configuration information the class manages).
      >
      (option 3)
      I still wanted actual singletons and realized that since I had to
      create a factory function even in option 1, that I could use module
      level variables to control the behavior of those factories, which led
      me to realize I'm basically just using the module itself as a
      singleton. And this is sort of where I have arrived... when I import
      the modules it runs code to build up it's basic services, much like an
      object construction. It only runs once no matter how many times it's
      imported. When client code asks for the library that should be a
      singleton, it gets a singleton which has been stored in a module level
      variable.
      >
      Anyone have any comments? Is there anything wrong, evil, or ugly
      about using a module this way, or am I correct to think that actually,
      this is a common approach in python.
      >
      Is it pythonic?
      >
      In option 1, you could use the __new__ method, and return the existing
      instance if there is one, or, I believe, call __init__ on the
      superclass. Alternatively, define your own 'create' method with the
      @classmethod decorator, instantiate with ClassA.create( ), and return
      any existing instance from there. The catch is you need to rely on
      the discipline of not using the default instantiation syntax.
      >
      In option 2, you would have to wrap the functions with the
      @staticmethod decorator, and all instance methods would act on the
      same object.
      >
      Each of these have different consequences for inheritance, if that is
      on the horizon in your project.

      Comment

      • Asun Friere

        #4
        Re: singletons

        On Jul 17, 8:20 am, Craig Allen <callen...@gmai l.comwrote:
        Is it pythonic?
        You probably can't get anymore pythonic than something written by the
        BDFL. In describing the use of __new__ in <i>Unifying types and
        classes in Python 2.2</ihe gives this recipe for a Singleton.


        class Singleton(objec t):
        def __new__(cls, *args, **kwds):
        it = cls.__dict__.ge t("__it__")
        if it is not None:
        return it
        cls.__it__ = it = object.__new__( cls)
        it.init(*args, **kwds)
        return it
        def init(self, *args, **kwds):
        pass

        You might find this a useful starting point.

        Comment

        • Lawrence D'Oliveiro

          #5
          Re: singletons

          In message
          <e2ef1d2c-f39b-43e2-a848-0cb7660fd9fa@l4 2g2000hsc.googl egroups.com>, Craig
          Allen wrote:
          ... the ideal is still that
          >
          tl = TehLibrary() would always return the same object.
          >class TehLibrary(obje ct) :
          .... @classmethod
          .... def __new__(self, cls) :
          .... return self
          >>s = TehLibrary()
          >>s == TehLibrary()
          True

          Comment

          • Carl Banks

            #6
            Re: singletons

            On Jul 16, 6:20 pm, Craig Allen <callen...@gmai l.comwrote:
            Anyone have any comments?  Is there anything wrong, evil, or ugly
            about using a module this way, or am I correct to think that actually,
            this is a common approach in python.
            >
            Is it pythonic?

            The one drawback to this is that it could require lots of globals
            definitions. Whereas in a regular class you could do this:

            def something(self) :
            self.var = 1
            self.max = 10

            using a module as a singleton you'd be doing this:

            def something():
            global var
            global max
            var = 1
            max = 10


            If you have a lot of "attributes " of your module to redefine, I'd
            suggest taking steps to avoid globals. The most straightforward way
            is to define a self variable in your module that is bound to the
            module itself, and access all "attributes " through that. The
            following code should suffice (though it may not work in some corner
            cases):

            self = sys.modules[__name__]

            So then you could rewrite the something method like so:

            def something():
            self.var = 1
            self.max = 10


            [Another possibility, and this is what I do, is to use a function
            decorator that passes the module in as the first argument. I have
            reasons for doing it but it doesn't do anything the above method
            does. It would be used like this:

            @modmethod
            def something(self) :
            self.var = 1
            self.max = 10

            ]


            Carl Banks

            Comment

            • Craig Allen

              #7
              Re: singletons

              On Jul 16, 7:01 pm, Lawrence D'Oliveiro <l...@geek-
              central.gen.new _zealandwrote:
              In message
              <e2ef1d2c-f39b-43e2-a848-0cb7660fd...@l4 2g2000hsc.googl egroups.com>, Craig
              >
              Allen wrote:
              ... the ideal is still that
              >
              tl = TehLibrary() would always return the same object.
              class TehLibrary(obje ct) :
              >
              ... @classmethod
              ... def __new__(self, cls) :
              ... return self
              >
              >s = TehLibrary()
              >s == TehLibrary()
              >
              True
              That's great, I simply didn't find that when looking. Thanks!

              Comment

              • Uwe Schmitt

                #8
                Re: singletons

                On 17 Jul., 00:20, Craig Allen <callen...@gmai l.comwrote:
                >
                I have several classes in our system which need to act like
                singletons, they are libraries of data classifications , and other such
                libraries of configurations for the system which need to be global.
                ...
                >
                Is it pythonic?
                My approach in this situation is to use the Borg pattern instead
                of singeltons. This is really pythonic, very simple and usefull.

                Look at http://aspn.activestate.com/ASPN/Coo...n/Recipe/66531
                The german wikipedia shows another solution using metaclasse:


                Greetings, Uwe

                Comment

                • Craig Allen

                  #9
                  Re: singletons

                  On Jul 17, 2:15 am, Uwe Schmitt <rocksportroc.. .@googlemail.co m>
                  wrote:
                  On 17 Jul., 00:20, Craig Allen <callen...@gmai l.comwrote:
                  >
                  >
                  >
                  I have several classes in our system which need to act like
                  singletons, they are libraries of data classifications , and other such
                  libraries of configurations for the system which need to be global.
                  ...
                  >
                  Is it pythonic?
                  >
                  My approach in this situation is to use the Borg pattern instead
                  of singeltons. This is really pythonic, very simple and usefull.
                  >
                  Look athttp://aspn.activestat e.com/ASPN/Cookbook/Python/Recipe/66531
                  The german wikipedia shows another solution using metaclasse:http://de.wikipedia.org/wiki/Singlet...s_Borg-Pattern
                  >
                  Greetings, Uwe
                  thanks uwe, doing some searching I ran into the borg pattern this
                  morning. Definitely relevant.

                  Thanks again and all for the feedback, I feel much reassured about the
                  options when this sort of thing is required.

                  Comment

                  • Lawrence D'Oliveiro

                    #10
                    Re: singletons

                    In message
                    <98eae1fc-ff34-4dcc-b46d-9e3da2850c28@r6 6g2000hsg.googl egroups.com>, Craig
                    Allen wrote:
                    On Jul 16, 7:01 pm, Lawrence D'Oliveiro <l...@geek-
                    central.gen.new _zealandwrote:
                    >>
                    >>class TehLibrary(obje ct) :
                    >>
                    >... @classmethod
                    >... def __new__(self, cls) :
                    >... return self
                    >>
                    >>s = TehLibrary()
                    >>s == TehLibrary()
                    >>
                    >True
                    >
                    That's great, I simply didn't find that when looking. Thanks!
                    Also note that

                    s == TehLibrary

                    will be true (the instance equals the class). I assume that doesn't matter
                    for your purposes. :)

                    Comment

                    • Paddy

                      #11
                      Re: singletons

                      On Jul 16, 11:20 pm, Craig Allen <callen...@gmai l.comwrote:
                      Hey, forgive me for just diving in, but I have a question I was
                      thinking of asking on another list but it really is a general question
                      so let me ask it here.  It's about how to approach making singletons.
                      Hi Craig,
                      This might be good for a general background on Design Patters in
                      Python:



                      - Paddy.

                      Comment

                      • Craig Allen

                        #12
                        Re: singletons

                        On Jul 17, 9:04 pm, Paddy <paddy3...@goog lemail.comwrote :
                        On Jul 16, 11:20 pm, Craig Allen <callen...@gmai l.comwrote:
                        >
                        Hey, forgive me for just diving in, but I have a question I was
                        thinking of asking on another list but it really is a general question
                        so let me ask it here. It's about how to approach making singletons.
                        >
                        Hi Craig,
                        This might be good for a general background on Design Patters in
                        Python:
                        >

                        >
                        - Paddy.
                        thanks for the link paddy, I'll watch it.

                        Comment

                        • Aahz

                          #13
                          Re: singletons

                          In article <2476438f-eaa2-495f-95fa-eb9efec25875@e3 9g2000hsf.googl egroups.com>,
                          Craig Allen <callen314@gmai l.comwrote:
                          >
                          >(option 2)
                          >Therefore option two is a family of options where class level members
                          >can be used to share whatever needs to be shared, though strictly the
                          >class is not a singleton since multiple instances are created which
                          >merely share the data that should be single (say a big dictionary of
                          >configuratio n information the class manages).
                          That's only true if you actually instantiate the class. You can just
                          use the class directly -- that's what I do.
                          --
                          Aahz (aahz@pythoncra ft.com) <* http://www.pythoncraft.com/

                          Adopt A Process -- stop killing all your children!

                          Comment

                          Working...