Appending an attribute to a function in python - python

I am not sure exactly what this means or how it is used, but i came across this functionality when it comes to a function. I am able to dynamically add attributes to a function. Can someone help me understand what is the use of this and how does it happen? I mean its a function name after all, how can we add attributes to it dynamically?
def impossible():
print "Adding a bool"
impossible.enabled = True
# i was able to just do this. And this is a function, how does this add up?
print(impossible.enabled) # No attribute error. o/p --> True

in python functions are objects, they have all sorts of inner attributes and they can also have the __dict__ attribute, and like any other object anything in __dict__ is a variable of that object.you can see it if you print it before and after impossible.enabled
def impossible():
print "Adding a bool"
print(impossible.__dict__) # {}
impossible.enabled = True
print(impossible.__dict__) # {'enabled': True}
this doesn't change the function in any way since most of the time __dict__ is empty and holds no special value in a function.
in fact its a bit useful since you could use this in a function to store static variables without cluttering your global names

The name impossible points to an object that represents the function. You're setting a property on this object (which python allows you to do on all objects by default):
>>> def foo():
... print("test")
...
>>> dir(foo)
['__call__', ..., 'func_closure', 'func_code', 'func_defaults', 'func_dict', 'func_doc', 'func_globals', 'func_name']
>>> foo.a = 'test'
>>> dir(foo)
['__call__', ..., 'a', ...]
Since this object implements __call__, it can be called as a function - you can implement your own class that defines __call__ and it'll also be allowed to be called as a function:
>>> class B:
... def __call__(self, **kw):
... print(kw)
...
>>> b = B()
>>> b()
{}
>>> b(foo='bar')
{'foo': 'bar'}
If you create a new function, you can see that you haven't done anything to the definition of a function (its class), just the object that represents the original function:
>>> def bar():
... print("ost")
...
>>> dir(bar)
['__call__', ..., 'func_closure', ...]
This new object does not have a property named a, since you haven't set one on the object bar points to.

You can, for example, use a function attribute to implement a simple counter, like so:
def count():
try:
count.counter += 1
except AttributeError:
count.counter = 1
return count.counter
Repeatedly calling "count()" yields: 1, 2, 3, ...

Related

Creating a list of objects in Python constructor

I would like to pass a variable into the constructor of an object and depending upon the value get one or more more objects out. Something like:
class MyClass():
def __init__(self,n_objects):
#Should return n_objects of MyClass
Something doesn't seem quite right about it though since I need to return a list (I think) but self is of type "MyClass". What am I missing?
A constructor only returns a single reference of what you are trying to create, so you can't do it this way. What you need is to make this list external from this:
result = [MyClass() for i in xrange(n_objects)]
Then make a wrapper function around that.
Do note that xrange is for python 2, it was renamed to range in python 3.
If you must insist on keeping the "encapsulation" of the class, you can just define a classmethod. Naive example:
>>> class Foo(object):
... def __init__(self):
... self.bar = 1
... #classmethod
... def Copies(cls, n):
... return [cls() for i in xrange(n)]
...
>>> Foo()
<__main__.Foo object at 0x7f2059ac1910>
>>> Foo.Copies(3)
[<__main__.Foo object at 0x7f2059ac19d0>, <__main__.Foo object at 0x7f2059ac1990>, <__main__.Foo object at 0x7f2059ac1a10>]

Why does an object still work properly without the class

I'm a newbie in Python. After reading some chapters of Python Tutorial Release 2.7.5, I'm confused about Python scopes and namespaces. This question may be duplicated because I don't know what to search for.
I created a class and an instance. Then I deleted the class using del. But the instance still works properly. Why?
>>>class MyClass: # define a class
... def greet(self):
... print 'hello'
...
>>>instan = MyClass() # create an instantiation
>>>instan
<__main__.MyClass instance at 0x00BBCDC8>
>>>instan.greet()
hello
>>>dir()
['instan', 'MyClass', '__builtins__', '__doc__', '__name__', '__package__']
>>>
>>>
>>>del MyClass
>>>dir()
['instan', '__builtins__', '__doc__', '__name__', '__package__']
>>>instan
<__main__.MyClass instance at 0x00BBCDC8> # Myclass doesn't exist!
>>>instan.greet()
hello
I know little about OOP so this question may seem simple. Thanks in advance.
Python is a garbage collected language. When you do del MyClass, you do not actually delete the 'class object' (classes are objects too), but you only remove the 'name' MyClass from the current namespace, which is some sort of reference to the class object. Any object stays alive as long as it is referenced by something. Since instances reference their own class, the class will stay alive as long as there is at least one instance alive.
One thing to be careful about is when you redefine a class (e.g. on the command line):
In [1]: class C(object):
...: def hello(self):
...: print 'I am an instance of the old class'
In [2]: c = C()
In [3]: c.hello()
I am an instance of the old class
In [4]: class C(object): # define new class and point C to it
...: def hello(self):
...: print 'I am an instance of the new class'
In [5]: c.hello() # the old object does not magically become a new one
I am an instance of the old class
In [6]: c = C() # point c to new object, old class and object are now garbage
In [7]: c.hello()
I am an instance of the new class
Any existing instances of the old class will continue to have the old behavior, which sort of makes sense considering the things I mentioned. The relation between name-spaces and objects is a bit particular to python, but is not that hard once you get it. A good explanation is given here.
When you delete a variable using del, you delete the variable name and your own reference to the object in the variable, not the object itself.
The object you created still contains its own reference to the class. In general, as long as someone still holds a reference to any object (including a class definition) it won't be deleted by the garbage collector.
Python doesn't store values in variables, it assigns names to objects. The locals() function will return all the names in the current namespace (or more specifically, the current scope). Let's start up a new interpreter session and see what locals() will give us.
>>> locals()
{'__builtins__': <module '__builtin__' (built-in)>, '__name__': '__main__', '__doc__': None, '__package__': None}
The only names currently in the namespace are built in names that Python puts there at start up. Here a quick one-liner to show us only the names we've assigned:
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{}
That's better. Don't worry about how that one-liner works, let's move on and create a class.
>>> class C(object):
greeting = "I'm the first class"
When we define a class, it's name in places in the current scope:
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>}
The part is Python's way of saying that there's an object that's too big to print out, but it's the class object we defined. Let's look at the memory address that our class object is stored at. We can use the id() function to find out.
>>> id(C)
18968856
The number that id() returns is the memory location of the argument. If you run these commands yourself, you'll see a different number, but the number doesn't change during a single session.
>>> id(C)
18968856
Now let's create an instance.
>>> c = C()
>>> c.greeting
"I'm the first class"
Now when we look at locals(), we can see both our class object, and our instance object.
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>}
Every instance object has a special member __class__ that is a reference to the class object that the instance is an instance of.
>>> c.__class__
<class '__main__.C'>
If we call id() on that variable, we can see it's a reference to the class C we just defined:
>>> id(c.__class__)
18968856
>>> id(c.__class__) == id(C)
True
Now let's delete the name C from out local namespace:
>>> del C
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'c': <__main__.C object at 0x011BDED0>}
>>> C
Traceback (most recent call last):
File "<pyshell#16>", line 1, in <module>
C
NameError: name 'C' is not defined
That's exactly what we expect. The name C is no longer assigned to anything. However, our instance still has a reference to the class object.
>>> c.__class__
<class '__main__.C'>
>>> id(c.__class__)
18968856
As you can see, the class still exists, you just can't refer to it through the name C in the local namespace.
Let's create a second class with the name C.
>>> class C(object):
greeting = "I'm the second class"
>>> {k:v for k,v, in locals().iteritems() if k[0] != '_'}
{'C': <class '__main__.C'>, 'c': <__main__.C object at 0x011BDED0>}
If we create an instance of the second class, it behaves like you noticed:
>>> c2 = C()
>>> c2.greeting
"I'm the second class"
>>> c.greeting
"I'm the first class"
To see why, let's look at the id of this new class. We can see that the new class object is stored in a different location from our first one.
>>> id(C)
19011568
>>> id(C) == id(C.__class__)
False
This is why the instances can still work properly: both class object still exists separately, and each instance holds a reference to its object.

What is the dfifference between instance dict and class dict

I was reading the python descriptors and there was one line there
Python first looks for the member in the instance dictionary. If it's
not found, it looks for it in the class dictionary.
I am really confused what is instance dict and what is class dictionary
Can anyone please explain me with code what is that
I was thinking of them as same
An instance dict holds a reference to all objects and values assigned to the instance, and the class level dict holds all references at the class namespace.
Take the following example:
>>> class A(object):
... def foo(self, bar):
... self.zoo = bar
...
>>> i = A()
>>> i.__dict__ # instance dict is empty
{}
>>> i.foo('hello') # assign a value to an instance
>>> i.__dict__
{'zoo': 'hello'} # this is the instance level dict
>>> i.z = {'another':'dict'}
>>> i.__dict__
{'z': {'another': 'dict'}, 'zoo': 'hello'} # all at instance level
>>> A.__dict__.keys() # at the CLASS level, only holds items in the class's namespace
['__dict__', '__module__', 'foo', '__weakref__', '__doc__']
I think, you can understand with this example.
class Demo(object):
class_dict = {} # Class dict, common for all instances
def __init__(self, d):
self.instance_dict = d # Instance dict, different for each instance
And it's always possible to add instance attribute on the fly like this: -
demo = Demo({1: "demo"})
demo.new_dict = {} # A new instance dictionary defined just for this instance
demo2 = Demo({2: "demo2"}) # This instance only has one instance dictionary defined in `init` method
So, in the above example, demo instance has now 2 instance dictionary - one added outside the class, and one that is added to each instance in __init__ method. Whereas, demo2 instance has just 1 instance dictionary, the one added in __init__ method.
Apart from that, both the instances have a common dictionary - the class dictionary.
Those dicts are the internal way of representing the object or class-wide namespaces.
Suppose we have a class:
class C(object):
def f(self):
print "Hello!"
c = C()
At this point, f is a method defined in the class dict (f in C.__dict__, and C.f is an unbound method in terms of Python 2.7).
c.f() will make the following steps:
look for f in c.__dict__ and fail
look for f in C.__dict__ and succeed
call C.f(c)
Now, let's do a trick:
def f_french():
print "Bonjour!"
c.f = f_french
We've just modified the object's own dict. That means, c.f() will now print Bounjour!. This does not affect the original class behaviour, so that other C's instances will still speak English.
Class dict is shared among all the instances (objects) of the class, while each instance (object) has its own separate copy of instance dict.
You can define attributes separately on a per instance basis rather than for the whole class
For eg.
class A(object):
an_attr = 0
a1 = A()
a2 = A()
a1.another_attr = 1
Now a2 will not have another_attr. That is part of the instance dict rather than the class dict.
Rohit Jain has the simplest python code to explain this quickly. However, understanding the same ideas in Java can be useful, and there is much more information about class and instance variables here

replacing the "new" module

I have code which contains the following two lines in it:-
instanceMethod = new.instancemethod(testFunc, None, TestCase)
setattr(TestCase, testName, instanceMethod)
How could it be re-written without using the "new" module? Im sure new style classes provide some kind of workaround for this, but I am not sure how.
There is a discussion that suggests that in python 3, this is not required. The same works in Python 2.6
http://mail.python.org/pipermail/python-list/2009-April/531898.html
See:
>>> class C: pass
...
>>> c=C()
>>> def f(self): pass
...
>>> c.f = f.__get__(c, C)
>>> c.f
<bound method C.f of <__main__.C instance at 0x10042efc8>>
>>> c.f
<unbound method C.f>
>>>
Reiterating the question for every one's benefit, including mine.
Is there a replacement in Python3 for new.instancemethod? That is, given an arbitrary instance (not its class) how can I add a new appropriately defined function as a method to it?
So following should suffice:
TestCase.testFunc = testFunc.__get__(None, TestCase)
You can replace "new.instancemethod" by "types.MethodType":
from types import MethodType as instancemethod
class Foo:
def __init__(self):
print 'I am ', id(self)
def bar(self):
print 'hi', id(self)
foo = Foo() # prints 'I am <instance id>'
mm = instancemethod(bar, foo) # automatically uses foo.__class__
mm() # prints 'I have been bound to <same instance id>'
foo.mm # traceback because no 'field' created in foo to hold ref to mm
foo.mm = mm # create ref to bound method in foo
foo.mm() # prints 'I have been bound to <same instance id>'
This will do the same:
>>> Testcase.testName = testFunc
Yeah, it's really that simple.
Your line
>>> instanceMethod = new.instancemethod(testFunc, None, TestCase)
Is in practice (although not in theory) a noop. :) You could just as well do
>>> instanceMethod = testFunc
In fact, in Python 3 I'm pretty sure it would be the same in theory as well, but the new module is gone so I can't test it in practice.
To confirm that it's not needed to use new.instancemthod() at all since Python v2.4, here's an example how to replace an instance method. It's also not needed to use descriptors (even though it works).
class Ham(object):
def spam(self):
pass
h = Ham()
def fake_spam():
h._spam = True
h.spam = fake_spam
h.spam()
# h._spam should be True now.
Handy for unit testing.

Difference between type(obj) and obj.__class__

What is the difference between type(obj) and obj.__class__? Is there ever a possibility of type(obj) is not obj.__class__?
I want to write a function that works generically on the supplied objects, using a default value of 1 in the same type as another parameter. Which variation, #1 or #2 below, is going to do the right thing?
def f(a, b=None):
if b is None:
b = type(a)(1) # #1
b = a.__class__(1) # #2
This is an old question, but none of the answers seems to mention that. in the general case, it IS possible for a new-style class to have different values for type(instance) and instance.__class__:
class ClassA(object):
def display(self):
print("ClassA")
class ClassB(object):
__class__ = ClassA
def display(self):
print("ClassB")
instance = ClassB()
print(type(instance))
print(instance.__class__)
instance.display()
Output:
<class '__main__.ClassB'>
<class '__main__.ClassA'>
ClassB
The reason is that ClassB is overriding the __class__ descriptor, however the internal type field in the object is not changed. type(instance) reads directly from that type field, so it returns the correct value, whereas instance.__class__ refers to the new descriptor replacing the original descriptor provided by Python, which reads the internal type field. Instead of reading that internal type field, it returns a hardcoded value.
Old-style classes are the problem, sigh:
>>> class old: pass
...
>>> x=old()
>>> type(x)
<type 'instance'>
>>> x.__class__
<class __main__.old at 0x6a150>
>>>
Not a problem in Python 3 since all classes are new-style now;-).
In Python 2, a class is new-style only if it inherits from another new-style class (including object and the various built-in types such as dict, list, set, ...) or implicitly or explicitly sets __metaclass__ to type.
type(obj) and type.__class__ do not behave the same for old style classes:
>>> class a(object):
... pass
...
>>> class b(a):
... pass
...
>>> class c:
... pass
...
>>> ai=a()
>>> bi=b()
>>> ci=c()
>>> type(ai) is ai.__class__
True
>>> type(bi) is bi.__class__
True
>>> type(ci) is ci.__class__
False
There's an interesting edge case with proxy objects (that use weak references):
>>> import weakref
>>> class MyClass:
... x = 42
...
>>> obj = MyClass()
>>> obj_proxy = weakref.proxy(obj)
>>> obj_proxy.x # proxies attribute lookup to the referenced object
42
>>> type(obj_proxy) # returns type of the proxy
weakproxy
>>> obj_proxy.__class__ # returns type of the referenced object
__main__.MyClass
>>> del obj # breaks the proxy's weak reference
>>> type(obj_proxy) # still works
weakproxy
>>> obj_proxy.__class__ # fails
ReferenceError: weakly-referenced object no longer exists
FYI - Django does this.
>>> from django.core.files.storage import default_storage
>>> type(default_storage)
django.core.files.storage.DefaultStorage
>>> default_storage.__class__
django.core.files.storage.FileSystemStorage
As someone with finite cognitive capacity who's just trying to figure out what's going in order to get work done... it's frustrating.

Categories