Подтвердить что ты не робот

Какая разница между "свойством" Python и "атрибутом"?

Я вообще путаюсь о различии между "свойством" и "атрибутом" и не могу найти большой ресурс, чтобы детализировать различия.

4b9b3361

Ответ 1

Свойства - это особый вид атрибута. В принципе, когда Python встречает следующий код:

spam = SomeObject()
print(spam.eggs)

он просматривает eggs в spam, а затем проверяет eggs, чтобы увидеть, имеет ли он метод __get__, __set__ или __delete__ & thinsp; — & thinsp; если это так, имущество. Если это свойство, вместо того, чтобы просто вернуть объект eggs (как и для любого другого атрибута), он вызовет метод __get__ (поскольку мы выполняем поиск) и возвращаем все возвращаемые методы.

Дополнительная информация о Модель и дескрипторы данных Python.

Ответ 2

С помощью свойства вы полностью контролируете его методы получения, настройки и удаления, которые у вас отсутствуют (если не использовать оговорки) с атрибутом.

class A(object):
    _x = 0
    '''A._x is an attribute'''

    @property
    def x(self):
        '''
        A.x is a property
        This is the getter method
        '''
        return self._x

    @x.setter
    def x(self, value):
        """
        This is the setter method
        where I can check it not assigned a value < 0
        """
        if value < 0:
            raise ValueError("Must be >= 0")
        self._x = value

>>> a = A()
>>> a._x = -1
>>> a.x = -1
Traceback (most recent call last):
  File "ex.py", line 15, in <module>
    a.x = -1
  File "ex.py", line 9, in x
    raise ValueError("Must be >= 0")
ValueError: Must be >= 0

Ответ 3

В общих терминах свойство и атрибут - одно и то же. Тем не менее, в Python есть декоратор свойств, который обеспечивает доступ к getter/setter к атрибуту (или другим данным).

class MyObject(object):
    # This is a normal attribute
    foo = 1

    @property
    def bar(self):
        return self.foo

    @bar.setter
    def bar(self, value):
        self.foo = value


obj = MyObject()
assert obj.foo == 1
assert obj.bar == obj.foo
obj.bar = 2
assert obj.foo == 2
assert obj.bar == obj.foo

Ответ 4

Свойство позволяет вам получать и устанавливать значения, как и обычные атрибуты, но под ним вызывается метод, переводящий его в getter и setter для вас. На самом деле это просто удобство, чтобы вырезать планку вызова геттеров и сеттеров.

Давайте скажем, например, у вас был класс, который содержал некоторые координаты x и y для чего-то, что вам нужно. Чтобы их установить, вы можете сделать что-то вроде:

myObj.x = 5
myObj.y = 10

Об этом гораздо легче смотреть и думать, чем писать:

myObj.setX(5)
myObj.setY(10)

Проблема в том, что если в один прекрасный день ваш класс изменится так, что вам нужно будет компенсировать ваши x и y некоторой ценностью? Теперь вам нужно будет войти и изменить определение класса и весь код, который его вызывает, что может быть очень трудоемким и подверженным ошибкам. Свойство позволяет использовать прежний синтаксис, предоставляя вам гибкость изменения последнего.

В Python вы можете определить методы getters, seters и delete с помощью функции property. Если вы просто хотите свойство read, есть также декоратор @property, который вы можете добавить выше своего метода.

http://docs.python.org/library/functions.html#property

Ответ 5

Я узнал 2 отличия от сайта Бернд Кляйн, вкратце:

1. Свойство - более удобный способ инкапсуляции данных.

ex: Если у вас есть длина атрибута public объекта, в дальнейшем ваш проект требует, чтобы вы инкапсулировали его, то есть: изменили его на private и предоставили getter и setter = > вам нужно изменить многие из кодов, которые вы написали ранее

#Old codes
obj1.length=obj1.length+obj2.length
#New codes(Using private attibutes and getter and setter)
obj1.set_lenght(obj1.get_length()+obj2.get_length()) #=> this is ugly

Если вы используете @property и @lenght.setter = > вам не нужно менять эти старые коды

2. Свойство может инкапсулировать несколько атрибутов

class Person:
  def __init__(self, name, physic_health, mental_health):
    self.name=name
    self.__physic_health=physic_health #physic_health is real value in range [0, 5.0]
    self.__mental_health=mental_health #mental_health is real value in range [0, 5.0]
  @property
  def condition(self):
    health=self.__physic_health+self.__mental_health
    if(health<5.0):
      return "I feel bad!"
    elif health<8.0:
      return "I am ok!"
    else:
      return "Great!"

В этом примере __physic_health и __mental_health являются закрытыми и не могут быть доступны непосредственно извне, единственный способ взаимодействия с внешним классом - свойство throught condition

Ответ 6

Существует также одна очевидная разница, которую я использую для кэширования или обновления данных, часто у нас есть функция, связанная с атрибутом класса. Например, мне нужно прочитать файл один раз и сохранить контент, назначенный атрибуту, чтобы значение было кэшировано:

class Misc():
        def __init__(self):
            self.test = self.test_func()

        def test_func(self):
            print 'func running'
            return 'func value'

cl = Misc()
print cl.test
print cl.test

Вывод:

func running
func value
func value

Мы дважды получили доступ к атрибуту, но наша функция была запущена только один раз. Изменение приведенного выше примера использования свойства приведет к обновлению атрибута каждый раз, когда вы его получите:

class Misc():

    @property
    def test(self):
        print 'func running'
        return 'func value'

cl = Misc()
print cl.test
print cl.test

Вывод:

func running
func value
func running
func value