簡體   English   中英

在python中使用@property的正確方法是什么

[英]What is the proper way to use @property in python

我有以下代碼,Dog和Cat類是從Animal類繼承的。 而Person類使用Dog和Cat類作為其實例。 我想有一個函數來返回實例名稱,例如字符串“獲取名稱xxx”作為john實例和john的屬性dog(貓的名字)。 我已經嘗試在Animal class和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

根據評論,我想您想避免兩次定義相同的方法。 您可以使用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

我將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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM