finding name of instances created

M

Michael Tobis

I have a similar problem. Here's what I do:

..def new_robot_named(name,indict=globals()):
.. execstr = name + " = robot('" + name + "')"
.. exec(execstr,indict)

..class robot(object):
.. def __init__(self,name):
.. self.name = name

.. def sayhi(self):
.. print "Hi! I'm %s!" % self.name

..if __name__=="__main__":
.. new_robot_named('Bert')
.. new_robot_named('Ernie')
.. Ernie.sayhi()
.. Bert.sayhi()
 
S

Steven Bethard

Michael said:
I have a similar problem. Here's what I do:

.def new_robot_named(name,indict=globals()):
. execstr = name + " = robot('" + name + "')"
. exec(execstr,indict)

.class robot(object):
. def __init__(self,name):
. self.name = name

. def sayhi(self):
. print "Hi! I'm %s!" % self.name

.if __name__=="__main__":
. new_robot_named('Bert')
. new_robot_named('Ernie')
. Ernie.sayhi()
. Bert.sayhi()

If you're changing the syntax from
alex = CreateRobot()
to
new_robot_named('Alex')
I don't see what you gain from using exec...

py> class robot(object):
.... def __init__(self,name):
.... self.name = name
.... def sayhi(self):
.... print "Hi! I'm %s!" % self.name
....
py> def new_robot_named(name, indict=globals()):
.... indict[name] = robot(name)
....
py> new_robot_named('Bert')
py> new_robot_named('Ernie')
py> Ernie.sayhi()
Hi! I'm Ernie!
py> Bert.sayhi()
Hi! I'm Bert!
py> import new
py> temp = new.module('temp')
py> new_robot_named('Alex', temp.__dict__)
py> temp.Alex.sayhi()
Hi! I'm Alex!

That said, I do think a 'new_robot_named' function is probably a better
approach than trying to change the meaning of Python's assignment
statement...

Steve
 
G

Georg Brandl

Michael said:
I have a similar problem. Here's what I do:

.def new_robot_named(name,indict=globals()):
. execstr = name + " = robot('" + name + "')"
. exec(execstr,indict)

.class robot(object):
. def __init__(self,name):
. self.name = name

. def sayhi(self):
. print "Hi! I'm %s!" % self.name

.if __name__=="__main__":
. new_robot_named('Bert')
. new_robot_named('Ernie')
. Ernie.sayhi()
. Bert.sayhi()

Uh. Try explaining this to newbies... ;)

On a second thought, the idea is quite usable considering some differences:

class Robot(object):
# as above

class Robots(dict):
def new(self, name):
new_robot = Robot(name)
self[name] = new_robot
return new_robot
def __getattr__(self, name):
if name in self:
return self[name]
raise AttributeError

robots = Robots()
robots.new('Bert')
robots.new('Ernie')
robots.Bert.sayhi()
robots["Bert"].sayhi()

for robot in robots:
robot.sayhi()

.... etc ...

This doesn't include ugly globals() and exec "tricks".

Georg
 
S

Steven Bethard

Nick said:
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()

If you'd like to handle these cases, but you don't want to have to
explain aliasing right off the bat, you could try something like:

py> class Robot(object):
.... def __init__(self):
.... self.names = set()
.... def move(self):
.... if len(self.names) == 1:
.... name, = self.names
.... print "robot with name %r moved" % name
.... else:
.... print "robot with names %r moved" % sorted(self.names)
....
py> class RobotDict(dict):
.... def __setitem__(self, name, value):
.... if isinstance(value, Robot):
.... value.names.add(name)
.... super(RobotDict, self).__setitem__(name, value)
....
py> user_code = """\
.... nick = Robot()
.... pete = Robot()
.... dad = pete
.... nick.move()
.... dad.move()
.... pete.move()"""
py> exec user_code in RobotDict(Robot=Robot)
robot with name 'nick' moved
robot with names ['dad', 'pete'] moved
robot with names ['dad', 'pete'] moved

That is, you can just keep track of all the names of a Robot in the
Robot object. In the simple case, where there's only one name, you can
display it as such. In the more complicated case, where there's some
aliasing, you can display the multiple aliases. This means you don't
have to teach about aliasing right off the bat, but if a student
accidentally discovers it on their own, the machinery's there to explain
it...

Steve
 
N

Nick Coghlan

Steven said:
That is, you can just keep track of all the names of a Robot in the
Robot object. In the simple case, where there's only one name, you can
display it as such. In the more complicated case, where there's some
aliasing, you can display the multiple aliases. This means you don't
have to teach about aliasing right off the bat, but if a student
accidentally discovers it on their own, the machinery's there to explain
it...

Incidentally, this discussion made me realise the real reason why using a lambda
to create a named function is evil:

Py> def f(): pass
....
Py> f.func_name
'f'
Py> f = lambda: None
Py> f.func_name
'<lambda>'

I think I've heard that explanation before, but it never really clicked.

Cheers,
Nick.
 
F

Fredrik Lundh

Nick said:
Incidentally, this discussion made me realise the real reason why using a lambda to create a named
function is evil:

Py> def f(): pass
...
Py> f.func_name
'f'
Py> f = lambda: None
Py> f.func_name
'<lambda>'

I think I've heard that explanation before, but it never really clicked.

that's nothing you cannot fix, though:
'f'

(only works in 2.4 and later, from what I can tell)

</F>
 
R

Ryan Paul

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']


A working solution:

class A:
pass

a = A()
b = A()
c = A()

[x for x,y in locals().items() if
hasattr(y,"__class__") and y.__class__ == A]

That said, you probably dont want to do it. I doubt that it will work
consistently.

BTW, based on my understanding of the other stuff you said, this is
probably not the best way to do whatever it is you are trying to do.

--SegPhault
 
R

Ryan Paul

A working solution:

class A:
pass

a = A()
b = A()
c = A()

[x for x,y in locals().items() if
hasattr(y,"__class__") and y.__class__ == A]

Just wanted to clarify, because I know that the intellectually deficient
amongst you will say that isinstance is better than using __class__...

In this case isinstance isnt desirable because it will catch
instances of any objects that inherit A, not just instances of A. Observe:

class A: pass
class B(A): pass

a = A()
b = A()
c = A()
d = B()
[x for x,y in locals().items() if isinstance(y,A)]
['a', 'c', 'b', 'd']
[x for x,y in locals().items() if
.... hasattr(y,"__class__") and y.__class__ == A]
['a', 'c', 'b']

-- SegPhault
 
A

Antoon Pardon

Op 2005-01-24 said:
Incidentally, this discussion made me realise the real reason why using a lambda
to create a named function is evil:

It is not a named function, it is just a lamda that is assigned to a
name.
Py> def f(): pass
...
Py> f.func_name
'f'
Py> f = lambda: None
Py> f.func_name
'<lambda>'

I think I've heard that explanation before, but it never really clicked.

I just don't see what is so evil about it.

Why is it so trouble some that a function wouldn't have a name, while
most objects don't have a name. Why is it a problem doing something
like:

f = lambda: None

But isn't it a problem doing something like

v = None.


Why don't we demand something like

Py> assign v: None
Py> v.obj_name
'v'
 
?

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

Ryan said:
A working solution:

class A:
pass

a = A()
b = A()
c = A()

[x for x,y in locals().items() if
hasattr(y,"__class__") and y.__class__ == A]

Just wanted to clarify, because I know that the intellectually deficient
amongst you will say that isinstance is better than using __class__...

In this case isinstance isnt desirable because it will catch
instances of any objects that inherit A, not just instances of A. Observe:

class A: pass
class B(A): pass

a = A()
b = A()
c = A()
d = B()
[x for x,y in locals().items() if isinstance(y,A)]
['a', 'c', 'b', 'd']
[x for x,y in locals().items() if
... hasattr(y,"__class__") and y.__class__ == A]
['a', 'c', 'b']

Actually, it this case, isinstance *is* desirable (or rather *would
have been*), exactly for the reason that you point out. After teaching
about objects, one of the next subject would be that of inheritance.
E.G.

class BetterRobot(Robot):
.... # create a robot that can turn right directly...

However, I have been convinced that it would be much truer to Python to
give the robot fake names (robot1, robot2, ...), and then have students
name their own robots through declarations like:

cleese = Robot(name="Cleese")

or
cleese = Robot()
cleese.name = "Cleese"
=====
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

No members online now.

Forum statistics

Threads
473,773
Messages
2,569,594
Members
45,118
Latest member
LatishaWhy
Top