finding name of instances created

J

Jeremy Bowers

etc. Since I want the user to learn Python's syntax, I don't want to
require him/her to write
alex = CreateRobot(name = 'alex')
to then be able to do
alex.move()

This is just my opinion, but I've been involved with teaching new
programmers before so I think it is an informed one. I don't think you
teach a language by hiding how the language works, no matter what the
intentions.

You should be *minimizing* the magic. You're going to train your students
that Python objects have names (they don't) and that's going to mess them
up later. Actually, it's going to mess them up almost right away, because
how can they have a list of robots like this:

for robot in robots:
robot.turn_left()

That can't work, right, the command inside the loop can only affect the
robot named "robot", right?

You can't teach Python if what you're actually teaching them is a variant
that you have created that is used nowhere else on Earth, and is
internally inconsistent to boot (see loop above, the *real* Python
variable semantics conflict with the semantics you are teaching).

Considering that not a month goes by where someone doesn't post a question
related to this, and it has been a FAQ entry for as long as I've used
Python, I think you are doing a major disservice to your "users" by
training them that objects magically gets the name when assigned. I
strongly urge you to do absolutely no pre-processing of any kind to the
programs they generate. (By which I mean changes to the code; running
pychecker on it would be OK; and I'd urge you to resist the temptation to
process its output, either. Provide a "translation table" if you need to,
but they need to learn to read the real output, too.)

Programming is hard enough with burdening people with "pleasant
falsehoods". Trust your students to handle the truth (and of course
rationally minimize the truth they have to handle, and by using Python
you're off to a great start there). If they can't handle the truth, with
time, effort, and support, they *sure* as hell can't handle lies!
 
?

=?iso-8859-1?B?QW5kcuk=?=

Short version of what I am looking for:

Given a class "public_class" which is instantiated a few times e.g.

a = public_class()
b = public_class()
c = public_class()

I would like to find out the name of the instances so that I could
create a list of them e.g.
['a', 'b', 'c']

I've read the Python Cookbook, Python in a Nutshell, Programming
Python, Learning Python, ... googled (probably missed something
obvious), all to no avail.

=====
Longer version:

If I can do the above, I believe I could do the following thing which
is what I am really after eventually.

Given the statement

I would like to generate
my_dict['a'] = private_class()

so that one could write

and that, behind the scene, I could translate that as
my_dict['a'].not_so_simple_method()

as well as do things like

Any help, pointers, sketches or outline of solution would be greatly
appreciated.

André
 
C

Craig Ringer

Short version of what I am looking for:

Given a class "public_class" which is instantiated a few times e.g.

a = public_class()
b = public_class()
c = public_class()

I would like to find out the name of the instances so that I could
create a list of them e.g.
['a', 'b', 'c']

I've read the Python Cookbook, Python in a Nutshell, Programming
Python, Learning Python, ... googled (probably missed something
obvious), all to no avail.

Yep. The short answer is that the instances don't have names - they're
just bound to names in a particular scope. They can be bound to
different names in the same scope or in other scopes.

You can get a dictionary for a particular scope using locals() then
search it to find the key for a given value. That key will be the name
the object is bound to in that scope.

In general, you won't want to do that - the need to do so probably
suggests a design issue in what you're trying to do.
If I can do the above, I believe I could do the following thing which
is what I am really after eventually.

Given the statement

I would like to generate
my_dict['a'] = private_class()

so that one could write

and that, behind the scene, I could translate that as
my_dict['a'].not_so_simple_method()

I'm not clear as to why you can't do this as part of the class of which
'a' is an instance.
as well as do things like


Any help, pointers, sketches or outline of solution would be greatly
appreciated.

I'm not really able to grasp what you're trying to do (but others
might). It wouldn't hurt if you could post a description of what you're
actually trying to achieve - /why/ you want this - as that can often be
very helpful both in understanding what you're thinking and in
suggesting a suitable approach or alternative.
 
S

Steven Bethard

André said:
Given the statement

I would like to generate
my_dict['a'] = private_class()

so that one could write

and that, behind the scene, I could translate that as
my_dict['a'].not_so_simple_method()

as well as do things like

Why can't you just make public_class a factory, alias the method in
PrivateClass and access the names through locals()?

py> class PrivateClass(object):
.... def not_so_simple_method(self):
.... print "not so simple"
.... apparently_simple_method = not_so_simple_method
....
py> def public_class():
.... return PrivateClass()
....
py> a = public_class()
py> a.apparently_simple_method()
not so simple
py> # add 'name' and 'value' to locals() before iteration starts
py> name, value = None, None
py> for name, value in locals().iteritems():
.... if isinstance(value, PrivateClass):
.... print name, value
....
a <__main__.PrivateClass object at 0x01146D50>

Steve
 
G

Guest

Craig said:
Short version of what I am looking for:

Given a class "public_class" which is instantiated a few times e.g.

a = public_class()
b = public_class()
c = public_class()

I would like to find out the name of the instances so that I could
create a list of them e.g.
['a', 'b', 'c']
[snip]


I'm not really able to grasp what you're trying to do (but others
might). It wouldn't hurt if you could post a description of what you're
actually trying to achieve - /why/ you want this - as that can often be
very helpful both in understanding what you're thinking and in
suggesting a suitable approach or alternative.

Ok, here it goes... I am designing a "learning environment" for Python.
(See rur-ple.sourceforge.org for details of a *very early, still buggy*
relase). I have a "world" in which a
"robot" can accomplish four built-in instructions: move(), turn_left(),
pick_beeper(), put_beeper().
turn_left() corresponds to a 90 degree left turn. One can define a
function to simulate a 90 degree right turn as follows:

def turn_right():
turn_left()
turn_left()
turn_left()

and call it as a built-in instruction thereafter.

By giving more and more complicated tasks for the robot to accomplish,
one can learn various programming concepts using python syntax:
def (as above), while, if, else, elif, ......

I have all of that working well so far (not on sourceforge yet).
Next, I want to introduce
the concept of classes and objects, again using python's syntax.

Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to
robot_dict['robot'].move()
(which does lots of stuff behind the scene.)

I have tested robot_dict[] with more than one robot (each with
its own unique name) and am now at the point where I would like
to have the ability to interpret something like:

alex = CreateRobot()
anna = CreateRobot()

alex.move()
anna.move()

etc. Since I want the user to learn Python's syntax, I don't
want to require him/her to write
alex = CreateRobot(name = 'alex')
to then be able to do
alex.move()

I have tried various things at the interpreter, found that
to a class 'a', I could see the instance 'b' created in
locals():
'a': <class '__main__.a'>, 'b': <__main__.a object at 0x011515D0>
which tells me that there must be a way to catch b's name as it is
created, and do what I want to do.

Does this clarify what I am trying to do and why?

André
 
?

=?iso-8859-1?B?QW5kcuk=?=

Using the method suggested by Steven Bethard, I *almost* got it working
the way I would like.
Here's my program:
===
..class PrivateClass(object):
.. dict = {}
.. def not_so_simple_method(self):
.. for name in PrivateClass.dict.keys():
.. if PrivateClass.dict[name] == self:
.. print "instance " + name + " called not so simple"
.. apparently_simple_method = not_so_simple_method

.. def __init__(self):
.. print "instance created"
.. for name, value in globals().iteritems():
.. if isinstance(value, PrivateClass):
.. PrivateClass.dict[name] = value

..def public_class():
.. return PrivateClass()

..print "=== start==="
..alpha = public_class()
..print "created alpha"
..print PrivateClass.dict
..print "### alpha is not there\n"

..beta = public_class()
..print "created beta"
..print PrivateClass.dict
..print "### we are always one behind in the dict content\n"

..alpha.apparently_simple_method()
..beta.apparently_simple_method()
=================================
The output follows:
=== start===
instance created
created alpha
{}
### alpha is not there

instance created
created beta
{'alpha': <__main__.PrivateClass object at 0x0117CDD0>}
### we are always one behind in the dict content

instance alpha called not so simple
=======
Note that instance beta was never recognized when it called "apparently
simple method".

I'm sure there must be a way to do this....

André
 
S

Steven Bethard

André said:
Using the method suggested by Steven Bethard, I *almost* got it working
the way I would like.
Here's my program:
===
.class PrivateClass(object):
. dict = {}
. def not_so_simple_method(self):
. for name in PrivateClass.dict.keys():
. if PrivateClass.dict[name] == self:
. print "instance " + name + " called not so simple"
. apparently_simple_method = not_so_simple_method

. def __init__(self):
. print "instance created"
. for name, value in globals().iteritems():
. if isinstance(value, PrivateClass):
. PrivateClass.dict[name] = value

.def public_class():
. return PrivateClass()

.print "=== start==="
.alpha = public_class()
.print "created alpha"
.print PrivateClass.dict
.print "### alpha is not there\n"

.beta = public_class()
.print "created beta"
.print PrivateClass.dict
.print "### we are always one behind in the dict content\n"

.alpha.apparently_simple_method()
.beta.apparently_simple_method()

It looks like you want PrivateClass.dict updated every time that
globals() is updated. You can just use globals directly instead:

py> class PrivateClass(object):
.... def __init__(self, globals):
.... self.globals = globals
.... def apparently_simple_method(self):
.... for name, value in self.globals.iteritems():
.... if value is self:
.... print "instance %s called not so simple" % name
....
py> def public_class():
.... return PrivateClass(globals())
....
py> alpha = public_class()
py> alpha.apparently_simple_method()
instance alpha called not so simple
py> beta = public_class()
py> beta.apparently_simple_method()
instance beta called not so simple

On the other hand, the iteration in
PrivateClass.apparently_simple_method has a very bad code smell...

Steve
 
?

=?iso-8859-1?B?QW5kcuk=?=

Steven said:
André said:
Using the method suggested by Steven Bethard, I *almost* got it working
the way I would like.
[snip]

It looks like you want PrivateClass.dict updated every time that
globals() is updated.

yes, that is what I would like to do.
You can just use globals directly instead:

py> class PrivateClass(object):
... def __init__(self, globals):
... self.globals = globals
... def apparently_simple_method(self):
... for name, value in self.globals.iteritems():
... if value is self:
... print "instance %s called not so simple" % name
...
py> def public_class():
... return PrivateClass(globals())
...
py> alpha = public_class()
py> alpha.apparently_simple_method()
instance alpha called not so simple
py> beta = public_class()
py> beta.apparently_simple_method()
instance beta called not so simple
That's exactly what I was looking for; thank you!
On the other hand, the iteration in
PrivateClass.apparently_simple_method has a very bad code smell...
I'm not sure what you mean...
Is it because it makes use of information that is
exterior to the class, which is not passed as a parameter
to the method?
[feel free to ignore this question if you want; you have
already helped me tremendously!!!]

André
 
S

Steven Bethard

André Roberge said:
Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to
robot_dict['robot'].move()
(which does lots of stuff behind the scene.)

I have tested robot_dict[] with more than one robot (each with
its own unique name) and am now at the point where I would like
to have the ability to interpret something like:

alex = CreateRobot()
anna = CreateRobot()

alex.move()
anna.move()

etc. Since I want the user to learn Python's syntax, I don't
want to require him/her to write
alex = CreateRobot(name = 'alex')
to then be able to do
alex.move()

How do you get the commands from the user? Maybe you can preprocess the
user code?

py> class Robot(object):
.... def __init__(self, name):
.... self.name = name
.... def move(self):
.... print "robot %r moved" % self.name
....
py> user_code = """\
.... alex = Robot()
.... anna = Robot()
.... alex.move()
.... anna.move()"""
py> new_user_code = re.sub(r'(\w+)\s+=\s+Robot\(\)',
.... r'\1 = Robot(name="\1")',
.... user_code)
py> print new_user_code
alex = Robot(name="alex")
anna = Robot(name="anna")
alex.move()
anna.move()
py> exec new_user_code
robot 'alex' moved
robot 'anna' moved

Steve
 
S

Steven Bethard

André said:
Steven said:
André said:
Using the method suggested by Steven Bethard, I *almost* got it
working
the way I would like.
[snip]

It looks like you want PrivateClass.dict updated every time that
globals() is updated.


yes, that is what I would like to do.

You can just use globals directly instead:

py> class PrivateClass(object):
... def __init__(self, globals):
... self.globals = globals
... def apparently_simple_method(self):
... for name, value in self.globals.iteritems():
... if value is self:
... print "instance %s called not so simple" % name
...
py> def public_class():
... return PrivateClass(globals())
...
py> alpha = public_class()
py> alpha.apparently_simple_method()
instance alpha called not so simple
py> beta = public_class()
py> beta.apparently_simple_method()
instance beta called not so simple

That's exactly what I was looking for; thank you!

On the other hand, the iteration in
PrivateClass.apparently_simple_method has a very bad code smell...

I'm not sure what you mean...
Is it because it makes use of information that is
exterior to the class, which is not passed as a parameter
to the method?
[feel free to ignore this question if you want; you have
already helped me tremendously!!!]

There's a couple things I don't like about it:

(1) Generally, I don't like passing globals() around. It's probably
okay in this scenario though because if you want to have the user code
in a different module, you can do something like:
def public_class():
return PrivateClass(usermodule.__dict__)

(2) The really bad code smell however is having to iterate through all
the values in globals to find the key you're looking for... Especially
when you have to check the type of each item... In a perfect world, you
would already have a PrivateClass->name mapping somewhere and this
should be a simple dict lookup instead of an iterative search... See my
other post about potentially pre-processing your user input to see how
you can convert the iteration to a simple attribute lookup.

Steve
 
?

=?iso-8859-1?B?QW5kcuk=?=

Steven said:
André Roberge said:
Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to
robot_dict['robot'].move()
(which does lots of stuff behind the scene.)

I have tested robot_dict[] with more than one robot (each with
its own unique name) and am now at the point where I would like
to have the ability to interpret something like:

alex = CreateRobot()
anna = CreateRobot()

alex.move()
anna.move()

etc. Since I want the user to learn Python's syntax, I don't
want to require him/her to write
alex = CreateRobot(name = 'alex')
to then be able to do
alex.move()

How do you get the commands from the user? Maybe you can preprocess the
user code?

py> class Robot(object):
... def __init__(self, name):
... self.name = name
... def move(self):
... print "robot %r moved" % self.name
...
py> user_code = """\
... alex = Robot()
... anna = Robot()
... alex.move()
... anna.move()"""
py> new_user_code = re.sub(r'(\w+)\s+=\s+Robot\(\)',
... r'\1 = Robot(name="\1")',
... user_code)
py> print new_user_code
alex = Robot(name="alex")
anna = Robot(name="anna")
alex.move()
anna.move()
py> exec new_user_code
robot 'alex' moved
robot 'anna' moved

Smack! (sound of hand slapping forehead).
Of course! This is *much* better.
(In all honesty, I have trouble reading regular expression
notation but I can decode it enough to understand that I can
do this - and I already asked a question today on the list
about regular expressions, so I have not excuse for not having
thought of an approach like this.)

I will be already 'processing' the code to make sure that
statements/words like: import, exec, eval, input, raw_input, vars,
chr, .... are not allowed in the user-defined instructions.
This will be just a simple addition.

Once again, thank you! Both for this, and for the other example which
taught me something about the use of locals(), globals(), and functions
that return classes. There are so many corners of Python to explore
:)
 
S

Steven Bethard

André Roberge said:
Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to
robot_dict['robot'].move()
(which does lots of stuff behind the scene.)

I have tested robot_dict[] with more than one robot (each with
its own unique name) and am now at the point where I would like
to have the ability to interpret something like:

alex = CreateRobot()
anna = CreateRobot()

alex.move()
anna.move()

etc. Since I want the user to learn Python's syntax, I don't
want to require him/her to write
alex = CreateRobot(name = 'alex')
to then be able to do
alex.move()

If you have access to the user module's text, something like this might
be a nicer solution:

py> class Robot(object):
.... def __init__(self):
.... self.name = None
.... def move(self):
.... print "robot %r moved" % self.name
....
py> class RobotDict(dict):
.... def __setitem__(self, name, value):
.... if isinstance(value, Robot):
.... value.name = name
.... super(RobotDict, self).__setitem__(name, value)
....
py> user_code = """\
.... alex = Robot()
.... anna = Robot()
.... alex.move()
.... anna.move()"""
py> robot_dict = RobotDict()
py> robot_dict['Robot'] = Robot
py> exec user_code in robot_dict
robot 'alex' moved
robot 'anna' moved

Note that I provide a specialized dict in which to exec the user code --
this allows me to override __setitem__ to add the appropriate attribute
to the Robot as necessary.

Steve
 
A

Alex Martelli

André Roberge said:
alex = CreateRobot()
anna = CreateRobot()

alex.move()
anna.move()

Hmmmm -- while I've long since been identified as a 'bot, I can assure
you that my wife Anna isn't!


Alex
 
?

=?iso-8859-1?B?QW5kcuk=?=

Jeremy said:
This is just my opinion, but I've been involved with teaching new
programmers before so I think it is an informed one. I don't think you
teach a language by hiding how the language works, no matter what the
intentions.

You should be *minimizing* the magic. You're going to train your students
that Python objects have names (they don't) and that's going to mess them
up later. Actually, it's going to mess them up almost right away, because
how can they have a list of robots like this:

for robot in robots:
robot.turn_left()

They will not be able to do that.
That can't work, right, the command inside the loop can only affect the
robot named "robot", right?

You can't teach Python if what you're actually teaching them is a variant
that you have created that is used nowhere else on Earth, and is
internally inconsistent to boot (see loop above, the *real* Python
variable semantics conflict with the semantics you are teaching).

I think you misunderstood my intentions, possibly because I explain
things too superficially.
Considering that not a month goes by where someone doesn't post a question
related to this, and it has been a FAQ entry for as long as I've used
Python, I think you are doing a major disservice to your "users" by
training them that objects magically gets the name when assigned. I
strongly urge you to do absolutely no pre-processing of any kind to the
programs they generate. (By which I mean changes to the code; running
pychecker on it would be OK; and I'd urge you to resist the temptation to
process its output, either. Provide a "translation table" if you need to,
but they need to learn to read the real output, too.)

Programming is hard enough with burdening people with "pleasant
falsehoods". Trust your students to handle the truth (and of course
rationally minimize the truth they have to handle, and by using Python
you're off to a great start there). If they can't handle the truth, with
time, effort, and support, they *sure* as hell can't handle lies!

The environment in which students (my kids first, others later :) will
learn is based on Richard Pattis's "Karel the Robot" (adapted for
Python in "Guido van Robot"). They are presented with a robot that can
do four basic actions, as I described in a previous post. It's been
used successfully in many places.

The students learn first the procedural aspect of python. Here's a
quick example of a program that they can write:

..def move_and_turn():
.. move()
.. turn_left()
..
..def draw_square():
.. for i in range(4):
.. move_and_turn()
..
..draw_square()
======
At this point, they don't know anything about objects and methods; but
they will have learned about functions and variables. This is where
'Guido van Robot (GvR)', which has been used succesfully to teach
programming using a syntax somewhat similar to python, but not quite,
stops. (Actually, you can't use variables in GvR).

I want to move beyond that and introduce objects and classes.

So, students will be able to write:
pete = CreateRobot(2, 3)
pete.move()

learning about objects and methods.

As for things like
for robot in robots:
do stuff

that will be for my use only: drawing robots on the screen, updating
the 'world' when robots pick stuff up, etc. My intention is that the
students will use the EXACT python syntax, so that they don't know that
*I* have given a *name* to their robot(s) behind the scene.
I have to cut this short; I hope it clarifies my intentions.

André
 
S

Scott David Daniels

André Roberge said:
Craig said:
Short version of what I am looking for:

Given a class "public_class" which is instantiated a few times e.g.

a = public_class()
b = public_class()
c = public_class()

I would like to find out the name of the instances so that I could
create a list of them e.g.
['a', 'b', 'c']

...
Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to robot_dict['robot'].move()
(which does lots of stuff behind the scene.)
...[good explanation]...
> Does this clarify what I am trying to do and why?

Yup. Would something like this help?

parts = globals().copy()
parts.update(locals())
names = [name for name, value in parts.iteritems()
if isinstance(value, Robot)] # actual class name here

Note, however, that

a = b = CreateRobot()

will give two different names to the same robot.

And even:

Karl = CreateRobot()
Freidrich = CreateRobot()
for robot in (Karl, Freidrich):
robot.move()

Will have two names for "Freidrich" -- Freidrich and robot


--Scott David Daniels
(e-mail address removed)
 
?

=?iso-8859-1?B?QW5kcuk=?=

Steven said:
If you have access to the user module's text, something like this might
be a nicer solution:

py> class Robot(object):
... def __init__(self):
... self.name = None
... def move(self):
... print "robot %r moved" % self.name
...
py> class RobotDict(dict):
... def __setitem__(self, name, value):
... if isinstance(value, Robot):
... value.name = name
... super(RobotDict, self).__setitem__(name, value)
...
py> user_code = """\
... alex = Robot()
... anna = Robot()
... alex.move()
... anna.move()"""
py> robot_dict = RobotDict()
py> robot_dict['Robot'] = Robot
py> exec user_code in robot_dict
robot 'alex' moved
robot 'anna' moved

Note that I provide a specialized dict in which to exec the user code --
this allows me to override __setitem__ to add the appropriate attribute
to the Robot as necessary.

I have tried this exact example (using Python 2.3 if it makes any
difference) and what I got was:
robot None moved
robot None moved

I checked what I wrote, used cut & paste on your code, removing the
leading "junk", tried it again ... to no avail. :-(

André
 
N

Nick Coghlan

André said:
I have tried this exact example (using Python 2.3 if it makes any
difference) and what I got was:
robot None moved
robot None moved

I checked what I wrote, used cut & paste on your code, removing the
leading "junk", tried it again ... to no avail. :-(

Worked exactly as written for me, but I believe there were Python 2.4 changes
relating to using exec with non-standard dictionaries.

Regards,
Nick.
 
N

Nick Coghlan

André said:
So, students will be able to write:
pete = CreateRobot(2, 3)
pete.move()

learning about objects and methods.

As for things like
for robot in robots:
do stuff

that will be for my use only: drawing robots on the screen, updating
the 'world' when robots pick stuff up, etc. My intention is that the
students will use the EXACT python syntax, so that they don't know that
*I* have given a *name* to their robot(s) behind the scene.
I have to cut this short; I hope it clarifies my intentions.

My (and, if I understand him correctly, Jeremy's) concern would be that error
messages like "Robot 'pete' has hit a wall!" would give students the impression
that the robots automatically know their name as a result of the assignment. In
standard Python, that simply isn't true.

If, instead, CreateRobot looked something like:

def CreateRobot(street, avenue, name=None):
if name is None:
name = "Robot" + Robot.getNextNumber()
return Robot(street, avenue, name)


Then, using a simple assignment:

pete = CreateRobot(2, 3)
pete.move()

Would give an error like:

"Robot1 has hit a wall"

This could then be used to point out that objects named using assignment don't
know about the names they have been given, and need to be told:

pete = CreateRobot(2, 3, "Pete")
pete.move()

"Pete has hit a wall"

Instead of misleading the students ("objects know what names they have been
given"), you have taught them a powerful truth - objects and the names you give
them via assignment are entirely independent.

It also directly addresses the question of aliasing. Think about how Steven's
modified dictionary would react to this code:

pete = CreateRobot(2, 3)
dad = pete
dad.move()
pete.move()

Internally, idioms like "for robot in robots" should be entirely unaffected -
the registration of the robot instance with the global list of robots can be
handled by the robot initialisation method.

Regards,
Nick.
 
?

=?iso-8859-1?B?QW5kcuk=?=

Nick said:
My (and, if I understand him correctly, Jeremy's) concern would be that error
messages like "Robot 'pete' has hit a wall!" would give students the impression
that the robots automatically know their name as a result of the assignment. In
standard Python, that simply isn't true.

It was not my intention to reveal that I had assigned a 'name' to the
robot; it was only for internal purpose. (However, see below)
If, instead, CreateRobot looked something like:

def CreateRobot(street, avenue, name=None):
if name is None:
name = "Robot" + Robot.getNextNumber()
return Robot(street, avenue, name)


Then, using a simple assignment:

pete = CreateRobot(2, 3)
pete.move()

Would give an error like:

"Robot1 has hit a wall"

That might be an excellent way to solve my problem.
This could then be used to point out that objects named using assignment don't
know about the names they have been given, and need to be told:

pete = CreateRobot(2, 3, "Pete")
pete.move()

"Pete has hit a wall"

Instead of misleading the students ("objects know what names they have been
given"), you have taught them a powerful truth - objects and the names you give
them via assignment are entirely independent.

Good point.
It also directly addresses the question of aliasing. Think about how Steven's
modified dictionary would react to this code:

pete = CreateRobot(2, 3)
dad = pete
dad.move()
pete.move()

Internally, idioms like "for robot in robots" should be entirely unaffected -
the registration of the robot instance with the global list of robots can be
handled by the robot initialisation method.

You make some excellent points. What I implemented (last night) was
the "code pre-processing" suggestion. Instead of simply "exec"uting
the code, I changed it first so that statements like

pete = CreateRobot(2, 3)
john = CreateRobot()
albert = CreateRobot(colour="blue")

get translated to

pete = CreateRobot(2, 3, name="pete")
john = CreateRobot(name="john")
albert = CreateRobot(colour="blue", name="albert")

I just checked with:

pete = CreateRobot()
dad = pete
dad.move()
pete.move()

and I got (I haven't implemented the gui part of dealing with multiple
robots)
==
robot pete move()
robot pete move()
==
which worked the same way as your method would (except with "pete" as a
common name instead of "Robot1").

[As an aside, it was an *interesting* experience to learn enough about
regular expressions to do this.]

Now, after reading your post, I realise that I would have to deal with
the problem of figuring out how to handle cases where the users has
already given a name to the robot. Your solution takes care of this in
a very simple way.

Furthermore, I could probably base a lesson around it, about how
instances have no name.
Thank you very much for your suggestions.

André
 
?

=?iso-8859-1?B?QW5kcuk=?=

Scott said:
André Roberge said:
Craig said:
On Fri, 2005-01-21 at 16:13 -0800, André wrote:

Short version of what I am looking for:

Given a class "public_class" which is instantiated a few times e.g.

a = public_class()
b = public_class()
c = public_class()

I would like to find out the name of the instances so that I could
create a list of them e.g.
['a', 'b', 'c']

...
Behind the scene, I have something like:
robot_dict = { 'robot' = CreateRobot( ..., name = 'robot') }
and have mapped move() to correspond to robot_dict['robot'].move()
(which does lots of stuff behind the scene.)
...[good explanation]...
Does this clarify what I am trying to do and why?

Yup. Would something like this help?

parts = globals().copy()
parts.update(locals())
names = [name for name, value in parts.iteritems()
if isinstance(value, Robot)] # actual class name here

Note, however, that

a = b = CreateRobot()

will give two different names to the same robot.

And even:

Karl = CreateRobot()
Freidrich = CreateRobot()
for robot in (Karl, Freidrich):
robot.move()

Will have two names for "Freidrich" -- Freidrich and robot

--Scott David Daniels

Thanks for your suggestion.
It might have been interesting to try, but I am going to
try and implement a suggestion given by Nick Coghlan instead.
André
 

Ask a Question

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

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

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,562
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top