Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/codeigniter/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么';这就是Python和;不动产;及;属性";?_Python - Fatal编程技术网

什么';这就是Python和;不动产;及;属性";?

什么';这就是Python和;不动产;及;属性";?,python,Python,我通常对“属性”和“属性”之间的区别感到困惑,并且找不到一个很好的资源来简要地详述这些区别 一般来说,属性和属性是一回事。但是,Python中有一个属性装饰器,它提供对属性(或其他数据)的getter/setter访问 对于属性,您可以完全控制它的getter、setter和deleter方法,而对于属性,您没有这些方法(如果没有使用警告) class A(object): _x = 0 '''A._x is an attribute''' @property

我通常对“属性”和“属性”之间的区别感到困惑,并且找不到一个很好的资源来简要地详述这些区别

一般来说,属性和属性是一回事。但是,Python中有一个属性装饰器,它提供对属性(或其他数据)的getter/setter访问


对于属性,您可以完全控制它的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
A类(对象):
_x=0
''A.''x是一个属性''
@财产
def x(自我):
'''
A.x是一个属性
这是getter方法
'''
返回自我
@x、 塞特
def x(自身,值):
"""
这是setter方法
在这里,我可以检查它是否未被赋值<0
"""
如果值<0:
提升值错误(“必须大于等于0”)
self._x=值
>>>a=a()
>>>a.x=-1
>>>a.x=-1
回溯(最近一次呼叫最后一次):
文件“ex.py”,第15行,在
a、 x=-1
文件“ex.py”,第9行,x中
提升值错误(“必须大于等于0”)
ValueError:必须大于等于0

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

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

myObj.x = 5
myObj.y = 10
这比写作更容易观察和思考:

myObj.setX(5)
myObj.setY(10)
问题是,如果有一天你的类发生了变化,以至于你需要用某个值来偏移你的x和y,该怎么办?现在,您需要修改类定义和所有调用它的代码,这可能非常耗时且容易出错。属性允许您使用前一种语法,同时允许您灵活更改后一种语法

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


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

spam = SomeObject()
print(spam.eggs)
它在
spam
中查找
eggs
,然后检查
eggs
以查看它是否有
\uuuuuuuuuuuuuuuuu
方法、
\uuuuuuuuuuuuuuuuuuuuuuuuuuuu设置方法或
\uuuuuuuuuuuuuuuuuu删除方法 — 如果是的话,那就是财产。如果它是一个属性,那么它将调用
\uuuu get\uuuu
方法(因为我们正在执行查找),而不是仅仅返回
eggs
对象(与任何其他属性一样),并返回该方法返回的任何内容


有关的更多信息。

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

1。属性是实现数据封装的更方便的方法

例如,假设您有一个公共属性
length
。稍后,您的项目要求您对其进行封装,即将其更改为private并提供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!"
班级人员:
定义初始(自我、姓名、身体健康、心理健康):
self.name=名称
自我健康=身体健康
自我心理健康=心理健康
@财产
def状态(自身):
健康=自我。身体健康+自我。心理健康
如果(健康状况<5.0):
return“我感觉很糟糕!”
elif健康<8.0:
return“我很好!”
其他:
返回“太好了!”

在本例中,
\uuuuuu physic\u health
\uuuu mental\u health
是私有的,不能直接从外部访问。

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

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
func running
func value
func running
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 value
func running
func value
func running
func value

这个(“完全控制”)也可以用“非属性”属性来完成,只是不需要这样简单的装饰器。我喜欢这个答案提供了一个现实而有用的例子。我觉得这个网站上有太多的答案不必要地解释了后端的工作原理,而没有说明用户应该如何与它们交互。如果一个人不理解为什么/何时使用某些功能,那么知道它在幕后是如何运行的就没有意义了。这个答案违反了“Python的禅宗——应该有一种——最好只有一种——显而易见的方法来实现它”。有两种方法可以设置x值。@TinLuu-只有一种方法可以设置x值。设置x的值也只有一种方法。它们是相同的事实是一个实现细节。这个类的聪明用户不使用x。@TinLuu-我想我们从相反的角度说的是同一件事。类的用户应该只看到
x
。单程。如果类的用户发现了x,他们使用它的风险由他们自己承担。你能不能也提到这段代码的预期结果?你是什么意思?这不是在代码的底部吗?听起来属性需要额外的处理来访问目标值……你知道它有多重要/慢吗?@martineau:嗯,有一个额外的函数调用,但额外的工作和时间很可能取决于属性在做多少(g)