Based on the comments, I guess you want to avoid defining the same method twice.
You could do that with Mixins (in a complex hierarchy) or just another base class. As for your question on whether or not you can avoid writing @property
: You can leave it out, but then you would have to write braces behind your method namegetter()
.
Example using a base class:
class NamedEntity(object):
def __init__(self, name):
self.name = name
@property
def namegetter(self):
return 'get the name of {}'.format(self.name)
class Animal(NamedEntity):
pass
class Cat(Animal):
def __init__(self, food, name):
super(Cat, self).__init__(name)
self.food = food
self.sound = 'meow'
class Dog(Animal):
def __init__(self, food, name):
super(Dog, self).__init__(name)
self.food = food
self.space = 'park'
class Person(NamedEntity):
def __init__(self, name):
super(Person, self).__init__(name)
self.dog = Dog("dog's food", "dog's name" )
self.cat = Cat("dog's food", "cat's name")
if __name__ == '__main__':
john = Person('john')
print(john.name) #john
print(john.dog.name) #dog's name
print(john.cat.name) #cat's name
print(john.dog.namegetter) #get the name of dog
print(john.cat.namegetter) #get the name of cat
print(john.namegetter) #get the name of john
In a more complex example, you could use a Mixin instead, this would basically change the way you inherit from it in the class definition:
class NamedEntityMixin(object):
def __init__(self, name):
self.name = name
@property
def namegetter(self):
return 'get the name of {}'.format(self.name)
class Animal(NamedEntityMixin, object):
# Imagine object being another parent class with additional properties and methods
pass
class Cat(Animal):
def __init__(self, food, name):
super(Cat, self).__init__(name)
self.food = food
self.sound = 'meow'
class Dog(Animal):
def __init__(self, food, name):
super(Dog, self).__init__(name)
self.food = food
self.space = 'park'
class Person(NamedEntityMixin, object):
# Imagine object being another parent class with additional properties and methods
def __init__(self, name):
super(Person, self).__init__(name)
self.dog = Dog("dog's food", "dog's name" )
self.cat = Cat("dog's food", "cat's name")
if __name__ == '__main__':
john = Person('john')
print(john.name) #john
print(john.dog.name) #dog's name
print(john.cat.name) #cat's name
print(john.dog.namegetter) #get the name of dog
print(john.cat.namegetter) #get the name of cat
print(john.namegetter) #get the name of john
Setters
In the comments you asked about what if someone wants to write to namegetter
. Above, I only defined readonly access, since the name namegetter
sounded to me as if you need that. Below, I defined you a version with getters and setters that allow you to set the format string with the optional variable {name}
being replaced on demand:
class NamedEntity(object):
def __init__(self, name):
self.name = name
self._namegetter = "get the name of {name}"
def _get_namegetter(self):
return self._namegetter.format(name=self.name)
def _set_namegetter(self, namegetter):
self._namegetter = namegetter
namegetter = property(_get_namegetter, _set_namegetter)
class Animal(NamedEntity):
pass
class Cat(Animal):
def __init__(self, food, name):
super(Cat, self).__init__(name)
self.food = food
self.sound = 'meow'
self.namegetter = 'catnamegetter'
class Dog(Animal):
def __init__(self, food, name):
super(Dog, self).__init__(name)
self.food = food
self.space = 'park'
class Person(NamedEntity):
def __init__(self, name):
super(Person, self).__init__(name)
self.dog = Dog("dog's food", "dog's name" )
self.cat = Cat("dog's food", "cat's name")
if __name__ == '__main__':
john = Person('john')
print(john.name) #john
print(john.dog.name) #dog's name
print(john.cat.name) #cat's name
print(john.dog.namegetter) #get the name of dog
print(john.cat.namegetter) #get the name of cat
print(john.namegetter) #get the name of john
I split up the getter & setter into two methods and made them available as the namegetter
property. Python will select the right method based on how you access the property automatically.
The above solution however does not use decorators anymore, which might make the code less readable. A version with decorators is this one. Please note that the method namegetter
is defined twice with different decorators:
class NamedEntity(object):
def __init__(self, name):
self.name = name
self._namegetter = "get the name of {name}"
@property
def namegetter(self):
return self._namegetter.format(name=self.name)
@namegetter.setter
def namegetter(self, namegetter):
self._namegetter = namegetter
class Animal(NamedEntity):
pass
class Cat(Animal):
def __init__(self, food, name):
super(Cat, self).__init__(name)
self.food = food
self.sound = 'meow'
self.namegetter = 'catnamegetter'
class Dog(Animal):
def __init__(self, food, name):
super(Dog, self).__init__(name)
self.food = food
self.space = 'park'
class Person(NamedEntity):
def __init__(self, name):
super(Person, self).__init__(name)
self.dog = Dog("dog's food", "dog's name" )
self.cat = Cat("dog's food", "cat's name")
if __name__ == '__main__':
john = Person('john')
print(john.name) #john
print(john.dog.name) #dog's name
print(john.cat.name) #cat's name
print(john.dog.namegetter) #get the name of dog
print(john.cat.namegetter) #get the name of cat
print(john.namegetter) #get the name of john