is it possible to give an instance a value?

M

manstey

Hi,

My question probably reflects my misunderstanding 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
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:
Canberra %String

etc.

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

Terry Reedy

| Hi,
|
| My question probably reflects my misunderstanding 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
['__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 0xXXXXXX> is because the C coded __str__
extracts the value field of the int structure and converts it to ascii.

Terry Jan Reedy
 
F

fumanchu

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


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:


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("TypedAttributes may not be deleted.")


class Person(object):

Address = TypedAttribute(str)

def __init__(self):
self._attributes = {}


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
(e-mail address removed)
 
B

Bruno Desthuilliers

manstey a écrit :
Hi,

My question probably reflects my misunderstanding 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



'hello 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:


Canberra %String

etc.
We have had to implement Person.Address as Person.Address.val, making
Address an instance with .val, .type, etc.
.... def __init__(self):
.... self.address = "sidney"
....

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
 
S

Steven D'Aprano

class Test(object):
def __init__(self, val):
self.val = val

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.MutableString 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:

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:


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(_getter, _setter, None, None)


Now you can do this:
<class '__main__.MyString'>

But this doesn't work:
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:
'%String'

Python can do this:
<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:
'%String'

then you're just making work for yourself.


Hope this makes sense.
 
D

Dennis Lee Bieber

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# ?).
Looks more like some variant of REXX stem variable... Closest would
probably be a Python dictionary, though having an automatic "var" key
isn't likely.

/* test */
Person.Address = "Sydney"
Person.Address.type = "%string"
echo Person
echo Person.
echo Person.Address Person.Address.type
Person.Address = "Canberra"
echo Person.Address Person.Address.type
Person.Name.last = "Cares"
Person.Name.first = "Who"
echo Person.Name.
part1 = "last"
part2 = "FIRST"
echo Person.Name.part2 Person.Name.part1
-=-=-=-=-=-


E:\UserData\Dennis Lee Bieber\My Documents>regina t.rx
PERSON
PERSON.
Sydney %string
Canberra %string
PERSON.NAME.
Who PERSON.NAME.last

E:\UserData\Dennis Lee Bieber\My Documents>



--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
E

egbert

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=adres

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
 
M

manstey

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.calculated
instance.type
instance.whatever
instance.save()
etc

thanks.
 
S

Steven D'Aprano

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:
SyntaxError: can't assign to function call


If you do this:

then we're back to the Original Poster's original problem.
 
A

Aahz

manstey a écrit :

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,586
Members
45,096
Latest member
ThurmanCre

Latest Threads

Top