Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

self

2 views
Skip to first unread message

Vojin Jovanovic

unread,
Jun 4, 2002, 12:15:22 PM6/4/02
to
I have been working on a project trying to implement some advanced
functionality. Now, one thing that has been a constraint for me is the
concept of self. Why is it that within a class one has to use self. (or
"any word". ) to refer to instance variables? Would it not be more logical
to just use the name of the variable like it is for example in C++?

Vin


Gerhard Häring

unread,
Jun 4, 2002, 12:27:53 PM6/4/02
to
It's good practice in C++ and Java too, to always use this->myvar resp.
this.myvar.

I hate to have to look at code where the scope of the variable isn't obvious at
once. And I also hate conventions like m_mymembervar to distinguish members
from locals.

Gerhard

Eric Brunel

unread,
Jun 4, 2002, 2:38:22 PM6/4/02
to

This is *not* a variable, this is an attribute. Hence the "self.". I always
found the C++/Java convention particularly disturbing. With this
convention, there's no obvious means to tell a local variable from an
object's attribute:

public class C {
public int a;

public void m() {
int b;

a = 0; // What's the difference
b = 0; // between these 2 lines?
}
}

The notation is exactly the same for two quite different things:
- "a = 0;" means "set the value of attribute a of method's receiver to 0",
setting that will still exist after the method's end
- "b = 0" means "set the value of the variable b, local to method m, to the
value 0", setting that will be discarded after the method's end

Not using any prefix in front of attribute names in methods is IMHO a
dangerous shortcut, and a confusing one... I really prefer Python's
notation, which is indeed a bit "heavier", but far less confusing. You'll
certainly find your code far more readable in a few months than it would be
in C++ or Java.
--
- Eric Brunel <eric....@pragmadev.com> -
PragmaDev : Real Time Software Development Tools - http://www.pragmadev.com

Andrew Koenig

unread,
Jun 4, 2002, 12:52:24 PM6/4/02
to
Vojin> I have been working on a project trying to implement some
Vojin> advanced functionality. Now, one thing that has been a
Vojin> constraint for me is the concept of self. Why is it that
Vojin> within a class one has to use self. (or "any word". ) to refer
Vojin> to instance variables? Would it not be more logical to just use
Vojin> the name of the variable like it is for example in C++?

It has advantages and disadvantages. The obvious disadvantage of
having to use "self" to refer to every instance variable is that
you have to use "self" to refer to every instance variable.

The advantage of having to use "self" to refer to every instance
variable is that there is never any doubt about whether a given name
represents an instance variable. These doubts can cause trouble for
C++ programmers; whether the convenience of not having to utter
"this->" constantly is a matter of personal taste and opinion.

For Python, requiring the explicit use of "self" is clearly the
right choice because variables are so dynamic that it would not
generally be possible to tell during compilation whether a
particular name refers to an instance variable.

--
Andrew Koenig, a...@research.att.com, http://www.research.att.com/info/ark

Jeff Epler

unread,
Jun 4, 2002, 12:31:47 PM6/4/02
to
On Tue, Jun 04, 2002 at 12:15:22PM -0400, Vojin Jovanovic wrote:
> Would it not be more logical
> to just use the name of the variable like it is for example in C++?

Nope. (Hint:
http://www.python.org/cgi-bin/faqw.py?req=show&file=faq06.007.htp)

Jeff
PS we love it this way. You will too.


Tim Peters

unread,
Jun 4, 2002, 12:28:38 PM6/4/02
to
[Vojin Jovanovic]

...
class C:
...
def vojin(self):
i = j + k

Which of i, j and k are instance variables? Which are locals? Which are
globals? For all its virtues, Python isn't telepathic <wink>.

Vojin Jovanovic

unread,
Jun 4, 2002, 2:35:24 PM6/4/02
to
> Which of i, j and k are instance variables? Which are locals? Which are
> globals? For all its virtues, Python isn't telepathic <wink>.

Well, now that you pointed it out, I think that Python should be telepathic.
Those i,j and k variables should have been found in class C, otherwise they
should have been searched outside of the class. I read the FAQ page that
somebody sent me and I really think that the main reason for self is ...
"When classes were added to Python, this was (again) the simplest way of
implementing methods without too many changes to the interpreter. " which is
the main and really lousy argument. All, other arguments are debatable.

Now let me give you the problem with self which is making my life
complicated. Consider this class.

class Foo:
def __init__(self):
self.__dict__['Equations']={
'a':str(5),
'b':'self.a+5',
'c':'self.b*self.a'}

def __getattr__(self,arg):
if self.Equations.has_key(arg) == 0:
raise AttributeError, "Foo instance has no attribute '" + arg + "'"
try:
try: #first check if this is a simple expression
return eval(self.Equations[arg])
except: #if not try to execute it
exec self.Equations[arg]
except: #if even that didn't work then just return undefined
return '#U'

def __setattr__(self,arg,val):
self.__dict__['Equations'][arg]=str(val)

def __delattr__(self,arg):
del self.__dict__['Equations'][arg]

This class implements a kind of symbolic behavior with the ability to add
new equations on the fly. For example...


>>> import foo
>>> A=foo.Foo()
>>> A.Equations
{'b': 'self.a+5', 'c': 'self.b*self.a', 'a': '5'}
>>> A.f='self.b*self.c'
>>> A.f
500
>>> A.Equations
{'f': 'self.b*self.c', 'b': 'self.a+5', 'c': 'self.b*self.a', 'a': '5'}


As you can see, equations get added on the fly and the parsing gets done as
the attribute is being called. Now, notice that ugly self. thing in the
equations. Instead of just typing >>>A.f='a*c' I have to add self in front
a and c to achieve the desired effect. I could not find any other way to
implement the class in order to avoid typing self. which of course it
doesn't mean that there isn't any. If anybody has an idea how to do this
please let me know. Otherwise, here is the situation where the self
concept is bad and having such a dynamic language like Python I think there
has to be a way out of this problem.

Why is this all relevant? Well, I am working on embedding an interpreted
language in a large engineering application and Python is one of few
candidates. So I have been looking for its pros and cons. So far it passed
all the tests except the above. Because, imagine if we required from the
user of our system that he needs to type self. or even s. in front of every
new variable that he has in his equation, it would be a big turn off.

Vin

Sean 'Shaleh' Perry

unread,
Jun 4, 2002, 2:49:04 PM6/4/02
to
> As you can see, equations get added on the fly and the parsing gets done as
> the attribute is being called. Now, notice that ugly self. thing in the
> equations. Instead of just typing >>>A.f='a*c' I have to add self in front
> a and c to achieve the desired effect. I could not find any other way to
> implement the class in order to avoid typing self. which of course it
> doesn't mean that there isn't any. If anybody has an idea how to do this
> please let me know. Otherwise, here is the situation where the self
> concept is bad and having such a dynamic language like Python I think there
> has to be a way out of this problem.
>
> Why is this all relevant? Well, I am working on embedding an interpreted
> language in a large engineering application and Python is one of few
> candidates. So I have been looking for its pros and cons. So far it passed
> all the tests except the above. Because, imagine if we required from the
> user of our system that he needs to type self. or even s. in front of every
> new variable that he has in his equation, it would be a big turn off.
>

why can't your class be an interpreter for math expressions?

it sees 'a*c' and asks it own dict 'do we know a?' if so it access dict['a']
and returns its value. Looking at your example you seem to be implementing a
symbolic calculator. Most implementations I have seen involve writing a small
language with interpreter.


Terry Reedy

unread,
Jun 4, 2002, 3:22:18 PM6/4/02
to

"Vojin Jovanovic" <vjov...@stevens-tech.edu> wrote in message
news:TL7L8.79$4p7.4...@newnews.cc.stevens-tech.edu...
[snip]

> Why is this all relevant? Well, I am working on embedding an
interpreted
> language in a large engineering application and Python is one of
few
> candidates. So I have been looking for its pros and cons. So far
it passed
> all the tests except the above. Because, imagine if we required
from the
> user of our system that he needs to type self. or even s. in front
of every
> new variable that he has in his equation, it would be a big turn
off.

Now that you have explained your actual problem, I believe there is a
simple solution that does not require breaking half of all Python code
written.

Add another dict 'Symbols' to your class. Then eval/exec your
equations 'in' Symbols as the local/global namespace. No 'self.'
needed then. This is also a good idea for security reasons, but
others have posted on that. Plus, you can initialize 'Symbols' with
the contents of the math module and add any other engineering
functions you want available for use in equations.

Terry J. Reedy


Vojin Jovanovic

unread,
Jun 4, 2002, 3:49:06 PM6/4/02
to
I don't see how that is going to work. In fact I tried things like that
before without success. Just sticking the dictionary into eval/exec is
missing the point. Every time parsing is done flow needs to go through
__getattr__ special method to evaluate nested equations. Without self. you
can't achieve that effect. Try the approach you suggested and you'll get
'#U'.


Vin


"Vojin Jovanovic" <vjov...@stevens-tech.edu> wrote in message
news:TL7L8.79$4p7.4...@newnews.cc.stevens-tech.edu...

holger krekel

unread,
Jun 4, 2002, 5:02:45 PM6/4/02
to
Vojin Jovanovic wrote:
> Now let me give you the problem with self which is making my life
> complicated. Consider this class.
>
> class Foo:
> def __init__(self):
> self.__dict__['Equations']={
> 'a':str(5),
> 'b':'self.a+5',
> 'c':'self.b*self.a'}
>
> (...)

To get rid of 'self' you might like to try this:

class Evaluator:
def __init__(self, eqs={}):
self.__dict__['equations']=eqs
def __getattr__(self, name):
begin={}
while 1:
try:
return eval(self.equations[name], begin)
except NameError, n:
var=str(n).split("'")[1]
begin[var]=getattr(self, var)
def __setattr__(self, name, value):
self.equations[name]=value

>>> e=Evaluator({'a':'3', 'b':'a*17', 'c': 'b*a'})
>>>
>>> e.c
153
>>> e.f='a*c'
>>> e.f
459

I don't really think that 'execing' is a good idea here
but i don't know your complete usecase.

With a little more care it should be possible to
catch cyclic equations.

have fun,

holger


Sean 'Shaleh' Perry

unread,
Jun 4, 2002, 4:56:04 PM6/4/02
to

On 04-Jun-2002 Vojin Jovanovic wrote:
> I don't see how that is going to work. In fact I tried things like that
> before without success. Just sticking the dictionary into eval/exec is
> missing the point. Every time parsing is done flow needs to go through
> __getattr__ special method to evaluate nested equations. Without self. you
> can't achieve that effect. Try the approach you suggested and you'll get
> '#U'.
>

calc.setEquation('f = a*c')
calc.valueFor('f')

sometimes you can just redesign.


Bjorn Pettersen

unread,
Jun 4, 2002, 5:09:07 PM6/4/02
to
> From: Vojin Jovanovic [mailto:vjov...@stevens-tech.edu]
>
> I don't see how that is going to work. In fact I tried
> things like that before without success. Just sticking the
> dictionary into eval/exec is missing the point. Every time
> parsing is done flow needs to go through __getattr__ special
> method to evaluate nested equations. Without self. you can't
> achieve that effect. Try the approach you suggested and
> you'll get '#U'.

Perhaps something like this?

-- bjorn


class Eval:
def __init__(self):
self.__dict__['dict'] = {}
exec "from math import *" in self.dict

def __call__(self, expr):
try:
return eval(expr, self.dict, self.dict)
except SyntaxError:
exec expr in self.dict, self.dict

def __getattr__(self, attr):
return self.dict[attr]

def __setattr__(self, attr, val):
self.dict[attr] = eval(val, self.dict, self.dict)

e = Eval()

print e('pi * 3')
e('x = sin(0.5)')
print e.x
e.y = 'sin(0.5)'
print e.y


Greg Ewing

unread,
Jun 4, 2002, 11:44:05 PM6/4/02
to
Eric Brunel wrote:
>
> I always
> found the C++/Java convention particularly disturbing.

If you want something really disturbing, try the
Apple Object Pascal scope rules:

type
Foo = object
a: integer;
procedure blarg(a: integer);
end;

procedure Foo.blarg(a: integer);
begin
writeln(a);
end;

Quickly, now -- which 'a' does that write out?
.
.
.
(answer below)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.

Believe it or not, it writes the *attribute* a,
not the parameter!

--
Greg Ewing, Computer Science Dept,
University of Canterbury,
Christchurch, New Zealand
http://www.cosc.canterbury.ac.nz/~greg

Nicola Kluge

unread,
Jun 5, 2002, 1:45:01 AM6/5/02
to
This is an interesting idea. However, your approach doesn't handle the dot
notation.
For example,
If object.x was = to 3 and g was = to 4 I need that
e.f='object.x*g' gives 12.
Just having e=Evaluator({'a':'3', 'b':'a*17', 'c':
'b*a','object.x':'3','g':'4'})
doesn't work. While parsing, 'object.x' is not taken as one symbol in your
approach.
I need to have object capabilities in the equations.

Vojin Jovanovic

"holger krekel" <py...@devel.trillke.net> wrote in message
news:mailman.102322464...@python.org...

Nicola Kluge

unread,
Jun 5, 2002, 2:14:20 AM6/5/02
to
Interesting approach. However, once you do that. The symbolic form of the
equations is lost. For example,
>>> c=Eval()
>>> c.y='3'
>>> c.y
3
>>> c.a='4'
>>> c.a
4
>>> c.f='y*a'
>>> c.f
12

but
>>> c.__dict__['dict']['f']
12

doesn't give you the equation back.

Your, approach goes under a lazy evaluation business. However, I need to
have all dependent attributes which are nested deeper to be evaluated every
time. That is why the equations should be retained in the dictionary. I
don't want to worry whether the previously evaluated attribute holds the
updated value or not. Evaluations have to propagate all the way to the end,
for example in the above case, while evaluating c.f the evaluation should
evaluate 'y' so that we are sure that 'y' is still 3. In you approach the
evaluation stops at 'f'=12 but it can't see whether 'y' changed even though
'f' once depended on 'y'.

Vojin Jovanovic


"Bjorn Pettersen" <BPett...@NAREX.com> wrote in message
news:mailman.1023225848...@python.org...

Jeff Epler

unread,
Jun 5, 2002, 8:34:40 AM6/5/02
to
Nicola,
If you are going to always store the equation, never the value, what
happens when the user does
c.y = 37
c.y = 'y+1'
? As far as I understand it, this would have to put the parser into an
infinite loop when
c.y
is later referenced (since it must be determined by taking the value of
y and adding 1, but the value of y must be determined by ...)

You'd need to detect this problem somehow, and presumably not let
c.y = 'y+1'
execute at all, but (especially if you allow dotted references like q.y)
this will be a bit of a pain to detect... regular expressions *might* be
up to the task (for a particular expression), but quite possibly not.
Then you're left with detecting stuff like
c.x = "y"
c.y = "x+1"
where it's a two-step process. You have to determine that x uses
the value of y, and that y uses the value of x, to notice the cycle and
prevent the second assignment.

You're getting closer to the point where using the parser module to
parse the string as though it were an expression using
>>> tree = parser.expr("x+1").totuple()
>>> pprint.pprint(tree)
(258,
(313,
(292,
(293,
(294,
(295,
(297,
(298,
(299,
(300,
(301,
(302, (303, (304, (305, (1, 'x'))))),
(14, '+'),
(302, (303, (304, (305, (2, '1'))))))))))))))),
(4, ''),
(0, ''))
you can use this form to both find the dependencies of the expression
and to interpret the expression. (btw I think the parser module doesn't
exist in jython)

Well, good luck with your project -- and don't spring any more
requirements on us, it's getting harder each time to solve your problem.

Jeff


Vojin Jovanovic

unread,
Jun 5, 2002, 10:51:59 AM6/5/02
to
> If you are going to always store the equation, never the value, what
> happens when the user does
> c.y = 37
> c.y = 'y+1'

that is very simple, look at my response to Tim Peters
and the method __setattr__

def __setattr__(self,arg,val):
self.__dict__['Equations'][arg]=str(val)

str(val) takes care of c.y=37

I suggets that you play with my Foo class to see how all that works.

> Then you're left with detecting stuff like
> c.x = "y"
> c.y = "x+1"

cycle staff can be taken care with a counter, I don't see a problem with
that.

> Well, good luck with your project -- and don't spring any more
> requirements on us, it's getting harder each time to solve your problem.

Sorry, but it is not that my problem is hard. It is that the concept of
having
to reference instance variables always through self. is making it hard and
inconvenient which was my point in my original post.
My opinion is that those points explained in FAQ are irrelevant. The only
one relevant is .....

"When classes were added to Python, this was (again) the simplest way of
implementing methods without too many changes to the interpreter. "

This sentence says it all, everything after that is said in FAQ is of less
importance and
it looks like "well, we did it in the simplest way, but, you know, this way
is really
better for you, let us show you how ..."
The consequence is that the simplest solution is not always the best one.

Vojin Jovanovic


Steve Holden

unread,
Jun 5, 2002, 11:47:26 AM6/5/02
to
"Vojin Jovanovic" <vjov...@stevens-tech.edu> wrote ...
[...]

>
> > Well, good luck with your project -- and don't spring any more
> > requirements on us, it's getting harder each time to solve your problem.
>
> Sorry, but it is not that my problem is hard. It is that the concept of
> having
> to reference instance variables always through self. is making it hard and
> inconvenient which was my point in my original post.
> My opinion is that those points explained in FAQ are irrelevant. The only
> one relevant is .....
>
[...]

Could you maybe use self.__dict__ as a namespace argument to the eval()?

if-tim-didn't-solve-this-i-don't-fancy-my-chances-ly y'rs - steve
--
-----------------------------------------------------------------------
Steve Holden http://www.holdenweb.com/
Python Web Programming http://pydish.holdenweb.com/pwp/
-----------------------------------------------------------------------

holger krekel

unread,
Jun 5, 2002, 11:48:14 AM6/5/02
to
Nicola Kluge wrote:
> This is an interesting idea. However, your approach doesn't handle the dot
> notation.
> For example,
> If object.x was = to 3 and g was = to 4 I need that
> e.f='object.x*g' gives 12.
> Just having e=Evaluator({'a':'3', 'b':'a*17', 'c':
> 'b*a','object.x':'3','g':'4'})
> doesn't work. While parsing, 'object.x' is not taken as one symbol in your
> approach.
> I need to have object capabilities in the equations.

i think i have to dig deeper into the python sources to see how
and if your task could be done cleanly. One of the main problems seems
to be that you can't pass your own 'dictish' object to 'eval' or 'exec'.
(Actually you can, but the interception points like '__getattr__'
don't get called. smells like a bug to me though this might be arguable).

And yes, i think that having an explicit 'self' is a very good pythonic idea (tm).
i know because i have done some pretty weird stuff like transfering 'locals()'
into the self-dict and back but it often isn't worse it.

have fun,

holger


holger krekel

unread,
Jun 5, 2002, 12:30:55 PM6/5/02
to
Steve Holden wrote:
> "Vojin Jovanovic" <vjov...@stevens-tech.edu> wrote ...
> [...]
> >
> > > Well, good luck with your project -- and don't spring any more
> > > requirements on us, it's getting harder each time to solve your problem.
> >
> > Sorry, but it is not that my problem is hard. It is that the concept of
> > having
> > to reference instance variables always through self. is making it hard and
> > inconvenient which was my point in my original post.
> > My opinion is that those points explained in FAQ are irrelevant. The only
> > one relevant is .....
> >
> [...]
>
> Could you maybe use self.__dict__ as a namespace argument to the eval()?

no his questions go deeper :-)

the problem is that the values in the dict have to be 'evaluated' if accessed.
For every name in such a value you need to evaluate its value again.
IOW it's recursive. The obvious solution is to intercept the namevalue-lookups
during evaluation of an equation. But this doesn't work for exec/eval:
They ignore the interception points.

IOW you cannot successfully wrap or inherit a dictionary type and pass it
to exec/eval :-(

The next best solution IMO is to preprend a namescope like 'self.'
to every name in an expression. But you may have to parse the expression to
do this. Maybe fixing exec/eval behaviour is a better idea?

regards,

holger


Vojin Jovanovic

unread,
Jun 5, 2002, 2:40:45 PM6/5/02
to
> no his questions go deeper :-)

I am glad that somebody here recognizes that.

> For every name in such a value you need to evaluate its value again.
> IOW it's recursive. The obvious solution is to intercept the
namevalue-lookups
> during evaluation of an equation. But this doesn't work for exec/eval:
> They ignore the interception points.

Correct.

Every evaluation has to go through __getattr__ method in order to access
the instance variables of the object, but that, unfortunately, can only be
done with self.
This is needed since the left hand sides of the equations must be the
variables of the instance
and not just some key values in a dictionary.

> The next best solution IMO is to preprend a namescope like 'self.'
> to every name in an expression.
> But you may have to parse the expression to
> do this.

I have been thinking about this for some time, and realized that there some
tricky cases that one has to deal with, and I am not sure that the whole
business of appending
self. will be error free in every case. For example in 'x + Geometry.x' the
correct result should
be 'self.x + self.Geometry.x' where Geometry is an instance of Geometry
class that is bound to
self.Geometry. So one has to distinguish between two names of x in two
different places. Maybe
stuff like this is not even so tricky. I don't know at this point, I
haven't looked at that too
closely yet to decide the feasibility of such an approach. I am still
trying to resolve
the problem in an easier way with whatever Python is offering to me.

> Maybe fixing exec/eval behaviour is a better idea?

Well, I don't know how to proceed in this regard. I am not familiar with the
source code.

It seems that the only two options are 1) work directly on the input string
or 2) parse the expression
and try to correctly append self. in front of the variables.

V. Jovanovic


David Bolen

unread,
Jun 5, 2002, 4:25:38 PM6/5/02
to
holger krekel <py...@devel.trillke.net> writes:

> the problem is that the values in the dict have to be 'evaluated' if
> accessed. For every name in such a value you need to evaluate its
> value again. IOW it's recursive. The obvious solution is to
> intercept the namevalue-lookups during evaluation of an
> equation. But this doesn't work for exec/eval: They ignore the
> interception points.

Right, so even if you use Python 2.2 and subclass dict, while you'll
get the first lookup properly the recursive lookups within the eval go
directly to the dictionary.

I think your earlier solution posted here, which was to start with an
empty dictionary for the eval, and then trap lookup errors and slowly
populate the dictionary by evaluating the needed symbol, looked the
most promising. It ends up doing a bunch of eval() calls, but using
the exception processing in lieu of needing the __getattr__ override
on the dictionary. I think it might still need some checking to
avoid infinite loops in cyclical references though.

> IOW you cannot successfully wrap or inherit a dictionary type and pass it
> to exec/eval :-(

Yes, I did also find a posting by Guido (didn't save the reference,
but it was via a google search) where he seemed to indicate that
subclassing list/dict other than add additional functionality (rather
than override core operations like lookups) could be problematic -
presumably because of cases like this where the special Python-exposed
functions are used. The message was during one of the later betas of
2.2, so I don't know if the viewpoint changed before final release.

--
-- David
--
/-----------------------------------------------------------------------\
\ David Bolen \ E-mail: db...@fitlinxx.com /
| FitLinxx, Inc. \ Phone: (203) 708-5192 |
/ 860 Canal Street, Stamford, CT 06902 \ Fax: (203) 316-5150 \
\-----------------------------------------------------------------------/

Fernando Pérez

unread,
Jun 5, 2002, 10:28:41 AM6/5/02
to
Vojin Jovanovic wrote:

>> For every name in such a value you need to evaluate its value again.
>> IOW it's recursive. The obvious solution is to intercept the
> namevalue-lookups
>> during evaluation of an equation. But this doesn't work for exec/eval:
>> They ignore the interception points.
>
> Correct.
>
> Every evaluation has to go through __getattr__ method in order to access
> the instance variables of the object, but that, unfortunately, can only be
> done with self.
> This is needed since the left hand sides of the equations must be the
> variables of the instance
> and not just some key values in a dictionary.

You seem to be trying to set up a system whose evaluation rules are very
similar to those in Mathematica. I've long toyed with this idea myself, as an
addition I'd love to make to IPython. What I've had in mind is allowing a
new definition symbol in the IPython prompt ':=' which like in Mathematica
represents 'delayed evaluation'. This part would be trivial, as the hooks for
special syntax processing are already in place (an example for physical
quantities with units is provided and one for pasting code from python
prompts). You'd then have something like (imagine this is at an interactive
prompt):

y=5 # normal variable
x:=y+1 # x is a delayed evaluation variable, stored in a special class
x # prints 6 on screen
y=9
x #prints 10 on screen

So ':=' variables would first try to evaluate their expressions in their
normal namespace (that of the class, the problem you're dealing with now) and
would then look for 'normal' variable names to resolve. Only if a name
wasnt't found in either would a NameError be raised.

Unfortunately I don't have the time right now to work on this (and won't for a
while). But if you want to add the syntax processor and the special class
using IPython (which gives you finer control over the namespaces wherer
things are evaluated than you get with the normal interpreter) I'll be glad
to include it in future releases.

Cheers,

f.

ps. IPython is at http://www-hep.colorado.edu/~fperez/ipython/

holger krekel

unread,
Jun 5, 2002, 7:59:18 PM6/5/02
to
[me]

IOW you cannot successfully wrap or inherit a dictionary type and pass it
to exec/eval :-(

[David Bolen]

Yes, I did also find a posting by Guido (didn't save the reference,
but it was via a google search) where he seemed to indicate that
subclassing list/dict other than add additional functionality (rather
than override core operations like lookups) could be problematic -
presumably because of cases like this where the special Python-exposed
functions are used. The message was during one of the later betas of
2.2, so I don't know if the viewpoint changed before final release.

everything is a google-search away if you know the right codewords :-)
I don't in this case, though ...

anyway, if you call dictionary methods from python you can intercept.
But either generally c-level code ignores python-overriden methods
or only eval/exec "optimizes" them out. I presume that this is for
speed reasons but there may lurk conceptual reasons as well. Who knows?

holger


David Bolen

unread,
Jun 5, 2002, 8:19:05 PM6/5/02
to
> everything is a google-search away if you know the right codewords :-)
> I don't in this case, though ...

Sorry, I must admit to being temporarily overcome with a fit of laziness. I
had actually fumbled around a bit before finding the posts I mentioned, so I
should really have tried to include a reference.

Lest the codewords remain secret, I managed to wind my way there with a
search on "eval dictionary instance" in comp.lang.python (which referenced a
post of Tim's on the fourth page of results).

The messages I had found occurred deep into a "Dictionary from list?" thread
from last October which crossed over into the subject of subclassing
dictionaries:

http://groups.google.com/groups?th=2338421ec8397bec&seekm=mailman.1004338951
.27778.python-list%40python.org

is a pointer to the relevant portion including a response by both Tim and
Guido.

-- David

holger krekel

unread,
Jun 5, 2002, 8:41:12 PM6/5/02
to
David Bolen wrote:
> [me]

> > everything is a google-search away if you know the right codewords :-)
> > I don't in this case, though ...
>
> Sorry, I must admit to being temporarily overcome with a fit of laziness. I
> had actually fumbled around a bit before finding the posts I mentioned, so I
> should really have tried to include a reference.
>
> Lest the codewords remain secret, I managed to wind my way there with a
> search on "eval dictionary instance" in comp.lang.python (which referenced a
> post of Tim's on the fourth page of results).
>
> The messages I had found occurred deep into a "Dictionary from list?" thread
> from last October which crossed over into the subject of subclassing
> dictionaries:
>
> http://groups.google.com/groups?th=2338421ec8397bec&seekm=mailman.1004338951
> .27778.python-list%40python.org

very nice, thanks!

[GvR in the above link]
IMO, fixing these internal accesses to always use the overrides would
remove much of the attractiveness of subclassing built-in types; I
believe it would slow things down too much given the current state of
the implementation.

If you want a vaguely dictionary-like object, write a class that
doesn't derive from dictionary but implements the mapping protocol; if
you want a base class that implements most of the operations already,
start with UserDict.

This seems reasonable except that 'exec' and 'eval' require a real dict-type.
Due to the generic nature of these execution statements i guess that
fixing it is roughly equivalent to fixing it all over the place unless
they could be somehow special-cased. Oh well...

holger


holger krekel

unread,
Jun 5, 2002, 8:28:15 PM6/5/02
to
Vojin Jovanovic wrote:
> [me]

> > The next best solution IMO is to preprend a namescope like 'self.'
> > to every name in an expression.
> > But you may have to parse the expression to
> > do this.
>
> I have been thinking about this for some time, and realized that there some
> tricky cases that one has to deal with, and I am not sure that the whole
> business of appending self. will be error free in every case.
> For example in 'x + Geometry.x' the correct result should
> be 'self.x + self.Geometry.x' where Geometry is an instance of Geometry
> class that is bound to self.Geometry.

with a small modification to my previously posted class you *can* do this:

class Evaluator:
def __init__(self, eqs={}):
self.__dict__['equations']=eqs
def __getattr__(self, name):

value = self.equations[name]
if type(value)!=str:
return value # if it's not a string, just give it back
scope={}
while 1:
try:
return eval(value, scope)
except Namerror, n:
var=str(n).split("'")[1]
scope[var]=getattr(self, var)


def __setattr__(self, name, value):
self.equations[name]=value

class Berta:
a=5

>>> e=Evaluator({'a':'3'])
>>> e.berta=Berta()
>>> e.g='berta.a*a'
>>> e.g
15

This is hopefully what you want. This version doesn't detect
cycles in equation definitions, though. Shouldn't be too difficult
to add but requires some more thought. ask again if you
are having problems with it.

have fun,

holger


Delaney, Timothy

unread,
Jun 5, 2002, 8:03:45 PM6/5/02
to
> From: Vojin Jovanovic [mailto:vjov...@stevens-tech.edu]
>
> Sorry, but it is not that my problem is hard. It is that the
> concept of
> having
> to reference instance variables always through self. is
> making it hard and
> inconvenient which was my point in my original post.

Actually, I think it's more that the problem is not specified correctly.

How would you do this in C? You haven't got any member variables there to do
it with.

How would you do it in C++? You can't execute arbitrary code.

How would you do it in Java? You can't execute arbitrary code.

You are trying to take advantage of a feature in Python (extreme dynamism)
and are then bemoaning that it doesn't work exactly as you would like?

What has happened is that you are no longer concentrating on the problem,
but on how to work around Python to make it work the way you think it should
work for this one problem domain.

The standard way of dealing with this is to create a parse tree for the
expressions and evaluate them, storing the actual values separately.

I think that in this case, the standard method is also the correct one.

Tim Delaney


Vojin Jovanovic

unread,
Jun 6, 2002, 10:34:09 AM6/6/02
to
I don't think you tested your code, because I can't get the output you
specified. In fact it seems that you broke your own code.

Vin


Vojin Jovanovic

unread,
Jun 6, 2002, 10:40:39 AM6/6/02
to
> So ':=' variables would first try to evaluate their expressions in their
> normal namespace (that of the class, the problem you're dealing with now)
and
> would then look for 'normal' variable names to resolve. Only if a name
> wasnt't found in either would a NameError be raised.

Your idea is good. It would be exactly what I need. It would bring a lot
to python; a kind of symbolic manipulation capability. Unfortunately, I
don't think that my current knowledge of Python is sufficient to implement
this in a general way you are suggesting.

V.J.


Fernando Pérez

unread,
Jun 6, 2002, 5:00:19 AM6/6/02
to
Vojin Jovanovic wrote:

Well, I've given it a bit of thought on the side but unfortunately right now
I'm swamped with other things. I'll put it in the idea-bucket for IPython,
hopefully later I'll have a chance to look at it. By the way, the ':=' part
is absolutely trivial to implement for me, the tricky side is the problem
you've been struggling with. So if you ever can build a class which evaluates
the way you've been trying, I could easily incorporate it into the ipython
framework with a special syntax pre-processor (I already have that
infrastructure in place).

But the problem is not trivial, esp. if you want to be able to mix and match
'normal' python variables with these 'delayed evaluation' ones. Good luck :)

f

Kragen Sitaker

unread,
Jun 6, 2002, 2:15:55 PM6/6/02
to
"Sean 'Shaleh' Perry" <shale...@attbi.com> writes:
> it sees 'a*c' and asks it own dict 'do we know a?' if so it access dict['a']
> and returns its value. Looking at your example you seem to be implementing a
> symbolic calculator. Most implementations I have seen involve writing a small
> language with interpreter.

It's a shame that this is necessary, since we already have a perfectly
good language with an interpreter already present.

holger krekel

unread,
Jun 6, 2002, 8:30:10 PM6/6/02
to
Vojin Jovanovic wrote:
> I don't think you tested your code, because I can't get the output you
> specified. In fact it seems that you broke your own code.

of course i tested it! Do you really think i am making up
results which can be proven wrong in ten seconds? Why such a
harsh reaction without bothering to correct the obvious 'typo'?
I don't actually know what went wrong while pasting the
code ('Namerror' instead of 'NameError').

Anyway, here is the paste-typo-corrected version:

class Evaluator:
def __init__(self, eqs={}):
self.__dict__['equations']=eqs
def __getattr__(self, name):
value = self.equations[name]
if type(value)!=str:
return value # if it's not a string, just give it back
scope={}
while 1:
try:
return eval(value, scope)

except NameError, n:


var=str(n).split("'")[1]
scope[var]=getattr(self, var)
def __setattr__(self, name, value):
self.equations[name]=value

class Berta:
a=5

>>> e=Evaluator({'a':3})
>>> e.berta=Berta()
>>> e.g='berta.a*a'
>>> e.g
15

regards,

holger


Vojin Jovanovic

unread,
Jun 7, 2002, 10:51:17 AM6/7/02
to
> Why such a
> harsh reaction without bothering to correct the obvious 'typo'?

No, it is not the 'typo'. I corrected that immediately.
Also you had in your message >>> e=Evaluator({'a':'3']), a wrong bracket.
Go back to your post and check it out. That is why I thought that you
didn't test it.
However, all that aside, the problems is that your code just din't work
after I corrected those 2 'typos'. Take a look yourself ....

Python 2.1.2 (#31, Jan 15 2002, 17:28:11) [MSC 32 bit (Intel)] on win32
Type "copyright", "credits" or "license" for more information.
IDLE 0.8 -- press F1 for help


>>> class Evaluator:
def __init__(self, eqs={}):
self.__dict__['equations']=eqs
def __getattr__(self, name):
value = self.equations[name]
if type(value)!=str:
return value # if it's not a string, just give it back
scope={}
while 1:
try:
return eval(value, scope)
except NameError, n:
var=str(n).split("'")[1]
scope[var]=getattr(self, var)
def __setattr__(self, name, value):
self.equations[name]=value


>>> class Berta:
a=5


>>> e=Evaluator({'a':3})
>>> e.berta=Berta()
>>> e.g='berta.a*a'
>>> e.g

'berta.a*a'
>>>


V.J.


Eric Texier

unread,
Jun 7, 2002, 11:08:44 AM6/7/02
to
It works for me with 2.2 but not with 1.5.2 both on Linux

holger krekel

unread,
Jun 7, 2002, 11:33:55 AM6/7/02
to
Vojin Jovanovic wrote:
> > Why such a
> > harsh reaction without bothering to correct the obvious 'typo'?
>
> No, it is not the 'typo'. I corrected that immediately.

ok. sorry for wrong accusations...

> However, all that aside, the problems is that your code just din't work
> after I corrected those 2 'typos'. Take a look yourself ....
>
> Python 2.1.2 (#31, Jan 15 2002, 17:28:11) [MSC 32 bit (Intel)] on win32

hmmm. it seems to be a problem with the python version: 'type(value)!=str'
comparison doesn't seem to work with python2.1 (works with 2.2).
So here goes my python2.1/2.2 version:

Python 2.1.3 (#1, Apr 20 2002, 10:14:34)
[GCC 2.95.4 20011002 (Debian prerelease)] on linux2


Type "copyright", "credits" or "license" for more information.

Welcome to Lazy Python. Type "help LazyPython" for help.


>>> class Evaluator:
def __init__(self, eqs={}):
self.__dict__['equations']=eqs
def __getattr__(self, name):
value = self.equations[name]

if type(value)!=type(''):
return value


scope={}
while 1:
try:
return eval(value, scope)
except NameError, n:
var=str(n).split("'")[1]
scope[var]=getattr(self, var)
def __setattr__(self, name, value):
self.equations[name]=value

>>> class Berta:
a=5

>>> e=Evaluator({'a':3})
>>> e.berta=Berta()
>>> e.g='berta.a*a'
>>> e.g

15
>>>

now i hope we are getting close to discussing the idea, finally :-)

regards,

holger


Vojin Jovanovic

unread,
Jun 10, 2002, 12:49:40 PM6/10/02
to
Yep, this time you did it. You practically implemented a delayed evaluator
in Python. I added the stuff to my own code and added some other things
like access to global variables etc. Everything works fine. I have to
admit that it is a clever trick to collect the names from an expression by
evaluating the expression in an empty dictionary. Exactly what one needs to
get rid of self. Now as Fernando Perez suggested this can be used to add
':=' to the language, but I am not familiar with that stuff.

Thank you for your help and for not giving up on the problem

V.J.


0 new messages