在 python 中使用 @属性 的正确方法是什么
What is the proper way to use @property in python
我有以下代码,Dog 和 Cat class 继承自 Animal class。 Person class 正在使用 Dog 和 Cat class 作为其实例。我想要 return 实例名称的函数,例如 john 实例的字符串 "get the name xxx" 和 john 的 属性 狗,猫的名字。我尝试在 Animal class 和 Person 下编写 属性 namegetter 并且我可以得到我想要的。但是,是否有适当的方法来做到这一点?所以如果我有几个 class 之类的人,我不需要在 class
下写相同的 属性
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
根据评论,我猜您想避免两次定义相同的方法。
您可以使用 Mixins(在复杂的层次结构中)或只是另一个基础 class 来做到这一点。至于你是否可以避免写@property
的问题:你可以不写,但是你必须在你的方法后面写大括号namegetter()
。
使用基数的示例 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
在更复杂的示例中,您可以改用 Mixin,这基本上会改变您在 class 定义中从它继承的方式:
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
这个名字听起来好像你需要它。下面,我为您定义了一个带有 getters 和 setters 的版本,允许您使用可选变量 {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 将根据您自动访问 属性 的方式 select 正确的方法。
然而,上述解决方案不再使用装饰器,这可能会降低代码的可读性。带有装饰器的版本是这个。请注意方法 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
我有以下代码,Dog 和 Cat class 继承自 Animal class。 Person class 正在使用 Dog 和 Cat class 作为其实例。我想要 return 实例名称的函数,例如 john 实例的字符串 "get the name xxx" 和 john 的 属性 狗,猫的名字。我尝试在 Animal class 和 Person 下编写 属性 namegetter 并且我可以得到我想要的。但是,是否有适当的方法来做到这一点?所以如果我有几个 class 之类的人,我不需要在 class
下写相同的 属性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
根据评论,我猜您想避免两次定义相同的方法。
您可以使用 Mixins(在复杂的层次结构中)或只是另一个基础 class 来做到这一点。至于你是否可以避免写@property
的问题:你可以不写,但是你必须在你的方法后面写大括号namegetter()
。
使用基数的示例 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
在更复杂的示例中,您可以改用 Mixin,这基本上会改变您在 class 定义中从它继承的方式:
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
这个名字听起来好像你需要它。下面,我为您定义了一个带有 getters 和 setters 的版本,允许您使用可选变量 {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 将根据您自动访问 属性 的方式 select 正确的方法。
然而,上述解决方案不再使用装饰器,这可能会降低代码的可读性。带有装饰器的版本是这个。请注意方法 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