在使用属性装饰器之后,python对象有两个非常相似的属性(foo.bar和foo.\u bar)。可以吗?

在使用属性装饰器之后,python对象有两个非常相似的属性(foo.bar和foo.\u bar)。可以吗?,python,python-3.x,properties,decorator,Python,Python 3.x,Properties,Decorator,因此,我正在重构我的代码,使之更具Pythonic风格——特别是我已经了解到,使用显式getter和setter应该被@property取代。我的情况是,我有一个示例类,它具有初始化的条属性(初始化帮助我知道用户设置了条): 运行foo=Example()。另外,当我运行foo.bar='changedValue'或foo.\u bar='changedValue'时,它们都会更改为'changedValue'。为什么有两个属性?这不是多余的吗?我想我理解为什么会有\u bar属性-我在@bar

因此,我正在重构我的代码,使之更具Pythonic风格——特别是我已经了解到,使用显式getter和setter应该被@property取代。我的情况是,我有一个
示例
类,它具有初始化的
属性(初始化帮助我知道用户设置了
):


运行
foo=Example()。另外,当我运行
foo.bar='changedValue'
foo.\u bar='changedValue'
时,它们都会更改为
'changedValue'
。为什么有两个属性?这不是多余的吗?我想我理解为什么会有
\u bar
属性-我在
@bar.setter
中添加了它,但是为什么会有
bar
作为字符串属性呢?
bar
不应该是一种导致
bar
的方法吗?

这很好。请记住,
bar
不是实例属性,而是类属性。由于它具有type
属性
,因此它实现了描述符协议,以便从实例访问时其行为不同。如果
e
Example
的实例,则
e.bar
不会提供分配给
Example.bar
属性的实例;它给出了
Example.bar.\uuuu-get\uuuu(e,Example)
(在本例中,它恰好是
Example.bar.fget(e)
,其中
fget
是由
@property
修饰的原始函数)

简言之,每个实例都有自己的
\u bar
属性,但对该属性的访问是通过class属性
Example.bar
来实现的


如果您编写这个最小(而且足够,因为在本例中,getter和setter都不需要
def
语句)定义,那么更容易看出
bar
是一个类属性

class Example:
    def __init__(self):
        self.bar = "initalizedValue"

    bar = property(lambda self: self._bar, lambda self, b: setattr(self, '_bar', b))
或者更一般地说

def bar_getter(self):
    return self._bar


def bar_setter(self, b):
    self._bar = b


class Example:
    def __init__(self):
        self.bar = "initalizedValue"

    bar = property(bar_getter, bar_setter)

很好。请记住,
bar
不是实例属性,而是类属性。由于它具有type
属性
,因此它实现了描述符协议,以便从实例访问时其行为不同。如果
e
Example
的实例,则
e.bar
不会提供分配给
Example.bar
属性的实例;它给出了
Example.bar.\uuuu-get\uuuu(e,Example)
(在本例中,它恰好是
Example.bar.fget(e)
,其中
fget
是由
@property
修饰的原始函数)

简言之,每个实例都有自己的
\u bar
属性,但对该属性的访问是通过class属性
Example.bar
来实现的


如果您编写这个最小(而且足够,因为在本例中,getter和setter都不需要
def
语句)定义,那么更容易看出
bar
是一个类属性

class Example:
    def __init__(self):
        self.bar = "initalizedValue"

    bar = property(lambda self: self._bar, lambda self, b: setattr(self, '_bar', b))
或者更一般地说

def bar_getter(self):
    return self._bar


def bar_setter(self, b):
    self._bar = b


class Example:
    def __init__(self):
        self.bar = "initalizedValue"

    bar = property(bar_getter, bar_setter)