What do you call a class not intended to be instantiated

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Steven D'Aprano

    What do you call a class not intended to be instantiated

    I have a class which is not intended to be instantiated. Instead of using
    the class to creating an instance and then operate on it, I use the class
    directly, with classmethods. Essentially, the class is used as a function
    that keeps state from one call to the next.

    The problem is that I don't know what to call such a thing! "Abstract
    class" isn't right, because that implies that you should subclass the
    class and then instantiate the subclasses.

    What do you call such a class?



    --
    Steven
  • James Mills

    #2
    Re: What do you call a class not intended to be instantiated

    Hi,

    Wouldn't a normal class called State
    suffice for storing state between calls ?
    And ... Creating a state instance ?

    For example:

    class State(object):
    """State() -new state object

    Creates a new state object that is suitable
    for holding different states of an application.
    Usefull in state-machines.

    The way this works is rather simple. You create a new
    state object, and simply set the state. If the state
    doesn't exist, it's added to it's internal data
    structure. The reason this is done is so that
    comparing states is consistent, and you can't just
    compare with a non-existent state.
    """

    def __init__(self):
    "initialize s x; see x.__class__.__d oc__ for signature"

    self._states = {}
    self._next = 0

    # Default States

    self._add("STAR T")
    self._add("DONE ")

    def __repr__(self):
    try:
    return "<State: %s>" % self._state
    except AttributeError:
    return "<State: ???>"

    def __str__(self):
    return self._state

    def __eq__(self, s):
    return s in self._states and self._state == s

    def __lt__(self, s):
    return s in self._states and self._state == s and \
    self._states[s] < self._states[self._state]

    def __gr__(self, s):
    return s in self._states and self._state == s and \
    self._states[s] self._states[self._state]

    def _add(self, s):
    self._states[s] = self._next
    self._next = self._next + 1

    def set(self, s):
    """S.set(s) -None

    Set the current state to the specified state given by s,
    adding it if it doesn't exist.
    """

    if s not in self._states:
    self._add(s)

    self._state = s

    cheers
    James

    On Mon, Sep 22, 2008 at 8:39 AM, Steven D'Aprano
    <steve@remove-this-cybersource.com .auwrote:
    I have a class which is not intended to be instantiated. Instead of using
    the class to creating an instance and then operate on it, I use the class
    directly, with classmethods. Essentially, the class is used as a function
    that keeps state from one call to the next.
    >
    The problem is that I don't know what to call such a thing! "Abstract
    class" isn't right, because that implies that you should subclass the
    class and then instantiate the subclasses.
    >
    What do you call such a class?
    >
    >
    >
    --
    Steven
    --

    >


    --
    --
    -- "Problems are solved by method"

    Comment

    • Steven D'Aprano

      #3
      Re: What do you call a class not intended to be instantiated

      Fixing top-posting.

      On Mon, 22 Sep 2008 08:54:43 +1000, James Mills wrote:
      On Mon, Sep 22, 2008 at 8:39 AM, Steven D'Aprano
      <steve@remove-this-cybersource.com .auwrote:
      >I have a class which is not intended to be instantiated. Instead of
      >using the class to creating an instance and then operate on it, I use
      >the class directly, with classmethods. Essentially, the class is used
      >as a function that keeps state from one call to the next.
      [...]
      Hi,
      >
      Wouldn't a normal class called State
      suffice for storing state between calls ? And ... Creating a state
      instance ?
      >
      For example:
      [snip]

      That's a rather big example for a rather small question.

      Yes, a normal class would work in many cases. In this case, the class
      itself is being produced by a factory function, and it's output is an
      iterator. Having to call:

      cls = factory()
      instance = cls()
      result = instance()

      to get anything done seems excessive, even if you write it as a one-liner
      result = factory()()().

      I'm not wedded to the idea, there are alternatives (perhaps the factory
      should instantiate the class and return that?) but I assume others have
      used this design and have a name for it.


      --
      Steven

      Comment

      • James Mills

        #4
        Re: What do you call a class not intended to be instantiated

        On Mon, Sep 22, 2008 at 9:05 AM, Steven D'Aprano
        <steve@remove-this-cybersource.com .auwrote:
        I'm not wedded to the idea, there are alternatives (perhaps the factory
        should instantiate the class and return that?) but I assume others have
        used this design and have a name for it.
        The problem is, I don't see why you're using a class
        to store state in the first place.

        cheers
        James

        --
        --
        -- "Problems are solved by method"

        Comment

        • bearophileHUGS@lycos.com

          #5
          Re: What do you call a class not intended to be instantiated

          Steven D'Aprano:
          I have a class which is not intended to be instantiated. Instead of using
          the class to creating an instance and then operate on it, I use the class
          directly, with classmethods. Essentially, the class is used as a function
          that keeps state from one call to the next.
          You may use a module too for that, with normal functions inside, plus
          module variables that keep the state. Modules can't be instantiated, I
          think.

          Bye,
          bearophile

          Comment

          • James Mills

            #6
            Re: What do you call a class not intended to be instantiated

            On Mon, Sep 22, 2008 at 9:39 AM, Calvin Spealman <ironfroggy@gma il.comwrote:
            I call it an obvious misuse and misunderstandin g of why you'd use a class in
            the first place. Either create an instance and not make these things
            classmethods or just share the stuff in a module-level set of variables. But
            the instantiating is the best options. Your class attributes might not be
            globals, but you're still using global state and you should avoid it where
            you can.
            I concur. Use a _proper_ state object that you share
            amongst your other objects. For instance, in many of
            my systems and applications I write, I often have
            an "Environmen t" instance, which is a container
            object that holds other objects required by parts
            of the system. Every other component/object in the
            system that is instantiated recievees exactly one
            instnace of thie "Environmen t" called, "env".

            Accessing shared states amongst components/objects
            within the system is as simple as this:

            class Foo(object):

            def __init__(self, env, *args, **kwargs):
            self.env = env

            def foo(self):
            if self.env.some_s tate:
            print "Do something useful"

            env = Environment()
            foo = Foo(env)
            foo.foo()

            cheers
            James

            --
            --
            -- "Problems are solved by method"

            Comment

            • Aaron \Castironpi\ Brady

              #7
              Re: What do you call a class not intended to be instantiated

              On Sep 21, 6:05 pm, Steven D'Aprano <st...@REMOVE-THIS-
              cybersource.com .auwrote:
              Fixing top-posting.
              >
              On Mon, 22 Sep 2008 08:54:43 +1000, James Mills wrote:
              On Mon, Sep 22, 2008 at 8:39 AM, Steven D'Aprano
              <st...@remove-this-cybersource.com .auwrote:
              I have a class which is not intended to be instantiated. Instead of
              using the class to creating an instance and then operate on it, I use
              the class directly, with classmethods. Essentially, the class is used
              as a function that keeps state from one call to the next.
              >
              [...]
              >
              Hi,
              >
              Wouldn't a normal class called State
              suffice for storing state between calls ? And ... Creating a state
              instance ?
              >
              For example:
              >
              [snip]
              >
              That's a rather big example for a rather small question.
              >
              Yes, a normal class would work in many cases. In this case, the class
              itself is being produced by a factory function, and it's output is an
              iterator. Having to call:
              >
              cls = factory()
              instance = cls()
              result = instance()
              >
              to get anything done seems excessive, even if you write it as a one-liner
              result = factory()()().
              >
              I'm not wedded to the idea, there are alternatives (perhaps the factory
              should instantiate the class and return that?) but I assume others have
              used this design and have a name for it.
              >
              --
              Steven
              Do you want anything from it that a dictionary doesn't have, besides
              the dot-member access?

              Comment

              • Ben Finney

                #8
                Re: What do you call a class not intended to be instantiated

                Steven D'Aprano <steve@REMOVE-THIS-cybersource.com .auwrites:
                I have a class which is not intended to be instantiated. Instead of
                using the class to creating an instance and then operate on it, I
                use the class directly, with classmethods. Essentially, the class is
                used as a function that keeps state from one call to the next.
                Classes aren't designed to keep state; state is kept in instances.

                I think you want Alex Martelli's 'Borg' pattern
                <URL:http://aspn.activestat e.com/ASPN/Cookbook/Python/Recipe/66531>,
                which is a class where each instance shares the same state.

                --
                \ “Pinky, are you pondering what I'm pondering?” “I think so, |
                `\ Brain, but there's still a bug stuck in here from last time.” |
                _o__) —_Pinky and The Brain_ |
                Ben Finney

                Comment

                • Rhamphoryncus

                  #9
                  Re: What do you call a class not intended to be instantiated

                  On Sep 21, 4:39 pm, Steven D'Aprano <st...@REMOVE-THIS-
                  cybersource.com .auwrote:
                  I have a class which is not intended to be instantiated. Instead of using
                  the class to creating an instance and then operate on it, I use the class
                  directly, with classmethods. Essentially, the class is used as a function
                  that keeps state from one call to the next.
                  >
                  The problem is that I don't know what to call such a thing! "Abstract
                  class" isn't right, because that implies that you should subclass the
                  class and then instantiate the subclasses.
                  >
                  What do you call such a class?
                  If defining it as a normal class, it is a namespace. Just a way to
                  cluster multiple globals into a single global. The borg pattern does
                  the same thing, but with a 12 page treatise on why it shouldn't do
                  exactly what it's doing.

                  If using a factory you should probably be using an instance; the fact
                  that your instance is a class is a relatively minor implementation
                  detail. Indeed, the only reason to have a class is to have your
                  methods bound when looked up.

                  You might want a metaclass to cripple it, preventing subclassing and
                  whatnot. *shrug*.

                  Comment

                  • Bruno Desthuilliers

                    #10
                    Re: What do you call a class not intended to be instantiated

                    Steven D'Aprano a écrit :
                    I have a class which is not intended to be instantiated. Instead of using
                    the class to creating an instance and then operate on it, I use the class
                    directly, with classmethods. Essentially, the class is used as a function
                    that keeps state from one call to the next.
                    >
                    The problem is that I don't know what to call such a thing! "Abstract
                    class" isn't right, because that implies that you should subclass the
                    class and then instantiate the subclasses.
                    >
                    What do you call such a class?
                    >
                    <nitpick>
                    Err... A possible design smell ?-)
                    </nitpick>


                    More seriously: this looks quite like a singleton, which in Python is
                    usually implemented way more simply using a module and plain functions.

                    Do you have a use case for specializing this class ?

                    Comment

                    • Steven D'Aprano

                      #11
                      Re: What do you call a class not intended to be instantiated

                      On Mon, 22 Sep 2008 10:12:38 +1000, James Mills wrote:
                      On Mon, Sep 22, 2008 at 9:39 AM, Calvin Spealman <ironfroggy@gma il.com>
                      wrote:
                      >I call it an obvious misuse and misunderstandin g of why you'd use a
                      >class in the first place. Either create an instance and not make these
                      >things classmethods or just share the stuff in a module-level set of
                      >variables. But the instantiating is the best options. Your class
                      >attributes might not be globals, but you're still using global state
                      >and you should avoid it where you can.
                      >
                      I concur. Use a _proper_ state object that you share amongst your other
                      objects.

                      But that's precisely what I want to avoid: I don't want the objects to
                      share *any* state, not even their class. I'm not trying for a Borg or
                      Singleton: the user can call the factory as many times as they want, but
                      the objects returned shouldn't share any state. I don't know if what I
                      want has a name. Judging from people's reactions, I'd say probably not.

                      (For the pedantic: the "instances" will all have the same methods, but
                      I'm not including methods as state.)


                      For instance, in many of my systems and applications I write, I
                      often have an "Environmen t" instance, which is a container object that
                      holds other objects required by parts of the system. Every other
                      component/object in the system that is instantiated recievees exactly
                      one instnace of thie "Environmen t" called, "env".
                      >
                      Accessing shared states amongst components/objects within the system is
                      as simple as this:
                      >
                      class Foo(object):
                      >
                      def __init__(self, env, *args, **kwargs):
                      self.env = env
                      >
                      def foo(self):
                      if self.env.some_s tate:
                      print "Do something useful"
                      Seems wasteful to me. Why give every instance it's own instance-level
                      reference to the shared object? Why not make env a class attribute, set
                      once, instead of every time you instantiate the class?


                      class Foo(object):
                      env = env

                      But in any case, this is not the behaviour I want. It's the opposite of
                      the behaviour I want. I don't want the objects to share state. I'm not
                      exactly sure what I said that has given so many people the impression
                      that I do.




                      --
                      Steven

                      Comment

                      • Ben Finney

                        #12
                        Re: What do you call a class not intended to be instantiated


                        Steven D'Aprano <steven@REMOVE. THIS.cybersourc e.com.auwrites:
                        I don't want the objects to share state. I'm not exactly sure what I
                        said that has given so many people the impression that I do.
                        This:

                        Steven D'Aprano <steve@REMOVE-THIS-cybersource.com .auwrites:
                        Essentially, the class is used as a function that keeps state from
                        one call to the next.
                        Perhaps if you say what you want that isn't provided by any of a
                        function, a module, or a class. Specifically, what state you want to
                        track, and why it's so important that the state not be available to
                        the instances.

                        --
                        \ “I love and treasure individuals as I meet them, I loathe and |
                        `\ despise the groups they identify with and belong to.” —George |
                        _o__) Carlin, 2007 |
                        Ben Finney

                        Comment

                        • Steven D'Aprano

                          #13
                          Re: What do you call a class not intended to be instantiated

                          On Mon, 22 Sep 2008 10:11:58 +0200, Bruno Desthuilliers wrote:
                          Steven D'Aprano a écrit :
                          >I have a class which is not intended to be instantiated. Instead of
                          >using the class to creating an instance and then operate on it, I use
                          >the class directly, with classmethods. Essentially, the class is used
                          >as a function that keeps state from one call to the next.
                          >>
                          >The problem is that I don't know what to call such a thing! "Abstract
                          >class" isn't right, because that implies that you should subclass the
                          >class and then instantiate the subclasses.
                          >>
                          >What do you call such a class?
                          >>
                          >>
                          <nitpick>
                          Err... A possible design smell ?-)
                          </nitpick>
                          >
                          >
                          More seriously: this looks quite like a singleton, which in Python is
                          usually implemented way more simply using a module and plain functions.

                          I really don't know why everyone thinks I want a Singleton. I want to
                          uncouple objects, not increase the coupling.


                          Consider a factory function:

                          def factory(x): # a toy example
                          alist = [x]
                          def foo():
                          return alist
                          return foo


                          Now suppose we "instantiat e" the factory (for lack of a better term):
                          >>f1 = factory(0)
                          >>f2 = factory(0)
                          Even though f1 and f2 have the same behaviour, they are obviously not the
                          same object. And although both return a list [0], it is not the same list:
                          >>f1() == f2() == [0]
                          True
                          >>f1() is f2()
                          False


                          They have a (very little) amount of state, which is *not* shared:
                          >>L = f1()
                          >>L.append(1)
                          >>f1()
                          [0, 1]
                          >>f2()
                          [0]


                          But there's only a limited amount of state that functions carry around. I
                          can give them more state like this:
                          >>f1.attr = 'x'
                          but it isn't good enough if the function needs to refer to it's own
                          state, because functions can only refer to themselves by name and the
                          factory can't know what name the function will be bound to.

                          As far as I know, the only objects that know how to refer to themselves
                          no matter what name they have are classes and instances. And instances
                          share at least some state, by virtue of having the same class.

                          (Pedants will argue that classes also share state, by virtue of having
                          the same metaclass. Maybe so, but that's at a deep enough level that I
                          don't care.)

                          I'm now leaning towards just having factory() instantiate the class and
                          return the instance, instead of having to do metaclass chicanery. Because
                          the class is built anew each time by the factory, two such instances
                          aren't actually sharing the same class. I think that will reduce
                          confusion all round (including mine!).

                          Hopefully now that I've explained what I want in more detail, it won't
                          seem so bizarre. Factory functions do it all the time. Is there a name
                          for this pattern?

                          Thanks to everyone who commented, your comments helped me reason out a
                          better alternative to what I first suggested.



                          --
                          Steven

                          Comment

                          • James Mills

                            #14
                            Re: What do you call a class not intended to be instantiated

                            On 22 Sep 2008 09:07:43 GMT, Steven D'Aprano
                            But that's precisely what I want to avoid: I don't want the objects to
                            share *any* state, not even their class. I'm not trying for a Borg or
                            Singleton: the user can call the factory as many times as they want, but
                            the objects returned shouldn't share any state. I don't know if what I
                            want has a name. Judging from people's reactions, I'd say probably not.
                            Snce when are "users" ever involved
                            in programming problems or programming
                            languages ?

                            --JamesMills

                            --
                            --
                            -- "Problems are solved by method"

                            Comment

                            • Bruno Desthuilliers

                              #15
                              Re: What do you call a class not intended to be instantiated

                              Steven D'Aprano a écrit :
                              On Mon, 22 Sep 2008 10:11:58 +0200, Bruno Desthuilliers wrote:
                              >
                              >Steven D'Aprano a écrit :
                              >>I have a class which is not intended to be instantiated. Instead of
                              >>using the class to creating an instance and then operate on it, I use
                              >>the class directly, with classmethods. Essentially, the class is used
                              >>as a function that keeps state from one call to the next.
                              >>>
                              >>The problem is that I don't know what to call such a thing! "Abstract
                              >>class" isn't right, because that implies that you should subclass the
                              >>class and then instantiate the subclasses.
                              >>>
                              >>What do you call such a class?
                              >>>
                              >>>
                              ><nitpick>
                              >Err... A possible design smell ?-)
                              ></nitpick>
                              >>
                              >>
                              >More seriously: this looks quite like a singleton, which in Python is
                              >usually implemented way more simply using a module and plain functions.
                              >
                              >
                              I really don't know why everyone thinks I want a Singleton.
                              May I quote you ?
                              """
                              Instead of using the class to creating an instance and then operate on
                              it, I use the class directly, with classmethods. Essentially, the class
                              is used as a function that keeps state from one call to the next.
                              """
                              I want to
                              uncouple objects, not increase the coupling.
                              >
                              >
                              Consider a factory function:
                              >
                              def factory(x): # a toy example
                              alist = [x]
                              def foo():
                              return alist
                              return foo
                              >
                              >
                              Now suppose we "instantiat e" the factory (for lack of a better term):
                              >
                              >>>f1 = factory(0)
                              >>>f2 = factory(0)
                              >
                              Even though f1 and f2 have the same behaviour, they are obviously not the
                              same object. And although both return a list [0], it is not the same list:
                              >
                              >>>f1() == f2() == [0]
                              True
                              >>>f1() is f2()
                              False
                              >
                              >
                              They have a (very little) amount of state, which is *not* shared:
                              >
                              >>>L = f1()
                              >>>L.append(1 )
                              >>>f1()
                              [0, 1]
                              >>>f2()
                              [0]
                              >
                              >
                              But there's only a limited amount of state that functions carry around. I
                              can give them more state like this:
                              >
                              >>>f1.attr = 'x'
                              >
                              but it isn't good enough if the function needs to refer to it's own
                              state, because functions can only refer to themselves by name and the
                              factory can't know what name the function will be bound to.
                              Then define your own callable type.
                              As far as I know, the only objects that know how to refer to themselves
                              no matter what name they have are classes and instances. And instances
                              share at least some state, by virtue of having the same class.
                              Is that a problem in your use case, and if so, why ???
                              (Pedants will argue that classes also share state, by virtue of having
                              the same metaclass. Maybe so, but that's at a deep enough level that I
                              don't care.)
                              >
                              I'm now leaning towards just having factory() instantiate the class and
                              return the instance, instead of having to do metaclass chicanery. Because
                              the class is built anew each time by the factory, two such instances
                              aren't actually sharing the same class. I think that will reduce
                              confusion all round (including mine!).
                              >
                              Hopefully now that I've explained what I want in more detail, it won't
                              seem so bizarre. Factory functions do it all the time. Is there a name
                              for this pattern?
                              >
                              Thanks to everyone who commented, your comments helped me reason out a
                              better alternative to what I first suggested.
                              >
                              Glad to know you found something helpful in all these answers, but as
                              far as I'm concerned, I'm afraid I still fail to understand what exactly
                              you're after...


                              Comment

                              Working...