Why __get__ method is not called for instance attribute? - python

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.

Related

python: print non inherited methods

I am trying to print a list of the methods that have not been inherited from other classes (e.g.., not inheritted from object or another base class). As an example say I have the following class:
class Point:
def __init__(self, x, y):
self.__x=x
self.__y=y
calling this method should print:
[__init__] without __str__ (inheritted from object).
I've tried:
dir(Point)
but the problem is that it includes already inheritted methods.
To print the non-inherited attributes of an object, such as a class object, use vars which checks the __dict__ of that object:
In [1]: class Point:
...: def __init__(self, x, y):
...: self.__x=x
...: self.__y=y
...:
In [2]: vars(Point)
Out[2]:
mappingproxy({'__dict__': <attribute '__dict__' of 'Point' objects>,
'__doc__': None,
'__init__': <function __main__.Point.__init__>,
'__module__': '__main__',
'__weakref__': <attribute '__weakref__' of 'Point' objects>})
Since a method is merely a callable object in the class, you can check for it using something to the effect of:
In [3]: for k, v in vars(Point).items():
...: if callable(v):
...: print(k)
...:
__init__
You can look into the __dict__ of the class itself:
import types
def list_methods(t):
for name, item in t.__dict__.items():
if isinstance(item, types.FunctionType):
print(name)
t is a class object here, not an instance of a class. If you want to operate on instances, replace t.__dict__.items() with type(t).__dict__.items() in the loop.

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).

Can I create an object that receives arbitrary method invocation in 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',)”

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})

Categories