471,337 Members | 1,452 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,337 software developers and data experts.

Discover instance variables

Ok, I know there has to be a way to do this, but my google-fu fails me
(once more). I have a class with instance variables (or should they be
called attributes, I'm newish to programming and get really confused
with OO sometimes), like the one in this example:

class Foo():
self.a = "bar"
self.z = "test"
self.var = 2

foo = Foo()

I want to print a list of the variables (strings, integers, etc) in
Foo, without knowing their names. So that the user who needs to change
a peice of information can view the variable list, enter the name of
the variable they need to change and then make the change. This is
what I'd like a sample run to look like:

Attributes for foo:
a = bar
z = test
var = 2

Change: a
New value: foobar
Change made!

I can handle the formatting and changing the variable itself, no
problem, but how do I get a list of all the variables in a class
instance? I almost put a list in there called vars and appended all
the variables to it so I could iterate the list, but this sounds like
something useful enough that someone has come up with a better way to
do it than that. It almost looks like self.__dir__() is what I want,
but that returns methods as well, correct? I only want variables, but
I can't think of how to do a list comprehension that would remove the
methods.

JonathanB

Jul 16 '07 #1
7 1416
JonathanB wrote:
Ok, I know there has to be a way to do this, but my google-fu
fails me (once more). I have a class with instance variables (or
should they be called attributes, I'm newish to programming and
get really confused with OO sometimes),
To complete confusion, those terms vary with languages :)
like the one in this example:

class Foo():
self.a = "bar"
self.z = "test"
self.var = 2
This will not work. Please use working code for examples.
I can handle the formatting and changing the variable itself, no
problem, but how do I get a list of all the variables in a class
instance? I almost put a list in there called vars and appended
all the variables to it so I could iterate the list, but this
sounds like something useful enough that someone has come up with
a better way to do it than that.
I'd use exactly this, since there may be attributes you don't want
to be changed from outside (perhaps __class__).
It almost looks like self.__dir__() is what I want, but that
returns methods as well, correct? I only want variables, but I
can't think of how to do a list comprehension that would remove
the methods.
That's quite a problem with your concept. There are no variables and
methods. There are only attributes. Attributes may be objects. Some
objects may be callable (like function objects).

If you know exactly what you want to be accessible like this, you
could filter __dir__() output with name/callable/isinstance tests.

Regards,
Björn
--
BOFH excuse #320:

You've been infected by the Telescoping Hubble virus.

Jul 16 '07 #2
En Mon, 16 Jul 2007 14:25:48 -0300, JonathanB <do******@gmail.com>
escribió:
Ok, I know there has to be a way to do this, but my google-fu fails me
(once more). I have a class with instance variables (or should they be
called attributes, I'm newish to programming and get really confused
with OO sometimes), like the one in this example:

class Foo():
self.a = "bar"
self.z = "test"
self.var = 2

foo = Foo()

I want to print a list of the variables (strings, integers, etc) in
Foo, without knowing their names. So that the user who needs to change
a peice of information can view the variable list, enter the name of
the variable they need to change and then make the change. This is
You should define more precisely *which* attributes do you actually want
in the list, but I think this may serve as a starting point:

pydef get_attributes(obj):
.... return [attr for attr in dir(obj) if not attr.startswith('_') and
.... type(getattr(obj,attr)) in (
.... int,str,unicode,float,dict,list,tuple)]
....
pyf=open("c:\\test.py")
pyget_attributes(f)
['mode', 'name', 'softspace']

The list keeps only the types explicitely enumerated. Other types are
excluded, as well as names starting with "_". Another criterion would be
`not attr.startswith('_') and not callable(getattr(obj,attr))`

--
Gabriel Genellina

Jul 16 '07 #3
JonathanB wrote:
Ok, I know there has to be a way to do this, but my google-fu fails me
(once more). I have a class with instance variables (or should they be
called attributes, I'm newish to programming and get really confused
with OO sometimes), like the one in this example:
Instance variable are indeed attributes, but you are doing fine with the
language so don't worry about it.
class Foo():
self.a = "bar"
self.z = "test"
self.var = 2
That's unlikely to work, though: the code is in the context of the
class, not one of its methods, so unless you happen to be declaring a
class inside another class's method it's unlikely that there's going to
be a "self" around when those three lines execute.

What you probably want is something like what follows (I am running it
interactively so I know I am telling the truth: it keeps me honest :-).
You should get used to using the interpreter to check your hypotheses -
it would have told you you were making a mistake above as soon as you
tried to create a Foo.
>>class Foo:
.... a = "bar"
.... z = "test"
.... var = 2
....

You can check that Foo (the class) has these attributes:
>>Foo.a
'bar'
foo = Foo()
Now foo is an instance of the Foo class. Class attributes can also be
accessed through instances:
>>foo = Foo()
foo.var
2
>>>
Binding an instance attribute, however, doesn't change the class, so you
can use class attributes as a kind of "default" for instance.
>>foo.a = "foo"
foo.a
'foo'
>>Foo.a
'bar'
>>>
I want to print a list of the variables (strings, integers, etc) in
Foo, without knowing their names. So that the user who needs to change
a peice of information can view the variable list, enter the name of
the variable they need to change and then make the change. This is
what I'd like a sample run to look like:

Attributes for foo:
a = bar
z = test
var = 2

Change: a
New value: foobar
Change made!

I can handle the formatting and changing the variable itself, no
problem, but how do I get a list of all the variables in a class
instance? I almost put a list in there called vars and appended all
the variables to it so I could iterate the list, but this sounds like
something useful enough that someone has come up with a better way to
do it than that. It almost looks like self.__dir__() is what I want,
but that returns methods as well, correct? I only want variables, but
I can't think of how to do a list comprehension that would remove the
methods.
[name for name in dir(x) if not callable(name) and not
name.startswith("__")]

might come close - I presume you don't want __doc__ and the like.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------

Jul 16 '07 #4
class Foo():
self.a = "bar"
self.z = "test"
self.var = 2

That's unlikely to work, though: the code is in the context of the
class, not one of its methods, so unless you happen to be declaring a
class inside another class's method it's unlikely that there's going to
be a "self" around when those three lines execute.
Ah, I see. Trouble is I write most of my code on a computer that
doesn't have python (shared computer and I don't have permissions to
install). So I code it here, email it to myself, and test it at home.
I had my debugged code at home so I couldn't post a working example.
Here's working example.

class World():
def __init__(self, name, WTN, Ag, Na, Ex, In, Ni, Al, Port, Type,
Dia, Grav, Atmosphere, Hyd, Climate, Pop, Gov, CR, TL, Wealth,
Trade=None, notes=None):
self.name = name
self.WTN = WTN
self.Ag = Ag
self.Na = Na
self.Ex = Ex
self.In = In
self.Ni = Ni
self.Al = Al
self.Port = Port
self.Trade = Trade
self.Type = Type
self.Dia = Dia
self.Grav = Grav
self.Atmosphere = Atmosphere
self.Hyd = Hyd
self.Climate = Climate
self.Pop = Pop
self.Gov = Gov
self.CR = CR
self.TL = TL
self.Wealth = Wealth
self.notes = notes

The code to execute this is:

def world_info():
# code to prompt for each variable
world = World(name, WTN, Ag, Na, Ex, In, Ni, Al, Port, Type, Dia,
Grav, Atmosphere, Hyd, Climate, Pop, Gov, CR, TL, Wealth)

So given that example, is there a clean way to get this output:

Data for Earth:
Name = Earth
WTN = 5.0
Ag = 0
Na = 0
....
....
Notes = None
[name for name in dir(x) if not callable(name) and not
name.startswith("__")]
That does looks almost exactly like what I want I think (I'm still
learning to read code to learn what it does, but from what it looks
like this does a list comprehension that removes everything callable
and that starts with "__")
[name for name in dir(x) if not callable(name) and not
name.startswith("__")]

might come close - I presume you don't want __doc__ and the like.
Jul 16 '07 #5
Gabriel Genellina <ga*******@yahoo.com.arwrote:
The list keeps only the types explicitely enumerated. Other types are
excluded, as well as names starting with "_". Another criterion would be
`not attr.startswith('_') and not callable(getattr(obj,attr))`
Why not:

In [1]: class Foo(object):
...: a = 3
...:
...:

In [2]: import inspect

In [4]: inspect.getmembers(Foo())
Out[4]:
[('__class__', <class '__main__.Foo'>),
('__delattr__', <method-wrapper '__delattr__' of Foo object at
0x12bf350>),
('__dict__', {}),
('__doc__', None),
('__getattribute__',
<method-wrapper '__getattribute__' of Foo object at 0x12bf350>),
('__hash__', <method-wrapper '__hash__' of Foo object at 0x12bf350>),
('__init__', <method-wrapper '__init__' of Foo object at 0x12bf350>),
('__module__', '__main__'),
('__new__', <built-in method __new__ of type object at 0x307860>),
('__reduce__', <built-in method __reduce__ of Foo object at
0x12bf350>),
('__reduce_ex__', <built-in method __reduce_ex__ of Foo object at
0x12bf350>),
('__repr__', <method-wrapper '__repr__' of Foo object at 0x12bf350>),
('__setattr__', <method-wrapper '__setattr__' of Foo object at
0x12bf350>),
('__str__', <method-wrapper '__str__' of Foo object at 0x12bf350>),
('__weakref__', None),
('a', 3)]

and then filter out __xyz__ methods?
--
Lawrence, oluyede.org - neropercaso.it
"It is difficult to get a man to understand
something when his salary depends on not
understanding it" - Upton Sinclair
Jul 16 '07 #6
In article <11**********************@n60g2000hse.googlegroups .com>,
JonathanB <do******@gmail.comwrote:
I can handle the formatting and changing the variable itself, no
problem, but how do I get a list of all the variables in a class
instance? I almost put a list in there called vars and appended all
the variables to it so I could iterate the list, but this sounds like
something useful enough that someone has come up with a better way to
do it than that. It almost looks like self.__dir__() is what I want,
but that returns methods as well, correct? I only want variables, but
I can't think of how to do a list comprehension that would remove the
methods.
For simple cases, the object's __dict__ will probably give you what you
want. By default, that's where an object's instance variables are
stored, and you can just examine the keys, etc:

class Foo(object):
def __init__(self):
self.a = "bar"
self.z = "test"
self.var = 2

foo = Foo()
print foo.__dict__

-{'a': 'bar', 'var': 2, 'z': 'test'}

However, there are lots of ways to bypass using the __dict__ to hold
attributes. If the class uses any of these techniques, __dict__ either
will not exist or may not be complete. A few of the techniques that
come to mind are:

* custom __getattr__/__setattr__ methods (or __getattribute__ in a new
style class)

* descriptors (http://docs.python.org/ref/descriptors.html)

* using __slots__ in a new style class
Dave
Jul 18 '07 #7
JonathanB wrote:
So given that example, is there a clean way to get this output:

Data for Earth:
Name = Earth
WTN = 5.0
Ag = 0
Na = 0
...
...
Notes = None
Sure, save the __init__ parameters explicitly in a dict.

self.data = {"Name": name,
"WTN": WTN,
"Ag": Ag,
...
}

To display them, you can iterate through the dict:

print "Data for Earth:"
for field, content in self.data.items():
print "%s = %r" % field, content

Hope that helps.

Regards,
Björn

--
BOFH excuse #188:

...disk or the processor is on fire.

Jul 18 '07 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

3 posts views Thread by David MacQuigg | last post: by
2 posts views Thread by hvj | last post: by
2 posts views Thread by Nikolaus Rath | last post: by
45 posts views Thread by =?Utf-8?B?QmV0aA==?= | last post: by
reply views Thread by rosydwin | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.