Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Python > Suggesting for overloading the assign operator

Reply
Thread Tools

Suggesting for overloading the assign operator

 
 
Ian Bicking
Guest
Posts: n/a
 
      07-01-2003
On Tue, 2003-07-01 at 13:01, Alan Kennedy wrote:
> Rim wrote:
>
> > What do you think about providing a statement to assign values
> > without assigning type?
> >
> > '=' statement assigns value and type
> > ':=' statement assigns value ony

>
> I think the concept has some merit. I think that sometimes it useful to ensure
> that the target of a rebind operation have the same type as the object which was
> bound before the rebind.
>
> I know that the same effect can be achieved by descriptors or overriding
> "setattr" et al. Or something like this


Or maybe:

class stricttype(object):

counter = 1

def __init__(self, required_type, doc=None, real_attr=None):
self.required_type = required_type
if not real_attr:
real_attr = '_stricttype_attr_%i' % stricttype.counter
stricttype.counter += 1
self.real_attr = real_attr
self.doc = doc

def __set__(self, obj, value):
if not isinstance(value, self.required_type):
raise TypeError, 'must be of type %r' % self.required_type
setattr(obj, self.real_attr, value)

def __get__(self, obj, cls):
return getattr(obj, self.real_attr)

def __del__(self, obj):
delattr(obj, self.real_attr)

def __doc__(self, obj):
return self.doc


class IntPoint(object):

def __init__(self, x, y):
self.x = x
self.y = y

def __str__(self):
return 'Point: (%i, %i)' % (self.x, self.y)

x = stricttype(int)
y = stricttype(int)

>>> p = IntPoint(1, 1)
>>> p

Point: (1, 1)
>>> p.x = 2
>>> p

Point: (2, 1)
>>> p.x = 2.2

Traceback (most recent call last):
File "stricttype.py", line 44, in ?
p.x = 2.2
File "stricttype.py", line 15, in __set__
raise TypeError, 'must be of type %r' % self.required_type
TypeError: must be of type <type 'int'>


If we're talking about optimizations, there's no reason something like
Psyco couldn't specifically look for specific descriptors like
stricttype, and probably replace that implementation with something
better optimized.

Ian



 
Reply With Quote
 
 
 
 
Bengt Richter
Guest
Posts: n/a
 
      07-02-2003
On Tue, 1 Jul 2003 09:22:03 -0600, Steven Taschuk <(E-Mail Removed)> wrote:

>Quoth Rim:
> [...]
>> The idea is to separate the value assignment from the type assignment,
>> by introducing a new operator, let's say the ':=' operator.
>>
>> '=' remains what it is, assigns type and value at the same time
>> ':=' assigns only the value

>
>That's a peculiar way of speaking. '=' does not assign type and
>value to a variable; it assigns an object to a name.
>
> [...]
>> In reality, := would just coerce the return type of the RHS of := to
>> the type of the variable on the LHS of the :=, preserving the value(s)
>> as best as it can.

>
>"The type of the variable" is not a meaningful phrase in Python:
>names do not have types; objects do. I assume you meant "the type
>of the object the name on the lhs is presently bound to".
>
>Coerce how? Do you want a new __magicmethod__ for this operation?
>
>Would ':=' mutate the object presently bound to the lhs name
>create a new object and rebind the lhs name? To be concrete:
>

One thought would be that it wouldn't change the current binding. E.g.,

x := y

could be a spelling of x.__update__(y) and would be an *expression* with
potential side effects. By convention, a reference to the updated same object
would be returned. I.e., x.__class__ would have to have

def __update__(self, other):
<optional use of other>
return self

For starters, you could just let AttributeError get raised if there's no __update__ method.

> a = whatever
> b = a
> a := 7
> assert a is b
>
>Should that assertion succeed or fail, in general? (Note that it
>fails in general if the ':=' is replaced with '=', even if
>whatever == 7.)


For the above, it should succeed, since the binding will have been unchanged
>
>Would ':=' support chaining? That is, would
> a := b := <some expression>
>work? If so, would it be equivalent to

Yes, it should work, but no, it wouldn't be equivalent to
> _tmp = <some expression>
> a := _tmp
> b := _tmp

working left to right, it would presumably be equivalent to

a.__update__(b).__update__(<some expression>)

>(except for the namespace pollution), to match the semantics of
>chained '='? (Note that the assignments happen left to right.)
>
>Would use of a name on the lhs of a ':=' cause that name to be
>considered local, as such use with '=' does?

No, because it would be a named object reference for the purpose of looking
up the __update__ attribute in the non-sugar spelling of a:=b (which
is a.__update__(b)) -- i.e., it's an expression, not really an assignment statement.

>
>> If the type of the variable was still undefined, ':=' would behave
>> like '='. It might create confusion in future code, but does not break
>> old code.

>
>Yikes. Why not raise NameError if the name on the lhs of ':=' is
>not yet bound?

Yes.

>
>> I think it would be a nice feature to have. Comments?

>
>Your example
> a = Currency(6)
> a := 7
>is highly strange. (Even if we ignore the question of *which*
>currency is being represented; the example could easily be
>restated with, say, FixedPoint or Rational or some such.)
>

I don't know that I would totally dismiss the usage. It could be
a concise notation for a possibly polymorphic update operation.

w = Widget(blah, blah)
w := ('blue','white') # changes fg/bg colors
w := (20,40) # changes position
w := Font('Times Roman', size=24)
w := 'some text appended to a text widget'

Of course, you could use a property very similarly, e.g.,
w.p = 'text ...'

I guess it's a matter of what kind of sugar you like

>How is it that your users are happy to write Currency(...) when
>first assigning to a name, but not happy doing so when assigning
>later?
>
>Do they not understand that '=' binds a name to an object? Are
>they C programmers who think of assignment as copying a value from
>one location in memory to another? Do they think of the first
>assignment as a type declaration for the name? (If any of these
>three are true, they need to be better educated -- they're all
>fundamental misconceptions about Python.)

True, but if they did understand that a=b binds but a:=b updates??

>
>Do they need a language with syntactic support for Currency
>objects?

I'm not sure what that would mean.

OTOH, a:=b might lead to analogies with a+=b and other a<op>=b
and then where would we be

Let's see...

a+:=b => a.__update__(a.__add__(b))

??

Regards,
Bengt Richter
 
Reply With Quote
 
 
 
 
Steven Taschuk
Guest
Posts: n/a
 
      07-02-2003
Quoth Bengt Richter:
[...suggests a := b equivalent to a.__update__(b)...]
> I guess it's a matter of what kind of sugar you like


Quite.

[...syntactic support for Currency objects...]
> I'm not sure what that would mean.


I meant a language like Python but with a Currency literal syntax.
With syntax such as, say,
123.45$ equivalent to Currency(123.45)
(except, perhaps, for decimal vs binary exactness issues), the
users could type
a = 7$
# ...
a = 6$
which is less onerous than writing Currency(7), Currency(6).

This idea is well-suited to the scenario in which the users make
pervasive use of objects of this type, and the main problem is
having to type "Currency" over and over again.

[...]
--
Steven Taschuk http://www.velocityreviews.com/forums/(E-Mail Removed)
"What I find most baffling about that song is that it was not a hit."
-- Tony Dylan Davis (CKUA)

 
Reply With Quote
 
Bengt Richter
Guest
Posts: n/a
 
      07-02-2003
On Wed, 2 Jul 2003 08:21:57 -0600, Steven Taschuk <(E-Mail Removed)> wrote:

>Quoth Bengt Richter:
> [...suggests a := b equivalent to a.__update__(b)...]
>> I guess it's a matter of what kind of sugar you like

>
>Quite.
>
> [...syntactic support for Currency objects...]
>> I'm not sure what that would mean.

>
>I meant a language like Python but with a Currency literal syntax.
>With syntax such as, say,
> 123.45$ equivalent to Currency(123.45)
>(except, perhaps, for decimal vs binary exactness issues), the
>users could type
> a = 7$
> # ...
> a = 6$
>which is less onerous than writing Currency(7), Currency(6).
>
>This idea is well-suited to the scenario in which the users make
>pervasive use of objects of this type, and the main problem is
>having to type "Currency" over and over again.


Hm, it just occurred to me that one could have yet another form of sugar
[ It's now later, and I think this may be more than sugar ]
to help with this, by treating the dot operator slightly more symmetrically,
like, e.g., '+'.

Example, then explanation:

a = 7 .USD # (using symbols from http://www.xe.com/iso4217.htm by convention, no hard defs)
# ...
a = 6 .USD

This example uses the fact that int has no methods with plain names, so 6 .__getattribute__('USD')
will fail. Normally that would be the AttributeError end of it, but if '.' were like '+', we could
look for the r-version of __getattribute__ on the other object, analogous to __radd__. Thus

6 .USD # => USD.__rgetattribute__(6)

(note necessary disambiguating space here is not necessary in unambiguous contexts)
could return a specific currency object, e.g., if USD were defined something like e.g.,
(untested sketch !!)
--
class XXX_Currency(FixedPoint):
def __init__(self, symbol, *valprec):
FixedPoint.__init__(self, *valprec)
self.symbol = symbol
def __rgetattribute__(self, other):
return self.__class__(self.symbol, other, self.get_precision())

USD = XXX_Currency('USD')
--
Alternatively, perhaps USD could be a class from a factory instead of an instance, and have
__rgetattribute__ as a class method.

BTW,

num = 6
num = num.USD

would do the expected. I.e., this would be a dynamic mechanism, not a tweaked literal syntax.

Obviously this could be used for other quantity units than currencies, e.g.,

distance_to_moon = 384467 .km # avg dist

I.e., the mechanism is conceived in terms of an __rgetattribute__ method analogous to __radd__,
where you look for a compatible method in the other if the left arg can't handle it.
This could then allow a general mechanism for all types, not just numerics, yet constrain it
to special methods, to avoid accidental connections. Thus for an int,

6 . USD # => USD.__rgetattr__(6)

but also, this kind of binary-op attribute computation could supply missing methods, e.g.,
for simple file objects. Thus

f.readlines()

would effectively become

readlines.__rgetattribute__(f)()

if there were no readlines method on f, and this could
wrap f on the fly to provide the missing readlines method.

Am I being a troublemaker?

Regards,
Bengt Richter
 
Reply With Quote
 
Irmen de Jong
Guest
Posts: n/a
 
      07-02-2003
Bengt Richter wrote:

> Hm, it just occurred to me that one could have yet another form of sugar
> [ It's now later, and I think this may be more than sugar ]
> to help with this, by treating the dot operator slightly more symmetrically,
> like, e.g., '+'.


[...lots of interesting examples...]

> f.readlines()
>
> would effectively become
>
> readlines.__rgetattribute__(f)()
>
> if there were no readlines method on f, and this could
> wrap f on the fly to provide the missing readlines method.


My head spins... I don't know if I should consider these ideas very
powerful -- or very evil... My guts tell me that this could be very
powerful indeed. However my intuition tells me that there is a big
catch about this, but I don't know what it is yet...

--Irmen

 
Reply With Quote
 
Ian Bicking
Guest
Posts: n/a
 
      07-03-2003
On Wed, 2003-07-02 at 15:09, Bengt Richter wrote:
> Hm, it just occurred to me that one could have yet another form of sugar
> [ It's now later, and I think this may be more than sugar ]
> to help with this, by treating the dot operator slightly more symmetrically,
> like, e.g., '+'.
>
> Example, then explanation:
>
> a = 7 .USD # (using symbols from http://www.xe.com/iso4217.htm by convention, no hard defs)
> # ...
> a = 6 .USD


Does 7 .USD *really* look that much better than USD(7)? And, really,
how often do you need currency literals? All my currency values come
from non-literal sources -- databases and XML files, an excel
spreadsheet, etc. I don't think this objection is particular to
currency either -- for most types this is true. If you are using them a
lot, you are acquiring them from non-code sources.

Though I suppose Rebol would be a counterexample. And, in the case of
scripting (a kind of programming, not a kind of programming language
it might be a more valid need. But most of Rebol's interesting data
types aren't syntactically valid in Python anyway.

Ian



 
Reply With Quote
 
Rim
Guest
Posts: n/a
 
      07-03-2003
Everyone! Thanks a lot for the insightful and enlightening discussion.

I think the suggestion to solve the problem by using the __setattr__
special method will not work because it intercepts attribute
assignment of the form "self.attr = somthing", and not what I want,
which is "name = something".

John suggested to look at properties, this is the closest I can get to
the
behavior I am looking for, but from my understanding, that will let me
intercept "name.value = something" instead of intercepting "name =
something".

Thank you very much everyone.
- Rim
 
Reply With Quote
 
Michele Simionato
Guest
Posts: n/a
 
      07-03-2003
(E-Mail Removed) (Rim) wrote in message news:<(E-Mail Removed). com>...
> Everyone! Thanks a lot for the insightful and enlightening discussion.
>
> I think the suggestion to solve the problem by using the __setattr__
> special method will not work because it intercepts attribute
> assignment of the form "self.attr = somthing", and not what I want,
> which is "name = something".
>
> John suggested to look at properties, this is the closest I can get to
> the
> behavior I am looking for, but from my understanding, that will let me
> intercept "name.value = something" instead of intercepting "name =
> something".
>
> Thank you very much everyone.
> - Rim


Okay, you asked for it

class MetaTrick(type):
def __init__(cls,name,bases,dic):
super(MetaTrick,cls).__init__(name,bases,dic)
for (k,v) in dic.iteritems():
if not k.endswith("__"): setattr(cls,k,v)
def __setattr__(cls,k,v):
print "Intercepting %s = %s" % (k,v)
super(MetaTrick,cls).__setattr__(k,v)

class C:
__metaclass__=MetaTrick
name='something'

This gives the output "Intercepting name = something".

I show you this snippet hoping you will not use it!

nothing-is-impossible-with-metaclasses-ly,

Michele
 
Reply With Quote
 
Aahz
Guest
Posts: n/a
 
      07-03-2003
In article <(E-Mail Removed) >,
Rim <(E-Mail Removed)> wrote:
>
>I think the suggestion to solve the problem by using the __setattr__
>special method will not work because it intercepts attribute
>assignment of the form "self.attr = somthing", and not what I want,
>which is "name = something".


Why don't you follow my suggestion about creating your own language?
--
Aahz ((E-Mail Removed)) <*> http://www.pythoncraft.com/

Usenet is not a democracy. It is a weird cross between an anarchy and a
dictatorship.
 
Reply With Quote
 
Rim
Guest
Posts: n/a
 
      07-04-2003
> >I think the suggestion to solve the problem by using the __setattr__
> >special method will not work because it intercepts attribute
> >assignment of the form "self.attr = somthing", and not what I want,
> >which is "name = something".

>
> Why don't you follow my suggestion about creating your own language?


I think it would be too much work for one person, and I don't know
how, and I don't think I have the time. Thanks but for now this is
beyond my limited capabilities!

Rim
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
overloading operator->*() and operator->() gob00st@googlemail.com C++ 2 02-21-2009 04:26 AM
overloading operator->*() and operator->() gob00st@googlemail.com C++ 11 02-20-2009 08:52 PM
user defined conversion operator or operator overloading? hurcan solter C++ 3 08-29-2007 07:39 PM
Why is overloading operator. (member operator) forbidden? dascandy@gmail.com C++ 11 05-16-2007 07:54 PM
Operator overloading on "default" operator John Smith C++ 2 10-06-2004 10:22 AM



Advertisments