osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Extending property using a Subclass - single method - why Super(Baz, Baz).name.__set__ ?


Veek M wrote:

> you've misunderstood my question

There were a lot of foobars bazzing in my head, but at least I tried ;)

> , let me try again:
> 
> So this is a simple descriptor class and as you can see, dunder-set needs
> 3 args: the descriptor CONTAINER/Bar-instance is the first arg, then a
> reference to the using instance/Foo-instance
> 
> class Bar(object):
>     
>     def __set__(self, instance, value):
>         #b-instance of Bar, f-instance of Foo, value
>         print(self, instance, value)
>         
>         
> class Foo(object):
>     b = Bar()
>     
> f = Foo()
> print(f)
> f.b = 10
> 
> 1. Now when we create/use @property..
> what is the first and second argument to dunder-set
> 
> (my guess is, the @property is the first arg and the second arg is 'Foo'
> IF you do
> 
> class Foo(object):
>    @property
>    def whatever..
> 
> Am I right? Is there a way to check?

@foo
def bar(...):
...

is an alternative way to writing

def bar(...):
...
bar = foo(bar)

so you can just add conforming __init__() and __get__() methods to your Bar 
descriptor and see for yourself:

>> class Bar:
...     def __init__(self, fget): pass
...     def __set__(*args): print(args)
...     def __get__(*args): pass
... 
>>> class Foo:
...     @Bar
...     def whatever(self): pass
... 
>>> foo = Foo()
>>> foo.whatever = 42
(<__main__.Bar object at 0x7f92b55d70b8>, <__main__.Foo object at 
0x7f92b55d70f0>, 42)

> 2. The Class Bar/descriptor acts a wrapper/protector for some sekret _var
> and therefore it gets all the data needed to make a judgement call.. that
> is, it's own name/instance-ref and the using class/instance-name-ref
> 
> Note that he's receiving instance-references
> 
> therefore when I start sub-classing a property why does he then switch to
> class-references/class-variables

If you were subclassing a property you'd do

class my_property(property):
   # tinker with __get/set/whatnot__

When you want to wrap a property defined in a superclass the property 
instance is not part of the class hierarchy that you are interested in. 
Instead of calling super() it has to figure out the base class of its "host" 
class manually.

If you want overridable properties you can devise a way to look up the 
method:

>>> class Foo:
...     @property
...     def name(self): return self.get_name()
...     @name.setter
...     def name(self, value): self.set_name(value)
...     def set_name(self, value): self._name = value
...     def get_name(self): return self._name
... 
>>> class Bar(Foo):
...     def set_name(self, value):
...         print("setting")
...         super().set_name(value)
...     def get_name(self):
...         print("getting")
...         return super().get_name()
... 
>>> foo = Foo()
>>> foo.name = "bar"
>>> foo.name
'bar'
>>> bar = Bar()
>>> bar.name = "baz"
setting
>>> bar.name
getting
'baz'