Python“属性”和“属性”之间有什么区别?

时间:2011-09-10 21:15:34

标签: python

我一般对“属性”和“属性”之间的区别感到困惑,并且找不到很好的资源来简明地描述差异。

6 个答案:

答案 0 :(得分:155)

属性是一种特殊的属性。基本上,当Python遇到以下代码时:

spam = SomeObject()
print(spam.eggs)

它在eggs中查找spam,然后检查eggs以查看它是否有__get____set____delete__方法 - 如果是的话,它是一个属性。如果属性,而不是只返回eggs对象(就像它对任何其他属性一样),它将调用__get__方法(因为我们正在进行查找)并返回该方法返回的内容。

有关Python's data model and descriptors的更多信息。

答案 1 :(得分:44)

使用属性,您可以完全控制其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

答案 2 :(得分:17)

一般而言,术语属性和属性是相同的。但是,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

答案 3 :(得分:11)

该属性允许您像普通属性一样获取和设置值,但在下面有一个方法被称为将其转换为getter和setter。这对于减少调用getter和setter的样板来说真的很方便。

让我们举个例子说,你有一个类,它为你需要的东西保留了一些x和y坐标。要设置它们,您可能需要执行以下操作:

myObj.x = 5
myObj.y = 10

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

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

问题是,如果有一天你的班级发生变化,你需要将你的x和y偏移某个值,该怎么办?现在你需要进入并更改你的类定义和所有调用它的代码,这可能非常耗时且容易出错。该属性允许您使用前一种语法,同时为您提供更改后者的灵活性。

在Python中,您可以使用属性函数定义getter,setter和delete方法。如果您只想要读取属性,还可以在方法上方添加@property装饰器。

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

答案 4 :(得分:4)

我总结了与Bernd Klein的site的2个不同之处:

<强> 1。属性是一种更方便的数据封装方式。

例如:如果您的公共属性长度为Object,则稍后,您的项目需要您对其进行封装,即:将其更改为私有并提供getter和setter =&gt;你必须改变你之前写的许多代码:

html

如果您使用@property和@ lenght.setter =&gt;你不需要改变那些旧代码

<强> 2。属性可以封装多个属性

#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

在此示例中,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

答案 5 :(得分:1)

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

WillPresent

输出:

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