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

Car*_*son 125 python

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

Eth*_*man 170

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

spam = SomeObject()
print(spam.eggs)
Run Code Online (Sandbox Code Playgroud)

它查找eggsspam,然后检查eggs,看它是否有一个__get__,__set____delete__方法-如果这样做,这是一个性质.如果它一个属性,而不是仅仅返回eggs对象(就像它对任何其他属性一样),它将调用该__get__方法(因为我们正在进行查找)并返回该方法返回的任何内容.

有关Python的数据模型和描述符的更多信息.


neu*_*ino 49

使用属性,您可以完全控制其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
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个答案提供了一个现实而有用的例子.我觉得这个网站上的答案太多,不必解释后端的工作原理,而不说明用户应该如何与他们互动.如果一个人不理解为什么/何时使用某些功能,那么就不知道它是如何在幕后操作的. (5认同)
  • @TinLuu - 我认为我们都从不同的角度说同样的话。该类的用户应该只看到 `x`。单程。如果该类的用户发现了 _x,他们将自行承担使用它的风险。 (2认同)

six*_*ix8 18

一般而言,术语属性和属性是相同的.但是,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
Run Code Online (Sandbox Code Playgroud)

  • 你的意思是?那不是在代码的底部吗? (2认同)

fal*_*ojr 11

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

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

myObj.x = 5
myObj.y = 10
Run Code Online (Sandbox Code Playgroud)

这比写作更容易看和思考:

myObj.setX(5)
myObj.setY(10)
Run Code Online (Sandbox Code Playgroud)

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

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

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


Sad*_*kib 10

我认为,如果您想为属性设置限制,请使用属性。

尽管所有属性都是公共的,但通常程序员用下划线(_)来区分公共属性和私有属性。考虑下面的课程,

class A:
    def __init__(self):
        self.b = 3    # To show public
        self._c = 4   # To show private
Run Code Online (Sandbox Code Playgroud)

这里,b属性的目的是从类 A 的外部访问。但是,这个类的读者可能会想,b属性可以从类的外部设置吗A

如果我们打算不b从外部设置,我们可以用 来表示这个意图@property

class A:
    def __init__(self):
        self._c = 4   # To show private
   
    @property
    def b(self):
        return 3
Run Code Online (Sandbox Code Playgroud)

现在,b无法设置。

a = A()
print(a.b)   # prints 3
a.b = 7      # Raises AttributeError
Run Code Online (Sandbox Code Playgroud)

或者,如果您只想设置某些值,

class A:
    @property 
    def b(self):
        return self._b
    
    @b.setter
    def b(self, val):
        if val < 0:
            raise ValueError("b can't be negative")
        self._b = val

a = A()
a.b = 6     # OK
a.b = -5    # Raises ValueError
Run Code Online (Sandbox Code Playgroud)


小智 8

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

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
Run Code Online (Sandbox Code Playgroud)

输出:

func running
func value
func value
Run Code Online (Sandbox Code Playgroud)

我们访问了该属性两次,但我们的函数只被触发了一次。将上面的示例更改为 use 属性将导致每次访问时刷新属性的值:

class Misc():

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

cl = Misc()
print cl.test
print cl.test
Run Code Online (Sandbox Code Playgroud)

输出:

func running
func value
func running
func value
Run Code Online (Sandbox Code Playgroud)


Tin*_*Luu 6

总的来说,我从Bernd Klein的网站中学到了2个区别 :

1.属性是进行数据封装的一种更方便的方法。

例如:如果您拥有一个对象的公共属性长度,那么以后,您的项目需要您对其进行封装,即:将其更改为私有并提供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
Run Code Online (Sandbox Code Playgroud)

如果使用@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!"
Run Code Online (Sandbox Code Playgroud)

在此示例中,__physic_health并且__mental_health是私有的并且不能直接从外部访问,所以类外部与之交互的唯一方法是throught属性condition