Python2 - printing an object's default attributes - python

I'm new to OOP, but I'm trying to look at an object's vars. Other Stack-O answers have suggested using object.__dict__ or vars(object). So I went into the Python shell to try a quick example, but I noticed neither of these answers prints the object's default attributes, only newly-assigned attributes, e.g.:
>>> class Classy():
... inty = 3
... stringy = "whatevs"
...
>>> object = Classy()
>>> object.inty
3
>>> object.__dict__
{}
>>> vars(object)
{}
>>> object.inty = 27
>>> vars(object)
{'inty': 27}
>>> object.__dict__
{'inty': 27}
Why are the variables present in one sense but not another? Is it because I didn't explicitly initialize them or something?

It's important understanding that in Python everything is an object (including functions, and a class declaration itself)
When you do this:
class Classy():
inty = 3
stringy = "whatevs"
You're assigning inty and stringy to the Class, not to the instances. Check this:
class Classy():
inty = 3
stringy = "whatevs"
print(Classy.__dict__)
Wait... A class with a __dict__? Yeah, because Classy is also an instance (of type classobj, since you're using old style classes, which you shouldn't really do, by the way... You should inherit from object, which gives you access to more goodies)
>>> print(type(Classy))
<type 'classobj'>
Now, if you created an instance of classy, and put an inty value to it, you would have:
class Classy():
inty = 3
stringy = "whatevs"
def __init__(self):
self.inty = 5
classy = Classy()
print("__dict__ of instance: %s" % classy.__dict__)
print("__dict__ of Class: %s" % classy.__class__.__dict__)
Which outputs
__dict__ of instance: {'inty': 5}
__dict__ of Class: {'__module__': '__main__', 'inty': 3, '__doc__': None, '__init__': <function __init__ at 0x1080de410>, 'stringy': 'whatevs'}
See the inty being 5 in the __dict__ of the instance but still being 3 in the __dict__ of the class? It's because now you have two inty: One attached to classy, an instance of the class Classy and another one attached to the class Classy itself (which is, in turn, an instance of classobj)
If you did
classy = Classy()
print(classy.inty)
print(classy.stringy)
You'd see:
5
whatevs
Why? Because when you try to get inty on the instance, Python will look for it in the __dict__ of the instance first. If it doesn't find it, it will go to the __dict__ of the class. That is what's happening on classy.stringy. Is it in the classy instance? Nopes. Is it in the Classy class? Yep! Aight, return that one... And that's the one you see.
Also, I mentioned that the Classy class is an object, right? And as such, you can assign it to something else like this:
What = Classy # No parenthesis
foo = What()
print(foo.inty)
And you'll see the 5 that was "attached" in Classy.__init__ because when you did What = Classy, you're assigning the class Classy to a variable named What, and when you do foo=What() you're actually running the constructor of Classy (remember: What and Classy are the same thing)
Another thing Python allows (and that I personally don't like because then it makes code very difficult to follow) is attaching attributes to instances "on-the-fly":
classy = Classy()
try:
print(classy.other_thing)
except AttributeError:
print("Oh, dang!! No 'other_thing' attribute!!")
classy.other_thing = "hello"
print(classy.other_thing)
Will output
Oh, dang!! No 'other_thing' attribute!!
hello
Oh, and did I say that functions are objects? Yeah, they are... and as such, you can also assign attributes to them (also, something that makes code really, really confusing) but you could do it...
def foo_function():
return None # Very dummy thing we're doing here
print("dict of foo_function=%s" % foo_function.__dict__)
foo_function.horrible_thing_to_do = "http://www.nooooooooooooooo.com/"
print("Horrible thing? %s" % foo_function.horrible_thing_to_do)
Outputs:
dict of foo_function={}
Horrible thing? http://www.nooooooooooooooo.com/

You can use vars or __dict__ with the class name, not instance:
Option 1:
class Classy:
inty = 3
stringy = "whatevs"
final_vals = {a:b for a, b in vars(Classy).items() if a not in ['__doc__', '__module__']}
Output:
{'inty': 3, 'stringy': 'whatevs'}
Option 2:
final_vals = {a:b for a, b in Classy.__dict__.items() if a not in ['__doc__', '__module__']}

The reason that the .__dict__ and vars methods aren't working as you expected is because you haven't defined a constructor for your class with python's self reference. The following will do what you're looking for:
class Classy():
def __init__(self):
self.inty = 3
self.stringy = 'whatevs'
object = Classy()
object.__dict__
vars(object)
Outputs:
{'inty': 3, 'stringy': 'whatevs'}
{'inty': 3, 'stringy': 'whatevs'}
Cheers!

Related

What better way to get around the "static variables" in Python?

It seems that in Python, to declare a variable in a class, it is static (keeps its value in the next instances). What better way to get around this problem?
class Foo():
number = 0
def set(self):
self.number = 1
>>> foo = Foo()
>>> foo.number
0
>>> foo.set()
>>> foo.number
1
>>> new_foo = Foo()
>>> new_foo.number
1
Variables defined at the class level are indeed "static", but I don't think they work quite the way you think they do. There are 2 levels here which you need to worry about. There are attributes at the class level, and there are attributes at the instance level. Whenever you do self.attribute = ... inside a method, you're setting an attribute at the instance level. Whenever python looks up an attribute, it first looks at the instance level, if it doesn't find the attribute, it looks at the class level.
This can be a little confusing (especially if the attribute is a reference to a mutable object). consider:
class Foo(object):
attr = [] #class level attribute is Mutable
def __init__(self):
# in the next line, self.attr references the class level attribute since
# there is no instance level attribute (yet)
self.attr.append('Hello')
self.attr = []
# Now, we've created an instance level attribute, so further appends will
# append to the instance level attribute, not the class level attribute.
self.attr.append('World')
a = Foo()
print (a.attr) #['World']
print (Foo.attr) #['Hello']
b = Foo()
print (b.attr) #['World']
print (Foo.attr) #['Hello', 'Hello']
As others have mentioned, if you want an attribute to be specific to an instance, just initialize it as an instance attribute in __init__ (using self.attr = ...). __init__ is a special method which is run whenever a class is initialized (with a few exceptions that we won't discuss here).
e.g.
class Foo(object):
def __init__(self):
self.attr = 0
Just leave the declaration out. If you want to provide default values for the variables, initialize them in the __init__ method instead.
class Foo(object):
def __init__(self):
self.number = 0
def set(self):
self.number = 1
>>> foo = Foo()
>>> foo.number
0
>>> foo.set()
>>> foo.number
1
>>> new_foo = Foo()
>>> new_foo.number
0
Edit: replaced last line of the above snippet; it used to read 1 although it was just a typo on my side. Seems like it has caused quite a bit of confusion while I was away.
You maybe want to change the class attribute:
class Foo():
number = 0
def set(self):
Foo.number = 1
instead of overriding it!

Built-in function to read __slots__

Let's say I have a class like this:
class Test(object):
prop = property(lambda self: "property")
The descriptor takes priority whenever I try to access Test().prop. So that will return 'property'. If I want to access the object's instance storage, I can do:
x = Test()
x.__dict__["prop"] = 12
print(x.__dict__["prop"])
However if I change my class to:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
How do I do the same, and access the internal storage of x, to write 12 and read it back, since x.__dict__ no longer exist?
I am fairly new with Python, but I understand the Python philosophy is to give complete control, so why is an implementation detail preventing me from doing that?
Isn't Python missing a built-in function that could read from an instance internal storage, something like:
instance_vars(x)["prop"] = 12
print(instance_vars(x)["prop"])
which would work like vars, except it also works with __slots__, and with built-in types that don't have a __dict__?
Short answer, You can't
The problem is that slots are themselves implemented in terms of descriptors. Given:
class Test(object):
__slots__ = ("prop",)
t = Test()
the phrase:
t.prop
Is translated, approximately to:
Test.prop.__get__(t, Test)
where Test.prop is a <type 'member_descriptor'> crafted by the run-time specifically to load prop values out of Test instances from their reserved space.
If you add another descriptor to the class body definition, it masks out the member_descriptor that would let you get to the slotted attribute; there's no way to ask for it, it's just not there anymore. It's effectively like saying:
class Test(object):
#property
def prop(self):
return self.__dict__['prop']
#property
def prop(self):
return "property"
You've defined it twice. there's no way to "get at" the first prop definition.
but:
Long answer, you can't in a general way. You can
You can still abuse the python type system to get at it using another class definition. You can change the type of a python object, so long as it has the exact same class layout, which roughly means that it has all of the same slots:
>>> class Test1(object):
... __slots__ = ["prop"]
... prop = property(lambda self: "property")
...
>>> class Test2(object):
... __slots__ = ["prop"]
...
>>> t = Test1()
>>> t.prop
'property'
>>> t.__class__ = Test2
>>> t.prop = 5
>>> t.prop
5
>>> t.__class__ = Test1
>>> t.prop
'property'
But there's no general way to introspect an instance to work out its class layout; you just have to know from context. You could look at it's __slots__ class attribute, but that won't tell you about the slots provided in the superclass (if any) nor will it give you any hint if that attribute has changed for some reason after the class was defined.
I don't quite understand what and why you want to do this, but does this help you?
>>> class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
>>> a = Test()
>>> b = Test()
>>> a.prop
'property'
>>> tmp = Test.prop
>>> Test.prop = 23
>>> a.prop
23
>>> Test.prop = tmp; del tmp
>>> b.prop
'property'
of course, you cannot overwrite the property on a per-instance basis, that's the whole point of slotted descriptors.
Note that subclasses of a class with __slots__ do have a __dict__ unless you manually define __slots__, so you can do:
>>> class Test2(Test):pass
>>> t = Test2()
>>> t.prop
'property'
>>> t.__dict__['prop'] = 5
>>> t.__dict__['prop']
5
>>> Test2.prop
<property object at 0x00000000032C4278>
but still:
>>> t.prop
'property'
and that's not because of __slots__, it's the way descriptors work.
your __dict__ is bypassed on attribute lookup, you are just abusing it as data structure that happens to be there for storing a state.
it is equivalent to do this:
>>> class Test(object):
__slots__ = ("prop", "state")
prop = property(lambda self: "property")
state = {"prop": prop}
>>> t.prop
'property'
>>> t.state["prop"] = 5
>>> t.state["prop"]
5
>>> t.prop
'property'
If you really ever want to do something like that, and you REALL REALLY need something like that, you can always override __getattribute__ and __setattribute__, it's just as stupid... This is just to prove it to you:
class Test(object):
__slots__ = ("prop",)
prop = property(lambda self: "property")
__internal__ = {}
def __getattribute__(self, k):
if k == "__dict__":
return self.__internal__
else:
try:
return object.__getattribute__(self, k)
except AttributeError, e:
try:
return self.__internal__[k]
except KeyError:
raise e
def __setattribute__(self, k, v):
self.__internal__[k] = v
object.__setattribute__(self, k, v)
t = Test()
print t.prop
t.__dict__["prop"] = "test"
print "from dict", t.__dict__["prop"]
print "from getattr", t.prop
import traceback
# These won't work: raise AttributeError
try:
t.prop2 = "something"
except AttributeError:
print "see? I told you!"
traceback.print_exc()
try:
print t.prop2
except AttributeError:
print "Haha! Again!"
traceback.print_exc()
(Tried it on Python 2.7)
It's exactly what you expect I guess. Don't do this, it's useless.

Python Reflection and callable objects

I have a two part question.
>>> class One(object):
... pass
...
>>> class Two(object):
... pass
...
>>> def digest(constr):
... c = apply(constr)
... print c.__class__.__name__
... print constr.__class__.__name__
...
>>> digest(Two)
Two
type
How would one create object 'Two'? Neither constr() or c() work; and it seems that apply turns it into a type.
What happens when you pass a class rather and an instance into a method?
Classes are high level objects, so you can simply pass them like this:
def createMyClass ( myClass ):
obj = myClass()
return obj
class A ( object ):
pass
>>> x = createMyClass( A )
>>> type( x )
<class '__main__.A'>
How would one create object 'Two'?
Neither constr() or c() work; and it
seems that apply turns it into a
type.
The above comment was made in regards to this code:
>>> def digest(constr):
... c = apply(constr)
... print c.__class__.__name__
... print constr.__class__.__name__
apply (deprecated: see #pyfunc's answer) certainly does not turn the class Two into a type: It already is one.
>>> class Two(object): pass
...
>>> type(Two)
<type 'type'>
Classes are first class objects: they're instances of type. This makes sense if you look at the next example.
>>> two = Two()
>>> type(two)
<class '__main__.Two'>
You can see that a class very clearly functions as a type because it can be returned from type. Here's another example.
>>> Three = type('Three', (Two, ), {'foo': 'bar'})
>>> type(Three)
<type 'type'>
>>> three = Three()
>>> type(three)
<class '__main__.Three'>
You can see that type is a class that can be instantiated. Its constructor takes three arguments: the name of the class, a tuple of base classes and a dictionary containing the class attributes. It returns a new type aka class.
As to your final question,
What happens when you pass a class
rather and an instance into a method?
You're going to have to be more specific. Classes are just instances of type and so are first class objects. Asking what happens if I pass a class into a method is like asking what happens if I pass an integer into a method: It depends entirely on what the method is expecting.
Just another one example:
def InstanceFactory(classname):
cls = globals()[classname]
return cls()
class A(object):
def start(self):
print "a.start"
class B(object):
def start(self):
print "b.start"
InstanceFactory("A").start()
InstanceFactory("B").start()
If the class belongs to another module:
def InstanceFactory(modulename, classname):
if '.' in modulename:
raise ValueError, "can't handle dotted modules yet"
mod = __import__(modulename)
cls = getattr(mod, classname]
return cls()
I am confused though. Wasn't apply() deprecated since 2.3
http://www.python.org/dev/peps/pep-0290/
We don't need this any more.
apply(f, args, kwds) --> f(*args, **kwds)
Others have been moved / considered deprecated in modern usage:
buffer()
coerce()
and intern()
Simply use : Classname() to create an object.

Python singleton pattern

someone can tell me why this is incorrect as a singleton pattern:
class preSingleton(object):
def __call__(self):
return self
singleton = preSingleton()
# singleton is actually the singleton
a = singleton()
b = singleton()
print a==b
a.var_in_a = 100
b.var_in_b = 'hello'
print a.var_in_b
print b.var_in_a
Edit: The above code prints:
True
hello
100
thank you very much
Part Two
Maybe this is better?
class Singleton(object):
def __new__(cls):
return cls
a = Singleton()
b = Singleton()
print a == b
a.var_in_a = 100
b.var_in_b = 'hello'
print a.var_in_b
print b.var_in_a
Edit: The above code prints:
True
hello
100
Thanks again.
Singletons are actually really simple to make in Python. The trick is to have the module do your encapsulation for you and not make a class.
The module will only be initialized once
The module will not be initialized until the first time it is imported
Any attempts to re-import the module will return a pointer to the existing import
And if you want to pretend that the module is an instance of a class, you can do the following
import some_module
class SomeClass(object):
def __init__(self):
self.singleton = some_module
Because this is not a singleton. Singleton must be single, your object is not.
>>> class preSingleton(object):
... def __call__(self):
... return self
...
>>> singleton = preSingleton()
>>> singleton2 = preSingleton()
>>> singleton
<__main__.preSingleton object at 0x00C6D410>
>>> singleton2
<__main__.preSingleton object at 0x00C6D290>
This is actualy the Borg pattern. Multiple objects that share state.
That's not to say there's anything wrong with it, and for most if not all use cases it's functionaly equivalent to a singleton, but since you asked...
edit: Of course since they're Borg objects, each instance uses up more memory so if you're creating tons of them this will make a difference to resource usage.
Here's a sexy little singleton implemented as a decorator:
def singleton(cls):
"""Decorate a class with #singleton when There Can Be Only One."""
instance = cls()
instance.__call__ = lambda: instance
return instance
Use it like this:
#singleton
class MySingleton:
def spam(self):
print id(self)
What happens is that outside of the class definition, MySingleton will actually refer to the one and only instance of the class that exists, and you'll be left with no mechanism for creating any new instances. Calling MySingleton() will simply return the exact same instance. For example:
>>> MySingleton
<__main__.MySingleton instance at 0x7f474b9265a8>
>>> MySingleton()
<__main__.MySingleton instance at 0x7f474b9265a8>
>>> MySingleton() is MySingleton
True
>>> MySingleton.spam()
139944187291048
>>> MySingleton().spam()
139944187291048
I don't see the problem (if it walks like a duck and quacks like a duck...). Looks like a singleton to me.
It works differently from a Java singleton (for example) because Python uses the same syntax to call a function as to create a new instance of an object. So singleton() is actually calling the singleton object, which returns itself.
You can do this with your class:
>>> class preSingleton(object):
... def __call__(self):
... return self
...
>>> x = preSingleton()
>>> y = preSingleton()
>>> x == y
False
So, more than one instances of the class can be created and it violates the Singleton pattern.

How to get instance variables in Python?

Is there a built-in method in Python to get an array of all a class' instance variables? For example, if I have this code:
class hi:
def __init__(self):
self.ii = "foo"
self.kk = "bar"
Is there a way for me to do this:
>>> mystery_method(hi)
["ii", "kk"]
Edit: I originally had asked for class variables erroneously.
Every object has a __dict__ variable containing all the variables and its values in it.
Try this
>>> hi_obj = hi()
>>> hi_obj.__dict__.keys()
Output
dict_keys(['ii', 'kk'])
Use vars()
class Foo(object):
def __init__(self):
self.a = 1
self.b = 2
vars(Foo()) #==> {'a': 1, 'b': 2}
vars(Foo()).keys() #==> ['a', 'b']
You normally can't get instance attributes given just a class, at least not without instantiating the class. You can get instance attributes given an instance, though, or class attributes given a class. See the 'inspect' module. You can't get a list of instance attributes because instances really can have anything as attribute, and -- as in your example -- the normal way to create them is to just assign to them in the __init__ method.
An exception is if your class uses slots, which is a fixed list of attributes that the class allows instances to have. Slots are explained in http://www.python.org/2.2.3/descrintro.html, but there are various pitfalls with slots; they affect memory layout, so multiple inheritance may be problematic, and inheritance in general has to take slots into account, too.
Both the Vars() and dict methods will work for the example the OP posted, but they won't work for "loosely" defined objects like:
class foo:
a = 'foo'
b = 'bar'
To print all non-callable attributes, you can use the following function:
def printVars(object):
for i in [v for v in dir(object) if not callable(getattr(object,v))]:
print '\n%s:' % i
exec('print object.%s\n\n') % i
You can also test if an object has a specific variable with:
>>> hi_obj = hi()
>>> hasattr(hi_obj, "some attribute")
False
>>> hasattr(hi_obj, "ii")
True
>>> hasattr(hi_obj, "kk")
True
Your example shows "instance variables", not really class variables.
Look in hi_obj.__class__.__dict__.items() for the class variables, along with other other class members like member functions and the containing module.
class Hi( object ):
class_var = ( 23, 'skidoo' ) # class variable
def __init__( self ):
self.ii = "foo" # instance variable
self.jj = "bar"
Class variables are shared by all instances of the class.
Suggest
>>> print vars.__doc__
vars([object]) -> dictionary
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
In otherwords, it essentially just wraps __dict__
Although not directly an answer to the OP question, there is a pretty sweet way of finding out what variables are in scope in a function. take a look at this code:
>>> def f(x, y):
z = x**2 + y**2
sqrt_z = z**.5
return sqrt_z
>>> f.func_code.co_varnames
('x', 'y', 'z', 'sqrt_z')
>>>
The func_code attribute has all kinds of interesting things in it. It allows you todo some cool stuff. Here is an example of how I have have used this:
def exec_command(self, cmd, msg, sig):
def message(msg):
a = self.link.process(self.link.recieved_message(msg))
self.exec_command(*a)
def error(msg):
self.printer.printInfo(msg)
def set_usrlist(msg):
self.client.connected_users = msg
def chatmessage(msg):
self.printer.printInfo(msg)
if not locals().has_key(cmd): return
cmd = locals()[cmd]
try:
if 'sig' in cmd.func_code.co_varnames and \
'msg' in cmd.func_code.co_varnames:
cmd(msg, sig)
elif 'msg' in cmd.func_code.co_varnames:
cmd(msg)
else:
cmd()
except Exception, e:
print '\n-----------ERROR-----------'
print 'error: ', e
print 'Error proccessing: ', cmd.__name__
print 'Message: ', msg
print 'Sig: ', sig
print '-----------ERROR-----------\n'
Sometimes you want to filter the list based on public/private vars. E.g.
def pub_vars(self):
"""Gives the variable names of our instance we want to expose
"""
return [k for k in vars(self) if not k.startswith('_')]
built on dmark's answer to get the following, which is useful if you want the equiv of sprintf and hopefully will help someone...
def sprint(object):
result = ''
for i in [v for v in dir(object) if not callable(getattr(object, v)) and v[0] != '_']:
result += '\n%s:' % i + str(getattr(object, i, ''))
return result
You will need to first, examine the class, next, examine the bytecode for functions, then, copy the bytecode, and finally, use the __code__.co_varnames. This is tricky because some classes create their methods using constructors like those in the types module. I will provide code for it on GitHub.
Based on answer of Ethan Joffe
def print_inspect(obj):
print(f"{type(obj)}\n")
var_names = [attr for attr in dir(obj) if not callable(getattr(obj, attr)) and not attr.startswith("__")]
for v in var_names:
print(f"\tself.{v} = {getattr(obj, v)}\n")

Categories

Resources