我有以下代码,Dog和Cat类继承自Animal类。 Person类使用Dog和Cat类作为其实例。我想有函数返回实例的名称,如字符串“获取名称xxx”为john实例和john的属性狗,猫的名字。我试图在Animal类和Person下修改属性 namegetter ,我可以得到我想要的东西。但是,如果有合适的方法可以做到这一点?所以,如果我有像Person这样的几个类,我不需要在类
下编写相同的属性class Animal(object):
def __init__(self, name):
self.name = name
@property
def namegetter(self):
return 'get the name of {}'.format(self.name)
class Cat(Animal):
def __init__(self, food, name):
super().__init__(name)
self.food = food
self.sound = 'meow'
class Dog(Animal):
def __init__(self, food, name):
super().__init__(name)
self.food = food
self.space = 'park'
class Person(object):
def __init__(self, name):
self.name = name
self.dog = Dog("dog's food", "dog's name" )
self.cat = Cat("dog's food", "cat's name")
@property
def namegetter(self):
return 'get the name of {}'.format(self.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
答案 0 :(得分:1)
根据评论,我想你想避免两次定义相同的方法。
您可以使用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
在评论中,您询问了有人想写信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
我分开了吸气剂和放大器将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