foo和_foo - 关于类中的变量

时间:2010-04-21 13:47:41

标签: python class variables

class ClassName(object):
    """
    """    
    def __init__(self, foo, bar):
        """
        """
        self.foo = foo # read-write property
        self.bar = bar # simple attribute

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    foo = property(_get_foo, _set_foo)

a = ClassName(1,2)
#a._set_foo(3)
print a._get_foo()

当我打印a._get_foo()时,函数_get_foo会打印变量self._foo。 但是它来自哪里? self._foo和self.foo是不同的,不是吗?

编辑:问题是我仍然不明白属性是做什么的。给我一些时间。

5 个答案:

答案 0 :(得分:2)

Docs for property解释它应该如何使用。这些行之间没有区别:

self.foo = foo # read-write property

a.foo = 3

你也不应该手动调用setter和getter。

eta :如果您在查看文档中提供的示例并阅读我们的答案后不理解property的作用,您或许应该放弃使用它。它确实不是Python最重要的功能。您可能希望从一个更简单的示例开始,这个示例很容易理解:

>>> class ClassName(object):
    def __init__(self, foo):
        self.foo = foo


>>> a = ClassName(1, 2)
>>> a.foo
1
>>> a.foo = 42
>>> a.foo
42

答案 1 :(得分:2)

我真的推荐这个网站:

http://adam.gomaa.us/blog/2008/aug/11/the-python-property-builtin/

对属性函数的一个很好的解释。

答案 2 :(得分:1)

您将foo定义为具有getter和setter的属性。

那些getter和setter使用变量self._foo,因为你是这样编码的:

def _set_foo(self, value):
  self._foo = value

如果你的实现略有不同,你会遇到问题:

class ClassName(object):
    """
    """    
    def __init__(self,):
        """
        """
        pass

    def _set_foo(self, value):
        self._foo = value

    def _get_foo(self):
        return self._foo

    foo = property(_get_foo, _set_foo)


 a = ClassName()
 print a.foo
 -> AttributeError

 b = ClassName()
 b.foo = 1 # implicitely sets self._foo !
 print b.foo
 >> OK, this is 1

实际上,您确实应该在self.foo中设置__init__,因为设置者创建了self._foo。 (或者直接在self._foo初始化__init__)。

那么,self.foo和self._foo来自哪里?它在代码中是明确的。 self.foo是一个属性,self._foo是决定保留该属性值的变量。

答案 3 :(得分:1)

self._fooself.foo会有所不同,只是您已将自己创建的媒体资源分配给名称foofoo = property(_get_foo, _set_foo)

所以现在你有两个名称foo,这是根据方法_set_foo_get_foo定义的属性。您还定义了名称_foo,但这与_set_foo_get_foo中使用的属性相同,因此属性foo中也是如此。

所以你有两个名字,但只有一个对象。

        foo
        /\
       /  \
_set_foo  _get_foo
       \   /
        \ /
       _foo --> object

注意:对于Python的示例,这是过度的,除非他们要在其中使用业务逻辑,否则不需要使用getter和setter方法。只需使用名为foo的属性,如果事实证明您需要在属性访问周围需要一些智能,那么您将来可以始终将其包装在属性中而不会影响客户端代码。

将您的代码更改为:

class ClassName(object): 
    def __init__(self, foo, bar):
    self.foo = foo # read-write property
    self.bar = bar # simple attribute

foobar都是读写,如果你需要更好的控制,你可以考虑使用属性。

答案 4 :(得分:0)

根据你的代码,它“来自”_set_foo。在你的init中,当你执行self.foo = foo时,调用_set_foo(1),执行self._foo = 1.

如果在_set_foo()中添加print语句,则可以更清楚地看到这一点。