我通常对“属性”和“属性”之间的区别感到困惑,并且找不到一个很好的资源来简要地详细说明它们的区别。


当前回答

该属性允许您像普通属性一样获取和设置值,但在下面有一个方法被调用,将其转换为getter和setter。这实际上只是为了减少调用getter和setter的样板文件。

举个例子,你有一个类,它为你需要的东西保存了一些x和y坐标。要设置它们,你可能需要这样做:

myObj.x = 5
myObj.y = 10

这比写作更容易理解和思考:

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

问题是,如果有一天你的类发生了变化,你需要用一些值来抵消x和y,该怎么办?现在,您需要更改类定义和调用它的所有代码,这可能非常耗时且容易出错。该属性允许您使用前一种语法,同时允许您灵活更改后一种语法。

在Python中,可以使用属性函数定义getter、setter和delete方法。如果你只想要read属性,你还可以在你的方法上面添加一个@property装饰器。

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

其他回答

对于一个属性,你可以完全控制它的getter, setter和deleter方法,这是你在属性中所没有的(如果没有使用警告的话)。

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's 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

一般来说,属性和属性是一样的东西。然而,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

该属性允许您像普通属性一样获取和设置值,但在下面有一个方法被调用,将其转换为getter和setter。这实际上只是为了减少调用getter和setter的样板文件。

举个例子,你有一个类,它为你需要的东西保存了一些x和y坐标。要设置它们,你可能需要这样做:

myObj.x = 5
myObj.y = 10

这比写作更容易理解和思考:

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

问题是,如果有一天你的类发生了变化,你需要用一些值来抵消x和y,该怎么办?现在,您需要更改类定义和调用它的所有代码,这可能非常耗时且容易出错。该属性允许您使用前一种语法,同时允许您灵活更改后一种语法。

在Python中,可以使用属性函数定义getter、setter和delete方法。如果你只想要read属性,你还可以在你的方法上面添加一个@property装饰器。

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

还有一个不明显的区别,我使用缓存或刷新数据,通常我们有一个函数连接到类属性。例如,我需要读取文件一次,并保留分配给属性的内容,以便该值被缓存:

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

我们访问了属性两次,但是我们的函数只被触发了一次。将上面的例子改为使用property将导致每次访问它时属性的值刷新:

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

我从Bernd Klein site中学到了2个不同之处,总结如下:

1. 属性是实现数据封装的更方便的方式

例如,假设您有一个公共属性长度。稍后,你的项目需要你封装它,即改变它为私有并提供一个getter和setter =>,你必须改变你之前写的代码:

# Old code
obj1.length = obj1.length + obj2.length
# New code (using private attributes and getter and setter)
obj1.set_length(obj1.get_length() + obj2.get_length()) # => this is ugly

如果你使用@property和@length。Setter =>你不需要改变旧的代码。

2. 一个属性可以封装多个属性

class Person:
  def __init__(self, name, physic_health, mental_health):
    self.name = name
    self.__physic_health = physic_health 
    self.__mental_health = mental_health 

  @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是私有的,不能从外部直接访问。