简体   繁体   中英

Can I use another class's property without extending that class?

Breif:

I have two classes that contain some pairs of identical property blocks. These classes share a common ancestor, but also have siblings that do not need these properties.

I would like to not duplicate the property code blocks.

If I were using Getters:

With Getter's my approach would be to call the authoritative method in another class:

# in ConcreteFooz.baz_per_bar:
def baz_per_bar(self):
    return ConcreteFoo.baz_per_bar(self)

But I'm not using getters ,

As @properties seem far more suitable for my needs. When I tried:

# in ConcreteFooz.baz_per_bar:
def baz_per_bar(self):
    return ConcreteFoo.baz_per_bar(self)

I get back:

*** TypeError: 'property' object is not callable

So;

Can I use another class's property without extending that class?


Example Code

So that we refere to things commonly:

import itertools

class MyBaseClass(object):
    pass

class ConcreteFoo(MyBaseClass):
    @property
    def baz_per_bar(self):
        """Returns as dict of {baz: list bar}"""
        # do baz lookup
        # do bar lookup
        # associcate and return
        return my_baz_per_bar

    @property
    def baz_chain(self):
        """Flattens baz_per_bar into baz's"""
        return itertools.chain(*self._baz_chain.values())

class ConcreteFooz(MyBaseClass):
    @property
    def baz_per_bar(self):
        """Returns as dict of {baz: list bar}"""
        # do baz lookup
        # do bar lookup
        # associcate and return
        return my_baz_per_bar

    @property
    def baz_chain(self):
        """Flattens baz_per_bar into baz's"""
        return itertools.chain(*self._baz_chain.values())

class ConcreteJaz(MyBaseClass):
    pass
    # Does not need property lookup

I'm not quite sure. Does mixin will suit your need?

import itertools

class MyBaseClass(object):
    pass

class BazMixin():
    @property
    def baz_per_bar(self):
        """Returns as dict of {baz: list bar}"""
        # do baz lookup
        # do bar lookup
        # associcate and return
        return my_baz_per_bar

    @property
    def baz_chain(self):
        """Flattens baz_per_bar into baz's"""
        return itertools.chain(*self._baz_chain.values())


class ConcreteFoo(MyBaseClass, BazMixin):
    pass

class ConcreteFooz(MyBaseClass, BazMixin):
    pass

class ConcreteJaz(MyBaseClass):
    pass
    # Does not need property lookup

Yes, you can use another class's property without extending that class. Consider this program:

import itertools

class MyBaseClass(object):
    pass

class ConcreteFoo(MyBaseClass):
    def __init__(self):
        self.my_baz_per_bar = { 'A' : ['apple', 'aardvark'] }

    @property
    def baz_per_bar(self):
        """Returns as dict of {baz: list bar}"""
        # do baz lookup
        # do bar lookup
        # associcate and return
        return self.my_baz_per_bar

    @property
    def baz_chain(self):
        """Flattens baz_per_bar into baz's"""
        return itertools.chain(*self._baz_chain.values())

class ConcreteFooz(MyBaseClass):
    def __init__(self):
        self.my_baz_per_bar = { 'Z' : ['zero', 'zebra'] }

    baz_per_bar = ConcreteFoo.baz_per_bar
    baz_chain = ConcreteFoo.baz_chain

class ConcreteJaz(MyBaseClass):
    pass
    # Does not need property lookup

print ConcreteFoo().baz_per_bar
print ConcreteFooz().baz_per_bar

Alternatively, consider this fragment:

    @property
    def baz_per_bar(self):
        return ConcreteFoo.baz_per_bar.fget(self)

Note that I did modify ConcreteFoo from your example, but only to fix the NameError in it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM