2

I have a set of classes which can contain an optional name attribute. The reason is that the classes will get a default name if the attribute is set, but individual classes can still have a custom name if needed.

What I want is to be able to get the name attribute from both the class (without any class instance) and from instances of a class.

class NameMixin(object):
    def _get_name(self):
        if getattr(self, '_name', ''):
            return self._name
        else:
            return self.__class__.__name__

    def _set_name(self, name):
        self._name = name

    name = property(_get_name, _set_name)

class A(NameMixin):
    name = 'Class A'

class B(NameMixin):
    pass

Here, the class A customizes the name, while class B does not.

>>> a = A()
>>> a.name
'Class A'
>>> A.name
'Class A'

As seen, this works as it should

>>> b = B()
>>> b.name
'B'
>>> B.name
<property object at 0x7fd50a38c578>

This does not work as I want! Getting the name from a specific instance works as it should, but attempting to get the name from the class returns a property object.

Is it possible to get the name directly from a class without jumping through hoops with the property object (which I really can't check for in the place where I need the class-attribute anyway.)

2 Answers 2

1
class NameMixinMeta(type):
    def _get_name(self):
        return getattr(self, '_name', self.__name__)

    def _set_name(self, name):
        self._name = name

    name = property(_get_name, _set_name)

class NameMixin(object):
    __metaclass__ = NameMixinMeta
    def _get_name(self):
        return getattr(self, '_name', self.__class__.__name__)

    def _set_name(self, name):
        self._name = name

    name = property(_get_name, _set_name)

class A(NameMixin):
    _name = 'Class A'

class B(NameMixin):
    pass
Sign up to request clarification or add additional context in comments.

1 Comment

Hmm... Almost works... A.name returns 'A' which is not quite right. However, your use of a metaclass got me thinking, and it seems like I got a solution that works. I will just skip the properties and mixins, and in the metaclass I will override __new__ and add 'name' to the dictionary if it's not there.
0

I am not sure if your NameMixin class is at work here.

In the first case, name is a class property and can be accessed just like you say.

>>> class A():
...     name = 'Class A'
... 
>>> 
>>> a = A()
>>> a.name
'Class A'
>>> A.name
'Class A'
>>> 

In the second case the NameMixin class has the effect of returning the property as you suggested.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.