is it possible to give an instance a value?

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

    #1

    is it possible to give an instance a value?

    Hi,

    My question probably reflects my misunderstandin g of python objects,
    but I would still like to know the answer.

    The question is, is it possible for an instnace to have a value (say a
    string, or integer) that can interact with other datatypes and be
    passed as an argument?

    The following code of course gives an error:

    class Test(object):
    def __init__(self, val):
    self.val = val
    >>a = Test('hello')
    >>a.val + ' happy'
    'hello happy'
    >>a + 'happy'
    TypeError: unsupported operand type(s) for +: 'Test' and 'str'

    Is there a way to make a have the value a.val when it is used as
    above, or as an argument (eg function(a, 10, 'sdf') etc)?

    The only fudge I discovered for simple addition was to add to the
    class

    def __add__(self, obj):
    return a.val + obj

    but this doesn't solve the problem in general. I have tried
    subclassing the string type, but as it is immutable, this is not
    flexible the way a.val is (i.e. it can't e reassigned and remain a
    subclass).

    Any pointers, or is my question wrong-headed?

    btw, my motivation is wanting to mimic another oo language which
    allows this, so it allows:
    >>>Person.Addre ss
    'Sydney'
    >>>Person.Addre ss.type
    '%String'
    >>>Person.Addre ss = 'Canberra'
    >>>print Person.Address. Person.Address. type
    Canberra %String

    etc.

    We have had to implement Person.Address as Person.Address. val, making
    Address an instance with .val, .type, etc.

  • Terry Reedy

    #2
    Re: is it possible to give an instance a value?


    "manstey" <manstey@csu.ed u.auwrote in message
    news:1173221145 .793008.298940@ v33g2000cwv.goo glegroups.com.. .
    | Hi,
    |
    | My question probably reflects my misunderstandin g of python objects,
    | but I would still like to know the answer.
    |
    | The question is, is it possible for an instnace to have a value (say a
    | string, or integer) that can interact with other datatypes and be
    | passed as an argument?

    In the way you are asking, no.

    | Is there a way to make a have the value a.val when it is used as
    | above, or as an argument (eg function(a, 10, 'sdf') etc)?
    |
    | The only fudge I discovered for simple addition was to add to the
    | class
    |
    | def __add__(self, obj):
    | return a.val + obj
    |
    | but this doesn't solve the problem in general. I have tried
    | subclassing the string type, but as it is immutable, this is not
    | flexible the way a.val is (i.e. it can't e reassigned and remain a
    | subclass).

    Special methods are the Python way, not a fudge. Consider
    >>dir(1)
    ['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__',
    '__delattr__', '__div__', '__divmod__', '__doc__', '__float__',
    '__floordiv__', '__getattribute __', '__getnewargs__ ', '__hash__',
    '__hex__', '__init__', '__int__', '__invert__', '__long__', '__lshift__',
    '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__',
    '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__',
    '__rdivmod__', '__reduce__', '__reduce_ex__' , '__repr__', '__rfloordiv__' ,
    '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__',
    '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__',
    '__setattr__', '__str__', '__sub__', '__truediv__', '__xor__']

    All these int methods do the C equivalent of return int(self.val +
    other.val), etc. Similarly, the reason an int object with value 123 prints
    as 123 instead of <int object at 0xXXXXXXis because the C coded __str__
    extracts the value field of the int structure and converts it to ascii.

    Terry Jan Reedy



    Comment

    • Bruno Desthuilliers

      #3
      Re: is it possible to give an instance a value?

      manstey a écrit :
      Hi,
      >
      My question probably reflects my misunderstandin g of python objects,
      but I would still like to know the answer.
      >
      The question is, is it possible for an instnace to have a value (say a
      string, or integer) that can interact with other datatypes and be
      passed as an argument?
      In Python, strings and integers *are* objects (instances of resp. str
      and int).
      The following code of course gives an error:
      >
      class Test(object):
      def __init__(self, val):
      self.val = val
      >
      >
      >>>>a = Test('hello')
      >>>>a.val + ' happy'
      >
      'hello happy'
      >
      >>>>a + 'happy'
      >
      TypeError: unsupported operand type(s) for +: 'Test' and 'str'
      No surprise so far.
      Is there a way to make a have the value a.val
      Forget about the value/instance distinction - it doesn't exists in Python.
      when it is used as
      above,
      implement __add__ (and any other appropriate magic method)
      or as an argument (eg function(a, 10, 'sdf') etc)?
      >
      The only fudge I discovered for simple addition was to add to the
      class
      >
      def __add__(self, obj):
      return a.val + obj
      So what's your problem exactly ?
      but this doesn't solve the problem in general. I have tried
      subclassing the string type, but as it is immutable, this is not
      flexible the way a.val is
      Err... In your above example implementation, a.val actually *is* a string.
      (i.e. it can't e reassigned
      ???

      a.val = "tutu"
      and remain a
      subclass).
      ???
      Any pointers, or is my question wrong-headed?
      I'm afraid I don't get the point.
      btw, my motivation is wanting to mimic another oo language which
      allows this, so it allows:
      >
      >>>>Person.Addr ess
      >
      'Sydney'
      >
      >>>>Person.Addr ess.type
      >
      '%String'
      >
      >>>>Person.Addr ess = 'Canberra'
      >>>>print Person.Address. Person.Address. type
      >
      Canberra %String
      >
      etc.
      We have had to implement Person.Address as Person.Address. val, making
      Address an instance with .val, .type, etc.
      >>class Person(object):
      .... def __init__(self):
      .... self.address = "sidney"
      ....
      >>person = Person()
      >>person.addres s
      'sidney'
      >>type(person.a ddress)
      <type 'str'>
      >># this is equivalent:
      >>person.addres s.__class__
      <type 'str'>
      >># of if you want the name of the class instead
      >># of the class object itself:
      >>person.addres s.__class__.__n ame__
      'str'
      >>>

      Looks like you'd better learn the Python way instead of wasting your
      time trying to mimic some other language (BTW, is it VB or C# ?).

      HTH

      Comment

      • fumanchu

        #4
        Re: is it possible to give an instance a value?

        On Mar 6, 2:45 pm, "manstey" <mans...@csu.ed u.auwrote:
        The question is, is it possible for an instance to have a value (say a
        string, or integer) that can interact with other datatypes and be
        passed as an argument?
        >
        The following code of course gives an error:
        >
        class Test(object):
        def __init__(self, val):
        self.val = val
        >
        >a = Test('hello')
        >a.val + ' happy'
        'hello happy'
        >a + 'happy'
        >
        TypeError: unsupported operand type(s) for +: 'Test' and 'str'
        >
        Is there a way to make a have the value a.val when it is used as
        above, or as an argument (eg function(a, 10, 'sdf') etc)?
        >
        The only fudge I discovered for simple addition was to add to the
        class
        >
        def __add__(self, obj):
        return a.val + obj
        >
        but this doesn't solve the problem in general. I have tried
        subclassing the string type, but as it is immutable, this is not
        flexible the way a.val is (i.e. it can't e reassigned and remain a
        subclass).
        >
        Any pointers, or is my question wrong-headed?
        >
        btw, my motivation is wanting to mimic another oo language which
        allows this, so it allows:
        >
        >>Person.Addres s
        'Sydney'
        >>Person.Addres s.type
        '%String'
        >>Person.Addres s = 'Canberra'
        >>print Person.Address. Person.Address. type
        >
        Canberra %String
        >
        etc.
        >
        We have had to implement Person.Address as Person.Address. val, making
        Address an instance with .val, .type, etc.
        The question is not, "is it possible for an instance to have a
        value?", but "is it possible for a value to have other attributes?" If
        you really need them, you want Python descriptors, which are described
        here: http://docs.python.org/ref/descriptors.html. However, if type is
        the only value metadata you care about, you probably don't need them
        (just use the builtin 'type' function on any object).


        class TypedAttribute( object):

        def __init__(self, type=unicode):
        self.type = type

        def __get__(self, obj, unitclass=None) :
        if obj is None:
        # When calling on the class instead of an instance...
        return self
        else:
        return obj._attributes[self.key]

        def __set__(self, obj, value):
        obj._attributes[self.key] = value

        def __delete__(self , obj):
        raise AttributeError( "TypedAttribute s may not be deleted.")


        class Person(object):

        Address = TypedAttribute( str)

        def __init__(self):
        self._attribute s = {}


        I'm using the _attributes dict here just by convention; I find it
        convenient to store the underlying values in each parent object. There
        are other ways to do it.


        Robert Brewer
        System Architect
        Amor Ministries
        fumanchu@amor.o rg

        Comment

        • Steven D'Aprano

          #5
          Re: is it possible to give an instance a value?

          On Tue, 06 Mar 2007 14:45:45 -0800, manstey wrote:
          class Test(object):
          def __init__(self, val):
          self.val = val
          >
          >>>a = Test('hello')
          >>>a.val + ' happy'
          'hello happy'
          >>>a + 'happy'
          TypeError: unsupported operand type(s) for +: 'Test' and 'str'
          >
          Is there a way to make a have the value a.val when it is used as
          above, or as an argument (eg function(a, 10, 'sdf') etc)?
          That's kinda-sorta like "delegation ", which is an alternative to
          sub-classing. Whether you subclass string or delegate to a string, the end
          result will be the same, only the implementation will be different.

          However, while sub-classing str will give you an immutable object,
          delegation can give you a mutable string. See UserString.Muta bleString for
          details -- but beware that this is significantly slower than ordinary
          strings.

          Honestly, once you've been using immutable strings for a while, you'll
          rarely care that they aren't mutable.


          The only fudge I discovered for simple addition was to add to the
          class
          >
          def __add__(self, obj):
          return a.val + obj
          >
          but this doesn't solve the problem in general. I have tried
          subclassing the string type, but as it is immutable, this is not
          flexible the way a.val is (i.e. it can't e reassigned and remain a
          subclass).
          Because of the way Python works, you can't really expect this to work:
          >>s = MyClass("someth ing") # s is assigned an instance of MyClass
          >>s = "ordinary string" # s magically remains a MyClass instance
          Python just doesn't work that way. The name "s" can't force the object
          "ordinary string" to be some other type. If you want "s" to have an
          instance of MyClass assigned to it, you have to do it explicitly:
          >>s = MyClass("ordina ry string") # not ordinary any more

          If you are willing to write s.data instead of s, then you can make the
          data attribute a property and automate most of that.


          class MyString(str):
          pass # customise the behaviour you want to see

          class MyClass(object) :
          def __init__(self, data):
          self.data = data
          def _getter(self):
          return self._data
          def _setter(self, data):
          self._data = MyString(data)
          data = property(_gette r, _setter, None, None)


          Now you can do this:
          >>inst = MyClass("hello world")
          >>inst.data += "!"
          >>type(inst.dat a)
          <class '__main__.MyStr ing'>
          >>inst.data = "Nobody expects the Spanish Inquisition!"
          >>type(inst.dat a)
          <class '__main__.MyStr ing'>

          But this doesn't work:
          >>inst = "dead parrot"
          >>type(inst) == MyClass # what we want to be True
          False


          But chances are that all of that scaffolding (delegation, properties,
          etc.) would be unnecessary if you just change the way you do things. E.g.
          instead of your example:
          >>Person.Addres s
          'Sydney'
          >>Person.Addres s.type
          '%String'

          Python can do this:
          >>Person.Addres s
          'Sydney'
          >>type(Person.A ddress)
          <type 'str'>

          If you sub-classed str like this:

          class MyString(object ):
          def __init__(self, data, type="%String") :
          self.data = data
          self.type = type

          hoping to use it like this:
          >>fred = Person("Address ", "Sydney", "%String") # or something...
          >>fred.Addres s
          'Sydney'
          >>fred.Address. type
          '%String'

          then you're just making work for yourself.


          Hope this makes sense.


          --
          Steven D'Aprano

          Comment

          • egbert

            #6
            Re: is it possible to give an instance a value?

            On Tue, 06 Mar 2007 14:45:45 -0800, manstey wrote:
            >
            class Test(object):
            def __init__(self, val):
            self.val = val
            >
            a = Test('hello')
            Is there a way to make a have the value a.val when it is used as
            above, or as an argument (eg function(a, 10, 'sdf') etc)?
            >
            My impression is that you can do everything you want to
            by making your instance callable, and not using a but a().

            This is just an example:

            class Persoon(object) :
            def __init__(self, adres):
            self.adres=adre s

            def __call__(self, new_adres=None) :
            if new_adres: self.adres = new_adres
            return self.adres

            a = Persoon("Sidney ")
            print "Living in " + a()
            a("Canberra")
            print "Living in " + a()
            print "Now living in ", a("Amsterdam" )
            print "Type of a() is: %s" % type(a())
            print "Now earning" , a(1234) + 500
            print "Type of a() is: %s" % type(a())
            print "string ? %s" % ["No","Yes"][isinstance(a(), basestring)]

            The output is:

            Living in Sidney
            Living in Canberra
            Now living in Amsterdam
            Type of a() is: <type 'str'>
            Now earning 1734
            Type of a() is: <type 'int'>
            string ? No


            e
            --
            Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
            =============== =============== =============== =============== ============

            Comment

            • manstey

              #7
              Re: is it possible to give an instance a value?

              Thanks everyone for your replies. The language is Cache Object Script,
              a language used in Intersystems Relational Dbase.

              I think egbert's answer provides the simplest answer. It allows our
              python interface to Cache to be almost identical to Cache Object
              Script, with simeply the addition of (), which we prefer to .val
              or .data for various reasons.

              Using the example .type was a mistake, as I meant simply any metadata
              about a value. If we make the instance callable, then we can have:

              instance()
              instance.calcul ated
              instance.type
              instance.whatev er
              instance.save()
              etc

              thanks.

              Comment

              • Steven D'Aprano

                #8
                Re: is it possible to give an instance a value?

                On Wed, 07 Mar 2007 16:02:05 +0100, egbert wrote:
                On Tue, 06 Mar 2007 14:45:45 -0800, manstey wrote:
                >>
                >class Test(object):
                > def __init__(self, val):
                > self.val = val
                >>
                >a = Test('hello')
                >
                >Is there a way to make a have the value a.val when it is used as
                >above, or as an argument (eg function(a, 10, 'sdf') etc)?
                >>
                My impression is that you can do everything you want to
                by making your instance callable, and not using a but a().
                You can't do this:
                >>a() = "some value"
                SyntaxError: can't assign to function call


                If you do this:
                >>a = "some value"
                then we're back to the Original Poster's original problem.



                --
                Steven D'Aprano

                Comment

                • egbert

                  #9
                  Re: is it possible to give an instance a value?

                  On Thu, Mar 08, 2007 at 01:22:25PM +1100, Steven D'Aprano wrote:
                  On Wed, 07 Mar 2007 16:02:05 +0100, egbert wrote:
                  My impression is that you can do everything you want to
                  by making your instance callable, and not using a but a().
                  You can't do this:
                  >
                  >a() = "some value"
                  I didn't say that you can do that.
                  But in my example you can do
                  >> a("some value")
                  and that seems to be near enough for manstey.
                  e
                  --
                  Egbert Bouwman - Keizersgracht 197 II - 1016 DS Amsterdam - 020 6257991
                  =============== =============== =============== =============== ============

                  Comment

                  • Aahz

                    #10
                    Re: is it possible to give an instance a value?

                    In article <45edfb62$0$285 23$426a74cc@new s.free.fr>,
                    Bruno Desthuilliers <bdesth.quelque chose@free.quel quepart.frwrote :
                    >manstey a écrit :
                    >>
                    >Is there a way to make a have the value a.val
                    >
                    >Forget about the value/instance distinction - it doesn't exists in Python.
                    Actually, I think it does. For example, int('123') has the value 123.
                    The way I would put it, any type/class that has an eval()able
                    representation has a value.
                    --
                    Aahz (aahz@pythoncra ft.com) <* http://www.pythoncraft.com/

                    "I disrespectfully agree." --SJM

                    Comment

                    Working...