Can I create an object that receives arbitrary method invocation in python? - python

In python, can I create a Class that, when instantiated, can receive arbitrary method invocation? I have read this but couldn't put the pieces together
I guess it has something to do with the attribute lookup. For a class Foo:
class Foo(object):
def bar(self, a):
print a
The class attribute can be obtained by print Foo.__dict__, which gives
{'__dict__': <attribute '__dict__' of 'Foo' objects>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__module__': '__main__', 'bar': <function bar at 0x7facd91dac80>, '__doc__': None}
So this code is valid
foo = Foo()
foo.bar("xxx")
If I call foo.someRandomMethod(), AttributeError: 'Foo' object has no attribute 'someRandomMethod' would be resulted.
I want foo object to receive any random invocations and defaults to no-op, ie.
def func():
pass
How can I achieve this? I want this behaviour to mock an object for testing.

From http://rosettacode.org/wiki/Respond_to_an_unknown_method_call#Python
class Example(object):
def foo(self):
print("this is foo")
def bar(self):
print("this is bar")
def __getattr__(self, name):
def method(*args):
print("tried to handle unknown method " + name)
if args:
print("it had arguments: " + str(args))
return method
example = Example()
example.foo() # prints “this is foo”
example.bar() # prints “this is bar”
example.grill() # prints “tried to handle unknown method grill”
example.ding("dong") # prints “tried to handle unknown method ding”
# prints “it had arguments: ('dong',)”

Related

get only values with #property wrapping from a python class [duplicate]

Is it possible to obtain a list of all #property decorated methods in a class? If so how?
Example:
class MyClass(object):
#property
def foo(self):
pass
#property
def bar(self):
pass
How would I obtain ['foo', 'bar'] from this class?
Anything decorated with property leaves a dedicated object in your class namespace. Look at the __dict__ of the class, or use the vars() function to obtain the same, and any value that is an instance of the property type is a match:
[name for name, value in vars(MyClass).items() if isinstance(value, property)]
Demo:
>>> class MyClass(object):
... #property
... def foo(self):
... pass
... #property
... def bar(self):
... pass
...
>>> vars(MyClass)
dict_proxy({'__module__': '__main__', 'bar': <property object at 0x1006620a8>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, 'foo': <property object at 0x100662050>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None})
>>> [name for name, value in vars(MyClass).items() if isinstance(value, property)]
['bar', 'foo']
Note that this will include anything that used property() directly (which is what a decorator does, really), and that the order of the names is arbitrary (as dictionaries have no set order).

Property decorator does not add the attribute to __dict__ [duplicate]

Is it possible to obtain a list of all #property decorated methods in a class? If so how?
Example:
class MyClass(object):
#property
def foo(self):
pass
#property
def bar(self):
pass
How would I obtain ['foo', 'bar'] from this class?
Anything decorated with property leaves a dedicated object in your class namespace. Look at the __dict__ of the class, or use the vars() function to obtain the same, and any value that is an instance of the property type is a match:
[name for name, value in vars(MyClass).items() if isinstance(value, property)]
Demo:
>>> class MyClass(object):
... #property
... def foo(self):
... pass
... #property
... def bar(self):
... pass
...
>>> vars(MyClass)
dict_proxy({'__module__': '__main__', 'bar': <property object at 0x1006620a8>, '__dict__': <attribute '__dict__' of 'MyClass' objects>, 'foo': <property object at 0x100662050>, '__weakref__': <attribute '__weakref__' of 'MyClass' objects>, '__doc__': None})
>>> [name for name, value in vars(MyClass).items() if isinstance(value, property)]
['bar', 'foo']
Note that this will include anything that used property() directly (which is what a decorator does, really), and that the order of the names is arbitrary (as dictionaries have no set order).

Can __setattr__() can be defined in a class with __slots__?

Say I have a class which defines __slots__:
class Foo(object):
__slots__ = ['x']
def __init__(self, x=1):
self.x = x
# will the following work?
def __setattr__(self, key, value):
if key == 'x':
object.__setattr__(self, name, -value) # Haha - let's set to minus x
Can I define __setattr__() for it?
Since Foo has no __dict__, what will it update?
All your code does, apart from negate the value, is call the parent class __setattr__, which is exactly what would happen without your __setattr__ method. So the short answer is: Sure you can define a __setattr__.
What you cannot do is redefine __setattr__ to use self.__dict__, because instances of a class with slots do not have a __dict__ attribute. But such instances do have a self.x attribute, it's contents are just not stored in a dictionary on the instance.
Instead, slot values are stored in the same location a __dict__ instance dictionary would otherwise be stored; on the object heap. Space is reserved for len(__slots__) references, and descriptors on the class access these references on your behalf.
So, in a __setattr__ hook, you can just call those descriptors directly instead:
def __setattr__(self, key, value):
if key == 'x':
Foo.__dict__[key].__set__(self, -value)
Interesting detour: yes, on classes without a __slots__ attribute, there is a descriptor that would give you access to the __dict__ object of instances:
>>> class Bar(object): pass
...
>>> Bar.__dict__['__dict__']
<attribute '__dict__' of 'Bar' objects>
>>> Bar.__dict__['__dict__'].__get__(Bar(), Bar)
{}
which is how normal instances can look up self.__dict__. Which makes you wonder where the Bar.__dict__ object is found. In Python, it is turtles all the way down, you'd look that object up on the type object of course:
>>> type.__dict__['__dict__']
<attribute '__dict__' of 'type' objects>
>>> type.__dict__['__dict__'].__get__(Bar, type)
dict_proxy({'__dict__': <attribute '__dict__' of 'Bar' objects>, '__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Bar' objects>, '__doc__': None})

Why __get__ method is not called for instance attribute?

There is this code:
class A:
def __init__(self, x):
self.x = x
def __get__(self, obj, type=None):
print("__get__")
return self.x
def __set__(self, obj, value):
pass
class B:
a_oc = A(44)
def __init__(self, y):
self.a_ob = A(y)
b = B(3)
print(b.a_oc) # class attribute called __get__
print(b.a_ob) # __get__ not called
For class attribute __get__ is called, for instance attribute it is not. Why?
The attribute lookup rule for the new type class(class in 3.x and class inherits from object in 2.x) is, take obj.attr:
if the value is generated by Python, such as __hash__, return it
lookup in obj.__class__.__dict__, if it exists and there exists __get__, return the result of attr.__get__(obj, obj.__class__), if not, lookup in the parent class recursively.
lookup in obj.__dict__. If obj is an instance and the attr exists, return it, or next step. Else if the obj is a class, lookup in itself's, its parents' __dict__, if it is a descriptor, return attr.__get__(None, obj.__class__) or the attr itself.
lookup in obj.__class__.__dict__. If attr is a non-data descriptor, return the result of it. Else return the attr itself if it exists.
raise AttributeError
See you class:
>>> b.__class__
<class 'des.B'>
>>> b.__class__.__dict__
mappingproxy({'__init__': <function B.__init__ at 0x7f2dacb4e290>, '__doc__': None, '__weakref__': <attribute '__weakref__' of 'B' objects>, '__dict__': <attribute '__dict__' of 'B' objects>, 'a_oc': <des.A object at 0x7f2dacb5de50>, '__module__': 'des', '__qualname__': 'B'})
>>>
>>> b.__dict__
{'a_ob': <des.A object at 0x7f2dacb5df10>}
>>>
b.a_oc fits step 2 and b.a_ob fits step3. I put your code in module des.

Obtaining object reference for a method using getattr

Say, I have the following class called Test with a method called start
>>> class Test:
... def __init__(self, *args, **kwargs):
... pass
... def start(self):
... pass
...
Now, I have a standalone independent function called func
>>> def func():
... print 'this is a func and not a method!!!'
...
>>>
[1]
Now, t.start is a method of an instance of __main__.Test which belong to 0xb769678c
>>> t = Test()
>>> t.start
<bound method Test.start of <__main__.Test instance at 0xb769678c>>
>>>
[2]
func is a function which belong to the location 0xb767ec6c
>>> func
<function func at 0xb767ec6c>
>>>
Now, we can extract the __module__ from t.start and func by using builtin __module__. Not surprisingly, func and t.start belong to the same module i.e. __main__
>>> func.__module__
'__main__'
>>> t.__module__
'__main__'
>>>
[3]
Now, lets store __module__ for t.start in a variable obj
>>> obj = __import__(t.start.__module__)
>>> obj
<module '__main__' (built-in)>
>>>
Now, I use getattr() to get the func handle <function func at 0xb767ec6c> for function func as follows and the output of getattr() is the identical to [2]
>>> print getattr(obj, 'func')
<function func at 0xb767ec6c>
>>>
>>> print getattr(__import__('__main__'), 'func')
<function func at 0xb767ec6c>
>>>
Question:
How do I use getattr() and the module name [3] to get the handle of Test.start [1] which should be <bound method Test.start of <__main__.Test instance at 0xb769678c>>
When I tried using getattr() on 't.start' I got the following Traceback
>>> print getattr(obj, 'Test.start')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Test.start'
>>>
>>>
>>> print getattr(__import__('__main__'), 'Test.start')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'Test.start'
>>>
In other words, I have two data with me. They are
__import__('__main__')
The sting 'Test.start'
Now, how do I get the handle for t.start (note the instance here) which should be <bound method Test.start of <__main__.Test instance at 0xb769678c>>
I'm not sure if I understand your question(s), but I think this does what you want:
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
def func():
print('this is a func and not a method!!!')
t = Test()
module = __import__(t.start.__module__)
print(vars(module)['Test'].start)
print(vars(module)['func'])
print(vars(module)['t'].start)
(Python 3) output:
<function Test.start at 0x00E52460>
<function func at 0x00E524F0>
<bound method Test.start of <__main__.Test object at 0x008DF670>>
obj = __import__(t.start.__module__)
test_class = getattr(obj, 'Test')
print getattr(test_class, 'start')
I'm not sure if you need it straight from the module (or even if that is possible) :/
You could also use:
obj = __import__(t.start.__module__)
print obj.__dict__["Test"].__dict__["start"]
but you asked for getattr() so...
I wondered why you wrote obj = __import__(t.start.__module__)
I think it's to hold a name for the main module, in order to have the possibility to obtain the objects in the module's namespace as attributes of the module thanks to the getattr( ) function.
I inform you that you don't have to do this trick.
globals( ) is a dictionary that represents the global namespace of the main space.
Then you can write, for example, globals()["func"] to obtain the object func
I also inform you that there is another way than with getattr(N,"xyz") to obtain an object xyz in the namespace of the object N thanks to its name xyz ,
it's by the __dict__ method:
N.__dict__ gives access to the namespace of the object N
I wonder if your problem doesn't lies in a subtlety of Python that induced you in an error.
In your question, at a place you wrote t.__module__ and at another place you wrote t.start.__module__ .
For the two cases, the result is the same and equal to "__main__"
However,
1) t has no attribute of name __module__
2) t has even no attribute of name start !
If you print t.__dict__ you'll see the result is { } !
start isn't really belonging to the namespace of the instance t because it belongs in fact to the namespace of Test
The following code proves these affirmations:
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
y = Test()
y.ku = 102
print 'y.__dict__',y.__dict__
print 'Test.__dict__',Test.__dict__
result
y.__dict__ {'ku': 102}
Test.__dict__ {'start': <function start at 0x011E11B0>,
'__module__': '__main__',
'__doc__': None,
'__init__': <function __init__ at 0x011E1170>}
.
The reason why the expressions t.__module__ and t.start.__module__ give answers anyway is explained by this citation:
A class instance has a namespace implemented as a dictionary which is
the first place in which attribute references are searched.
When an
attribute is not found there, and the instance’s class has an
attribute by that name, the search continues with the class
attributes.
http://docs.python.org/2/reference/datamodel.html#index-55
Hence:
1) t has no attribute of name __module__ then Python searches for it in the class of t
2) t has no attribute of name start then Python searches for it in the class of t
.
Well, so, Python goes to the class of t to find the values of t.__module__ and t.start.__module__
This mechanism, described by the above citation, can be observed with the following code:
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
t = Test()
print 'getattr(t,"start")'
print getattr(t,"start")
# result is
getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DF288>>
I mean that Python answers that the attribute of t whose name is "start" is Test.start , not t.start !
.
Thereby, from the fact that t.start.__module__ is "__main__", it seems to me that you may have believed that t.start is belonging to the module namespace, and hence you should be able to write something similar to getattr(obj,"func") to obtain the object start
But it is false.
You can't find the method start (I write the METHOD) in the global namespace = namespace of the module, since it is in the namespace of Test. You must attain it, as a method, through the instance or the class or through the class itself.
One more thing.
I precised : the METHOD, because I believe that the method t.start is based on a FUNCTION that is something different from it and that lies in the module's namespace. In reality, a method is a wrapper of pointers pointing to an instance and to this global namespace's function:
If you still don’t understand how methods work, a look at the
implementation can perhaps clarify matters. When an instance attribute
is referenced that isn’t a data attribute, its class is searched. If
the name denotes a valid class attribute that is a function object, a
method object is created by packing (pointers to) the instance object
and the function object just found together in an abstract object:
this is the method object. When the method object is called with an
argument list, a new argument list is constructed from the instance
object and the argument list, and the function object is called with
this new argument list.
http://docs.python.org/2/tutorial/classes.html#method-objects
Well what I want to underline is that it seems a function (not a method) exists somewhere, on which a method is based.
What I believe is that this function lies in the module namespace and that it's why Test.__dict__["start"]
gives
<function start at 0x011E40F0>
while
getattr(Test,"start")
and getattr(t,"start")
give
<unbound method Test.start>
and <bound method Test.start of <__main__.Test instance at 0x011DF530>>
without localizing the bound and unbound methods.
So, in my opinion, as far as I have correctly understood the doc (which is not explaining these points very well, I find, by the way) a method is a wrapper, and is based on a real function that lies in the module namespace, and that's why t.start.__module__ and Test.start.__module__ are "__main__"
It may seem a little weird that there exists a function in the module namespace that doesn't appear among the attributes of the module when we print them with globals() :
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
def func():
print 'this is a func and not a method!!!'
t = Test()
print '* globals()["func"]'
print globals()["func"]
print id(globals()["func"])
print "===================================="
print '* Test.__dict__["start"]'
print Test.__dict__["start"]
print id(Test.__dict__["start"])
print '----------------------------------------------'
print '* getattr(Test,"start")'
print getattr(Test,"start")
print id(getattr(Test,"start"))
print '----------------------------------------------'
print '* getattr(t,"start")'
print getattr(t,"start")
print id(getattr(t,"start"))
print "===================================="
print globals()
result
* globals()["func"]
<function func at 0x011C27B0>
18622384
====================================
* Test.__dict__["start"]
<function start at 0x011DEFB0>
18739120
----------------------------------------------
* getattr(Test,"start")
<unbound method Test.start>
18725304
----------------------------------------------
* getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DF418>>
18725304
{'__builtins__': <module '__builtin__' (built-in)>,
'__package__': None,
't': <__main__.Test instance at 0x011DF418>,
'func': <function func at 0x011C27B0>,
'Test': <class __main__.Test at 0x011DC538>,
'__name__': '__main__',
'__doc__': None}
But the fact is that we indeed see a Test.__dict__["start"] function whose address 18739120 is different from the bound and unbound methods address 18725304.
Moreover, I don't see which other explanation could explain the totality of the facts exposed.
There's in fact nothing weird in the fact that a function that didn't receive any assigned name doesn't appear in the module namespace.
It is an internal function, necessary to Python, not at the disposal of the programmer, that's all.
Concerning func, using all the methods you employed:
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
def func():
print 'this is a func and not a method!!!'
t = Test()
print 'func --->',func
print id(func)
print '\nobj = __import__(t.start.__module__) done\n'
obj = __import__(t.start.__module__)
print '* globals()["func"]'
print globals()["func"]
print id(globals()["func"])
print '* obj.__dict__["func"]'
print obj.__dict__["func"]
print "* getattr(obj, 'func')"
print getattr(obj, 'func')
print "* getattr(__import__('__main__'), 'func')"
print getattr(__import__('__main__'), 'func')
result
func ---> <function func at 0x011C2470>
18621552
obj = __import__(t.start.__module__) done
* globals()["func"]
<function func at 0x011C2470> # <== address in hexadecimal
18621552 # <== address in decimal
* obj.__dict__["func"]
<function func at 0x011C2470>
* getattr(obj, 'func')
<function func at 0x011C2470>
* getattr(__import__('__main__'), 'func')
<function func at 0x011C2470>
.
Now taking apart your methods using obj :
class Test:
def __init__(self, *args, **kwargs):
pass
def start(self):
pass
print 'Test.start -->',Test.start
print id(Test.start)
print '----------------------------------------------'
print '* Test.__dict__["start"]'
print Test.__dict__["start"]
print id(Test.__dict__["start"])
print '* getattr(Test,"start")'
print getattr(Test,"start")
print id(getattr(Test,"start"))
print '\n'
print 't.start -->',t.start
print id(t.start)
print '----------------------------------------------'
print '* t.__dict__["start"]'
try:
print t.__dict__["start"]
print id(t.__dict__["start"])
except KeyError as e:
print 'KeyError :',e
print '* getattr(t,"start")'
print getattr(t,"start")
print id(getattr(t,"start"))
result
Test.start --> <unbound method Test.start>
18725264
----------------------------------------------
* Test.__dict__["start"]
<function start at 0x011E40F0>
18759920
* getattr(Test,"start")
<unbound method Test.start>
18725264
t.start --> <bound method Test.start of <__main__.Test instance at 0x011DB940>>
18725264
----------------------------------------------
* t.__dict__["start"]
KeyError : 'start'
* getattr(t,"start")
<bound method Test.start of <__main__.Test instance at 0x011DB940>>
18725264
Until now, I had seldom used getattr( ).
I realize on these results that getattr( ) gives results in a specific manner: the attribute start is described as a method, bound or unbound according if it is attained through an instance or through a class.
However, only __dict__ gives precise information on the real attributes of an object.
Thus, we see that start isn't really in the namespace of the instance, but only in the namespace of the class.
It is described as being a function when it is as element of the namespace Test.__dict__ and as being a method when given as an attribute through getattr( ). There are no addresses given in this last case.
The use of the vars( ) function gives the same results.

Categories