Google Groupes n'accepte plus les nouveaux posts ni abonnements Usenet. Les contenus de l'historique resteront visibles.

Suggesting for overloading the assign operator

3 vues
Accéder directement au premier message non lu

Rim

non lue,
30 juin 2003, 23:31:4730/06/2003
à
Hi,

I have been thinking about how to overload the assign operation '='.
In many cases, I wanted to provide users of my packages a natural
interface to the extended built-in types I created for them, but the
assign operator is always forcing them to "type cast" or coerce the
result when they do a simple assign for the purpose of setting the
value of a variable. Borrowing an example from this newgroup, the
second assignment below ereases all Currency knowledge from variable
'c', when the user only wanted to update the value of c, not its type:

c=Currency(5)
c=7

I fully understand the workaround of doing c=Curreny(7) instead, but
users don't want to be bothered with that.

I read some of the prior discussions, but I did not see a suggestion
for permanent a solution. I would like to propose the following.

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

For example:

>>> class myint(int): pass
...
>>> a = myint()
>>> a := 6
type(a)
<class '__main__.myint'>
>>> a
6

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.

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.

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

Thanks,
- Rim

Terry Reedy

non lue,
1 juil. 2003, 00:13:4301/07/2003
à

"Rim" <rimb...@yahoo.com> wrote in message
news:6f03c4a5.03063...@posting.google.com...

> Hi,
>
> I have been thinking about how to overload the assign operation '='.

Assignment is a statement, not an operator, and therefore not
overloadable . This is an intentional design decision that GvR will
not change.

TJR


Michele Simionato

non lue,
1 juil. 2003, 07:28:5801/07/2003
à
rimb...@yahoo.com (Rim) wrote in message news:<6f03c4a5.03063...@posting.google.com>...

> Hi,
>
> I have been thinking about how to overload the assign operation '='.

Notice that you can always override __setattr__ ...

Michele

sism...@hebmex.com

non lue,
1 juil. 2003, 10:06:3801/07/2003
à
> From: rimb...@yahoo.com [mailto:rimb...@yahoo.com]
> Sent: Lunes, 30 de Junio de 2003 10:32 p.m.
>
> Hi,
>
> [..same rehash of overloading '=' a'la C++...]

>
> 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.
>
> I think it would be a nice feature to have. Comments?
>

It's *not* a nice feature to have. If this kind of
functionality, strictly applicable to mutable types,
is needed, then a self.set(x) method, or a self.value = x
property, can be created.

An overloadable assignment _statement_ is not going
to happen.

>
> Thanks,
> - Rim
>

You're welcome.

-gustavo
Advertencia:La informacion contenida en este mensaje es confidencial y
restringida, por lo tanto esta destinada unicamente para el uso de la
persona arriba indicada, se le notifica que esta prohibida la difusion de
este mensaje. Si ha recibido este mensaje por error, o si hay problemas en
la transmision, favor de comunicarse con el remitente. Gracias.

John Roth

non lue,
1 juil. 2003, 12:44:0201/07/2003
à

"Rim" <rimb...@yahoo.com> wrote in message
news:6f03c4a5.03063...@posting.google.com...
> Hi,
>
> I have been thinking about how to overload the assign operation '='.
> In many cases, I wanted to provide users of my packages a natural
> interface to the extended built-in types I created for them, but the
> assign operator is always forcing them to "type cast" or coerce the
> result when they do a simple assign for the purpose of setting the
> value of a variable.

Use a property. Changing the semantics of the assignment
statement (NOT assignment operator) is not going to happen.

Properties are new in Python 2.2 (which is around a year
old by now.) They enable you to have getter and setter
methods with an interface that looks like an instance
variable.

John Roth


Rim

non lue,
1 juil. 2003, 13:07:0401/07/2003
à
"Terry Reedy" <tjr...@udel.edu> wrote in message news:<coqdnfH2G47...@comcast.com>...

Well, what about the idea of providing another statement, the one I
proposed in the original post?

'=' statement assigns type and value
':=' statement assigns value only

Rim

Rim

non lue,
1 juil. 2003, 13:10:2601/07/2003
à
mi...@pitt.edu (Michele Simionato) wrote in message news:<2259b0e2.03070...@posting.google.com>...

Thanks. I have noticed that already, but it does not give me what I
want. What do you think about providing a statement to assign values
without assigning type?

'=' statement assigns value and type
':=' statement assigns value ony

Rim

Alan Kennedy

non lue,
1 juil. 2003, 14:01:3101/07/2003
à
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

a = 9
b = 42
if isinstance(b, type(a)):
a = b
else:
raise TypeError("Incompatible types.")

However, these options, i.e. putting type checking logic in "setattr" et al, do
not make it explicit in the code that type enforcement is in place.

Expressing the enforcement syntactically, as Rim suggests, would make it more
explicit for the programmer, as well as providing some extremely useful
optimisation hints, especially for products such as psyco.

Psyco, if I understand it correctly, generates machine code for all paths
through a suite, depending on the types of the objects manipulated in the suite.
Such explicitly stated type enforcement would provide valuable information to
optimisers.

Not that I'm proposing that the OPs solution be adopted. Just that I think he is
addressing a valid concern.

regards,

--
alan kennedy
-----------------------------------------------------
check http headers here: http://xhaus.com/headers
email alan: http://xhaus.com/mailto/alan

Aahz

non lue,
1 juil. 2003, 14:28:3801/07/2003
à
In article <6f03c4a5.03063...@posting.google.com>,

Rim <rimb...@yahoo.com> wrote:
>
>I have been thinking about how to overload the assign operation '='.
>In many cases, I wanted to provide users of my packages a natural
>interface to the extended built-in types I created for them, but the
>assign operator is always forcing them to "type cast" or coerce the
>result when they do a simple assign for the purpose of setting the
>value of a variable. Borrowing an example from this newgroup, the
>second assignment below ereases all Currency knowledge from variable
>'c', when the user only wanted to update the value of c, not its type:
>
>c=Currency(5)
>c=7
>
>I fully understand the workaround of doing c=Curreny(7) instead, but
>users don't want to be bothered with that.

If you have users who don't want to learn Python, give them a special
Python-like language. I won't say it's trivial, but it's not that hard.
--
Aahz (aa...@pythoncraft.com) <*> http://www.pythoncraft.com/

Usenet is not a democracy. It is a weird cross between an anarchy and a
dictatorship.

Michael Chermside

non lue,
1 juil. 2003, 14:33:4901/07/2003
à
Rim writes:
> I have been thinking about how to overload the assign operation '='.
[...]

> the
> second assignment below ereases all Currency knowledge from variable
> 'c', when the user only wanted to update the value of c, not its type:
>
> c=Currency(5)
> c=7
>
> I fully understand the workaround of doing c=Curreny(7) instead, but
> users don't want to be bothered with that.

I think you have a fundamental misunderstanding of how assignment works
in Python. In some languages (C for example) variables are things that
have a TYPE and a VALUE. You typically set the TYPE by declaring the
variable and typically can't change it. You typically set the VALUE
by assignment. In at least one case (C++ is the only example I know of)
you can override the meaning of assignment to variables of a certain
type.

In Python, variables do NOT have a type and a value. Instead, variables
have a single value, which is always some object. Objects have a type
(and sometimes a class also... I'm not going to worry about this
difference). But there's little connection between variables and types.
When we assign (actually, a better term is "rebind") a variable it can
be assigned to any object.
>>> x = "a string"
>>> x = 5
>>> x = Currency(7)

I'm confident that what you want to achieve can be accomplished in
Python, you just have to adjust your mindset. In Python it's useful to
think of things in terms of namespaces. (See last line of
"http://www.awaretek.com/zen.html".) Namespaces are just dictionaries
-- and they're used throughout Python. When you write
>>> x = "abc"
you are simply performing __setitem__("x", "abc") on a namespace called
the "module globals". If you want, you can get ahold of this dictionary
via the function globals(), and you can see that manipulating it is just
the same as using "=".
>>> x = 'a string'
>>> theGlobals = globals()
>>> print theGlobals
{'__builtins__': <module '__builtin__' (built-in), '__name__':
'__main__', 'theGlobals': {...}, '__doc__': None, 'x': 'a stri
ng'}
>>> theGlobals["y"] = 7
>>> print y
7
Function definition is just another operation on this namespace...
writing "def func(x): return x + 1" is (almost) the same as
"globals()["x"] = lambda x: x + 1". When you use local variables
within a function, you are manipulating another namespace, (for
performance purposes it's not actually implemented as a dictionary,
but it acts as if it were... just call locals() to see it as a dict).

So when you say that you want your users to be able to do this:
>>> x = Currency(5)
>>> x = 7
and then have x be a Currency object, what you're *really* saying is
that you want to take over control of the namespace that your users
are working in so that they can't store just anything in it, but
are forced to store only Currency objects. Or perhaps you mean for
them to be able to store only Currency objects for any key which
was previously used for a Currency object. Or maybe you mean that
if they try storing a NUMBER in a slot which was previously used to
store a Currency object that a new Currency object should be stored
instead. Actually, I'm not quite certain what your requirements are,
but it's pretty clear to me that what you want is a special namespace
with custom behavior.

Well, Python provides special namespaces with customizable
behavior. They're called classes. Classes are just another namespace
("one honking great idea")... well, technically TWO namespaces:
one for the class itself and one for the individual object. Normally,
saying "myObject.x = 7" performs another dictionary assignment
(this dictionary is accessible as "myobject.__dict__"), but you can
use the special functions __getattr__, __setattr__, __delattr_, and
perhaps __getattribute__ to customize its behavior.

So I'm guessing that you can accomplish your objective by getting
your users to store their values as fields in an object and providing
customized behavior on that object. I was going to suggest that you
create a custom dict type (here's one that just prints stuff out
when modified... you could use any logic you wanted):

>>> class NoisyDict(dict):
... def __setitem__(self, key, value):
... print 'setting %s to %r' % (key, value)
... dict.__setitem__(self, key, value)
...

and that you then use it in an exec statement, like this:

>>> exec "x = 7\nprint x" in NoisyDict()
7

Unfortunately, it didn't work (that printed "7", but didn't print
"setting x to 7"), so you may need a slightly better guru than me
to get this working. Or if you can better describe your PARTICULAR
problem, I may be able to figure out how to approach it. But I'm
almost certain that there's a much easier way than changing how
Python does assignments.

-- Michael Chermside


Steven Taschuk

non lue,
1 juil. 2003, 11:22:0301/07/2003
à
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:

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.)

Would ':=' support chaining? That is, would
a := b := <some expression>
work? If so, would it be equivalent to
_tmp = <some expression>
a := _tmp
b := _tmp
(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?

> 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?

> 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.)

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.)

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

--
Steven Taschuk stas...@telusplanet.net
"Our analysis begins with two outrageous benchmarks."
-- "Implementation strategies for continuations", Clinger et al.

John Roth

non lue,
1 juil. 2003, 17:17:0101/07/2003
à

"John Roth" <john...@ameritech.net> wrote in message
news:vg3eghr...@news.supernews.com...

I usually don't reply to my own posts, but I thought it
might be nice if I put up a skeletal example of how to do it.

I'm assuming that what you want is a way of insuring, in a
class named Foo, that the variable fooBar is always bound
to a class instance of Bar, regardless of what the user tries
to assign to it.

Most of what follows is documented in "What's New in Python 2.2,"
section 2: Peps 252 and 253: Type and Class Changes.

The information on the __new__ method is in the document
under 2.5: Related Links.

The way to do this is:

1. Both Foo and Bar have to inherit from a built-in type.
That's usually "object", but it can be any built-in type.

2. Refactor Foo so that all references to self.fooBar
now refer to self._fooBar. (It can be any name; the
underscore is a convention that means "private."

3. Insert the following code in Foo:

def _getFooBar(self):
return self._fooBar

def _setFooBar(self, parm):
self._fooBar = Bar(parm)

_fooBar = property(_setFooBar, _getFoobar, None, "doc strings swing")

4. In class Bar, use the __new__ method to check if
the parameter is an instance of class Bar. If it is, return that
instance, otherwise call your superclass's __new__ method
to create a new object and return it.

5. In class Bar, do whatever type determination you need to
in the __init__ method to build your new Bar object.

Most of this is documented in "What's New in Python 2.2,"
section 2: Peps 252 and 253: Type and Class Changes.

The information on the __new__ method is in the document
under 2.5: Related Links.

HTH

John Roth

>
>


Cliff Wells

non lue,
1 juil. 2003, 17:50:0501/07/2003
à
On Mon, 2003-06-30 at 20:31, Rim wrote:

> 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

On the surface, this idea seems appealing. However, besides the
arguments that others have forwarded, you might consider the fact that
given two similar "assignment operators", subtle bugs are bound to
arise.

> >>> class myint(int): pass
> ...
> >>> a = myint()
> >>> a := 6
> type(a)
> <class '__main__.myint'>
> >>> a
> 6

What if the programmer accidentally uses '=' rather than ':=' (and I
think this would be a natural mistake)? It would be legal Python but
would probably not have the intended effect. It is not unlike the
"allow assignment in expressions" arguments that come up here every 3.2
weeks.

Anyway, your arguments cancel themselves out. You asked initially for a
way to overload '=' because your users didn't want to have to type
something different. But ':=' *is* different, so what are you really
looking for?. Worse, because ':=' isn't *very* different, it makes
mistakes more likely.

In short, I think using a = myint(6) or even a.value = 6 is preferable.
Besides, when I used Pascal (many years ago), I found ':=' to be one of
the most annoying (and most common) things I had to type. Please don't
ask to bring it back.


Regards,

--
Cliff Wells, Software Engineer
Logiplex Corporation (www.logiplex.net)
(503) 978-6726 (800) 735-0555


sism...@hebmex.com

non lue,
1 juil. 2003, 17:19:0701/07/2003
à
> From: rimb...@yahoo.com [mailto:rimb...@yahoo.com]
> Sent: Martes, 01 de Julio de 2003 12:07 p.m.

>
> Well, what about the idea of providing another statement, the one I
> proposed in the original post?
>
> '=' statement assigns type and value
> ':=' statement assigns value only
>
> Rim
>

Probably the reason most prople on this list don't quite
like these threads is that there's no *need* for this
"value-assignment" operation.

For one, how would you implement it for immutable data
types?

This ":=" statement you're talking about already exists
for lists, you can do something like:

A[:] = some_other_list

Why? Because you're assigning to a slice of A (which happens
to be the whole list) the contents of the second list.

But, what about strings, for example? Or ints? Or longs,
floats, complexes? These data types are not mutable,
an int object like, for example, 123, cannot change it's
value to some other value, like 124. It's created
with that value and lives like that until destroyed,
or the end of the program. Same goes for all those
other immutable types mentioned above.

Why would you need such an operation?

Is there some unsurmountable programming problem that cannot
be solved except by such a vile hack as an overloadable
assignment operator? The existance of huge software
projects already done in python (such as Zone, Yahoo,
and others) tells me that the language really doesn't
need it.

Another question would be, why not tell us what
you're trying to do (which most probably looks like
a C++ algorith or something like that) and how can
we help you turn it into a Python algorithm?

Programming C++ in Python is difficult.

Cliff Wells

non lue,
1 juil. 2003, 17:53:2001/07/2003
à
On Tue, 2003-07-01 at 11:01, Alan Kennedy wrote:
> Not that I'm proposing that the OPs solution be adopted. Just that I think he is
> addressing a valid concern.

I agree that it is a valid concern. I think, however, that other valid
concerns outweigh this one. I suspect you think so as well, otherwise
you would have omitted the first sentence.

Ian Bicking

non lue,
1 juil. 2003, 18:13:0101/07/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

Bengt Richter

non lue,
1 juil. 2003, 22:07:2101/07/2003
à
On Tue, 1 Jul 2003 09:22:03 -0600, Steven Taschuk <stas...@telusplanet.net> 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

Steven Taschuk

non lue,
2 juil. 2003, 10:21:5702/07/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 stas...@telusplanet.net
"What I find most baffling about that song is that it was not a hit."
-- Tony Dylan Davis (CKUA)

sism...@hebmex.com

non lue,
2 juil. 2003, 10:22:4902/07/2003
à
> From: bo...@oz.net [mailto:bo...@oz.net]
> Sent: Martes, 01 de Julio de 2003 09:07 p.m.
>
> [...snippage...]

>
> 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))
>

And people say Forth is unreadable. Yeesh.

>
> ?? ;-)
>
> Regards,
> Bengt Richter
>

-gustavo

--

Bengt Richter

non lue,
2 juil. 2003, 16:09:4702/07/2003
à
On Wed, 2 Jul 2003 08:21:57 -0600, Steven Taschuk <stas...@telusplanet.net> 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

Irmen de Jong

non lue,
2 juil. 2003, 16:47:3202/07/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... :-P

--Irmen

Ian Bicking

non lue,
2 juil. 2003, 20:16:1402/07/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

Rim

non lue,
3 juil. 2003, 01:19:4203/07/2003
à
> Do they not understand that '=' binds a name to an object? Are

They do understand the binding to the object, but there are objects
that do not need explicit casting, like integers. As you know you can
say "name = 18" and name will become an int, but int was not
explicitely specified, it was infered by the interpreter, but as soon
as I extend int to myint, I suddenly have to do "name = myint(18)",
which I find annoying, but if that's the way it is so be it.

Thanks!
- Rim

Rim

non lue,
3 juil. 2003, 01:19:5103/07/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

Michele Simionato

non lue,
3 juil. 2003, 11:32:2803/07/2003
à
rimb...@yahoo.com (Rim) wrote in message news:<6f03c4a5.03070...@posting.google.com>...

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

Aahz

non lue,
3 juil. 2003, 11:52:1003/07/2003
à
In article <6f03c4a5.03070...@posting.google.com>,

Rim <rimb...@yahoo.com> 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?

Rim

non lue,
4 juil. 2003, 08:33:4804/07/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

Corey Coughlin

non lue,
8 juil. 2003, 14:50:5608/07/2003
à
You know, I couldn't even figure out what the whole ':=' assignment
did until I saw this message:

bo...@oz.net (Bengt Richter) wrote in message

> 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 ;-)
>

So what we're talking about here is some form of type driven
assignment? Where you can assign to properties of an object given a
specific type of rhs expression? I guess that could be useful, but it
sounds like it could only apply to a very small set of objects, namely
objects where all the properties have different types. It seems like
adding a new syntax to support a fairly small subset of objects is a
long way to go to make things 'easier'. It looks like it would be easy
to screw up, too. For instance:

class Point(object):
def __init__(self, nx, ny):
self.x = nx
self.y = ny
def __typeassign__(self, whatever):
# some magic #

a = Point(3,4) # so far so good
a := (3,4) # ok, that could work
a := 3 # hmm... will it set x, or y, or x and y, or give an
exception?

or, let's go with the currency example:

class Currency(object):
def __init__(self, cval):
self.amount = cval
self.exchangerate = 1.0
def __typeassign__(self, whatever):
#even better magic #

a = Currency(7)
a := 6 # so does this change the amount, or the exchange rate?

So it looks like the behavior here would be at best unpredictable,
unless you already have a deep understanding of what's going on in the
object. (And if you have a deep understanding of what's going on in
the object, would 'a.amount' be so tricky to use?) Now sure, there
are lots of operations that aren't used by every object, but assigning
values to object attributes is a pretty fundamental part of any object
oriented language, and the way Python does it now seems to work for a
lot of people. From the original example, it looks kind of like you
want to define a sort of user-definable built in type, like integer or
string, where there is always a singular piece of data that may have
special functional attributes but no other data attributes. But in
that case, you wouldn't want to assign it as a regular object, you'd
want to build in a special syntax that Python could use to understand
the built in type, so you would have to have:

a = $7
a = $6

so I guess even that wouldn't work quite the way you want. So for
now, I vote no to adding ':=' assignment. Sorry if this is too basic
a look at this, it takes me a while to wrap my head around this
complicated syntax stuff.

0 nouveau message