Using Python property() inside a method - python

Assuming you know about Python builtin property: http://docs.python.org/library/functions.html#property
I want to re-set a object property in this way but, I need to do it inside a method to be able to pass to it some arguments, currently all the web examples of property() are defining the property outside the methods, and trying the obvious...
def alpha(self, beta):
self.x = property(beta)
...seems not to work, I'm glad if you can show me my concept error or other alternative solutions without subclassing the code (actually my code is already over-subclassed) or using decorators (this is the solution I'll use if there is no other).
Thanks.

Properties work using the descriptor protocol, which only works on attributes of a class object. The property object has to be stored in a class attribute. You can't "override" it on a per-instance basis.
You can, of course, provide a property on the class that gets an instance attribute or falls back to some default:
class C(object):
_default_x = 5
_x = None
#property
def x(self):
return self._x or self._default_x
def alpha(self, beta):
self._x = beta

In this case all you need to do in your alpha() is self.x = beta. Use property when you want to implement getters and setters for an attribute, for example:
class Foo(object):
#property
def foo(self):
return self._dblookup('foo')
#foo.setter
def foo(self, value):
self._dbwrite('foo', value)
And then be able to do
f = Foo()
f.foo
f.foo = bar

Related

property.setter and inheritance

I have two classes, BaseClass and Subclass (where Subclass is a subclass of BaseClass). In each of these classes, I have a property 'foo' which I'd like to be able to get and set. The way in which 'foo' is set is independent of the class - it's done the same way in both BaseClass and Subclass. However, the way in which we 'get' the property 'foo' is dependent on the class. I would thus like a way to define my 'setter' on BaseClass and have it inherit to Subclass in such a way that it's compatible with the class-dependent implementations of the 'getter' in both Subclass and BaseClass.
My first instinct was to use python #property and #property.setter. I quickly ran into issues:
class BaseClass(object):
def __init__(self):
self._foo = None
#property
def foo(self):
print 'BaseClass'
#foo.setter
def foo(self, val):
self._foo = val
class Subclass(BaseClass):
#property
def foo(self):
print 'Subclass'
My naive hope was that the foo.setter would be inherited into Subclass and that it would be compatible with the Subclass implementation of the foo property. However:
b = BaseClass()
s = Subclass()
b.foo
BaseClass
s.foo
Subclass
b.foo = 'BaseClass!'
s.foo = 'Subclass!'
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: can't set attribute
I believe what is happening here is that the '#foo.setter' is being bound to the BaseClass namespace at compile time, and thus is not available to Subclass (although I could be wrong on this point).
Can anyone tell me a neat way of achieving what I want here? It doesn't necessarily need to use python property builtin, but that would be nice.
There are some interesting things going on here. BaseClass.foo is an object, and the lines
#foo.setter
def foo(self, val):
self._foo = val
return a modified copy of that object.
In the SubClass, you are redefining this object by recreating the property and so you will need to write a new setter or follow Aran-Fey’s answer.
I found a similar question that might also help with understanding this idea.
You can use #BaseClass.foo.getter to create a copy of the property with a different getter:
class Subclass(BaseClass):
#BaseClass.foo.getter
def foo(self):
print('Subclass')
See the property documentation for details.

Methods in python are associated with the class. what does a function associated directly with the instance imply?

I know that in python, methods are associated the class and not the instance but they accept the instance as their first argument so as to access it. but, one can still define a function and tie it to an instance directly. What does this imply? and can this function somehow access the instance?
class TestClass:
def __init__(self, a):
self.a = a
def method1(self):
return self.a
my_obj = TestClass(12)
print(my_obj.method1()) // 12
Python also allows this:
class TestClass:
def __init__(self, a):
self.a = a
my_obj = TestClass(12)
def method1_defined_outside(self):
return self.a
TestClass.method1 = method1_defined_outside
print(my_obj.method1()) // 12
The two snippets above mean the same thing.
but python also allows this:
class TestCase:
def __init__(self, a):
self.a = a
my_obj = TestCase(12)
def method1_defined_outside(self):
return self.a
my_obj.method1 = method1_defined_outside
print(my_obj.method1()) // this throws an error stating the method1 is missing one postional argument(s), so clearly self does not automatically equate to the object
difference between the second and the third snippet is that the method defined outside is tied to the instance in latter, and to the class in the former.
When you access a method through an instance, but the method lives on the class, accessing the method actually creates a method wrapper. This wrapper knows what instance the method was called on, and passes it through to the actual function as the first argument (named, by convention, self). The mechanism behind this is the descriptor protocol and it's how properties work, too.
When you put the method directly on the instance, none of that applies and it's just a function that you access by way of the instance. It doesn't get self.
Now, you can create a method wrapper by manually invoking the descriptor, and set the resulting bound method on the instance.
my_obj.method1 = method1_defined_outside.__get__(my_obj)
Now my_obj.method1() passes my_obj as self.
The situations in which you'd want to set a method on an instance like this are fairly rare, though.
One way you could force sending the instance as self is by using the functools.partial wrapper as:
from functools import partial
class A:
def __init__(self):
self.x = 10
a1 = A()
def do_external(self):
print("EXTERNAL", self.x)
a1.doext = partial(do_external, a1)
a1.doext()
which will yield in the console:
EXTERNAL 10

get source code for method with #property decorator python

Suppose I have a class MyClass that has a property created with the #property decorator, like this:
class MyClass(object):
#property
def foo(self):
if whatever:
return True
else:
return False
Suppose I want to use the python inspect module to get the source code that defines the property. I know how to do this for methods (inspect.getsource) but I don't know how to do this for property objects. Anyone know how to do this?
Access the underlying getter function through the property's fget attribute:
print(inspect.getsource(MyClass.foo.fget))
If it has a setter or deleter, you can access those through fset and fdel:
print(inspect.getsource(MyClass.foo.fset))
print(inspect.getsource(MyClass.foo.fdel))

How to let inheritance take precedence over class properties when using a metaclass?

I have posted a similar question before but I interpreted my problem wrong, so I flagged it for deletion and come forth with the new and correct problem.
My general goal is the following: I want to have a property on a class, so I implement it on a metaclass using a property as suggested on my question Implementing a class property that preserves the docstring. Additionally, I want users to be able to subclass the base class and override this property with static values. The thing here is that if the user does not provide an attribute, I want to calculate a sensible default and since all configuration is done at the class level, I need a property at the class level.
A basic example will show this:
class Meta(type):
#property
def test(self):
return "Meta"
class Test(object):
__metaclass__ = Meta
class TestSub(Test):
test = "TestSub"
class TestSubWithout(Test):
pass
print(TestSub.test, TestSubWithout.test)
Here is what it prints:
('Meta', 'Meta')
And what I want it to print:
('TestSub', 'Meta')
Essentially, on TestSub the user overrides the test attribute himself. Now, TestSub is the correct output, since the user provided it. In the case of TestSubWithout, the user instead did not provide the attribute and so the default should be calculated (of course, the real calculation has more than just a static return, this is just to show it).
I know what happens here: First the attribute test is assigned to TestSub and then the metaclass overrides it. But I don't know how to prevent it in a clean and pythonic way.
A property is a "data descriptor", which means that it takes precedence in the attribute search path over values stored in a instance dictionary (or for a class, the instance dictionaries of the other classes in its MRO).
Instead, write your own non-data descriptor that works like property:
class NonDataProperty(object):
def __init__(self, fget):
self.fget = fget
def __get__(self, obj, type):
if obj:
return self.fget(obj)
else:
return self
# don't define a __set__ method!
Here's a test of it:
class MyMeta(type):
#NonDataProperty
def x(self):
return "foo"
class Foo(metaclass=MyMeta):
pass # does not override x
class Bar(metaclass=MyMeta):
x = "bar" # does override x
class Baz:
x = "baz"
class Baz_with_meta(Baz, metaclass=MyMeta):
pass # inherited x value will take precedence over non-data descriptor
print(Foo.x) # prints "foo"
print(Bar.x) # prints "bar"
print(Baz_with_meta.x) # prints "baz"
I cleanest way I could come up with is creating a subclass of property that handles this case:
class meta_property(property):
def __init__(self, fget, fset=None, fdel=None, doc=None):
self.key = fget.__name__
super(meta_property, self).__init__(fget, fset, fdel, doc)
def __get__(self, obj, type_):
if self.key in obj.__dict__:
return obj.__dict__[self.key]
else:
return super(meta_property, self).__get__(obj, type_)
This handles the case by storing the name of the function and returning the overridden value if it is present. This seems like an okayish solution but I am open to more advanced suggestions.

How to call subclass methods in a superclass in Python

I want to know how to call subclass methods in the superclass.
I believe this is a pattern used often.
class A(object):
def x(self):
self.y()
def y(self):
print('default behavior')
class B(A):
def y(self):
print('Child B behavior')
class C(A):
def z(self):
pass
>>>B().x()
Child B behavior
>>>C().x()
default behavior
It is sort of like an abstract class, but provides default behavior. Can't remember the name of the pattern off the top of my head though.
The point behind a subclass is that it extends and alters the behaviour of the superclass. The superclass can't know how a subclass will extend it.
Edit: But it is well possible that the superclass knows, that the subclass will extend it. Not sure, if this is good design, though.
Here's what I've just tried:
class A(object):
def x(self):
print self.y()
class B(A):
def y(self):
return 1
>>> B().x()
1
So unless you had some specific problem, just call a method from the subclass in the base class and it should just work.
This is a very broad question. As you don't provide example code, I'll just show the easiest example:
class A(object):
def meth1(self, a):
self.meth2(a, a*a)
class B(A):
def meth2(self, a, b):
return b / a
b = B()
b.meth1(10)
I think this is related to using abstract methods. The parent class defines methods that the subclass should implement and the parent class knows that these methods will be implemented. Similar structures exist for example in Java.
Using these in Python is discussed here well: Abstract methods in Python

Categories

Resources