基于 cmets,我猜你想避免两次定义相同的方法。
您可以使用 Mixins(在复杂的层次结构中)或仅使用另一个基类来做到这一点。至于你是否可以避免写@property的问题:你可以不写,但是你必须在你的方法后面写大括号namegetter()。
使用基类的示例:
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
在一个更复杂的例子中,你可以使用 Mixin,这基本上会改变你在类定义中从它继承的方式:
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
二传手
在 cmets 中,您询问如果有人想写信给 namegetter 怎么办。上面,我只定义了只读访问,因为namegetter 这个名字在我听来好像你需要它。下面,我为您定义了一个带有 getter 和 setter 的版本,它允许您使用可选变量 {name} 按需替换来设置格式字符串:
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
我将 getter 和 setter 拆分为两个方法,并将它们作为 namegetter 属性提供。 Python 会根据你自动访问属性的方式选择正确的方法。
然而,上述解决方案不再使用装饰器,这可能会降低代码的可读性。带有装饰器的版本是这个。请注意,namegetter 方法使用不同的装饰器定义了两次:
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