Python setter也返回一个值

时间:2013-05-17 18:42:21

标签: python python-3.x decorator setter getter-setter

我想知道是否有可能让属性设置器也返回一个值。下面的代码试图从表面上解释问题。

基本上我需要为对象设置属性,但在我需要检查它是否是唯一的之前。我想知道是否有办法直接向用户返回唯一名称,而不需要事后查询对象的新名称。

class MyClass(object):
    def __init__(self,ID):
        self._ID = ID
    @property
    def Name(self):
        return DBGetName(self._ID)

    @Name.setter
    def Name(self, value):
        UniqueName = DBGetUniqueName(self._ID,value)
        return DBSetName(UniqueName)

Myinstance = MyClass(SomeNumber)
#What I do now
Myinstance.Name = "NewName"
Uniquename = Myinstance.Name

#What I was wondering if possible. Line below is syntactically invalid, but shows the idea.
Name = (Myinstance.Name = "NewName")

编辑: 这是一个伪代码,我忘了将值实际传递给内部函数。我的坏。

2 个答案:

答案 0 :(得分:5)

一个setter当然可以返回一个值。

但这样做并不是很有用,因为setter通常用在赋值语句中 - 就像你的例子一样。

问题是在Python中,赋值不是表达式,而是一个声明。它没有您可以使用的值,并且您不能将其嵌入另一个语句中。所以,没有办法写出你想写的行。

你可以改为明确地调用setter ...但是在这种情况下,将它作为常规方法而不是属性设置器来编写它会更加清晰。


在你的情况下,我认为常规方法正是你想要的。你完全忽略了传递给setter的值。这将使您的代码(包括您在6个月内)的读者感到困惑。它根本不是真正的制定者,它是一个创造一个独特名称的功能。那么,为什么不称之为呢?

def CreateUniqueName(self):
    UniqueName = DBGetUniqueName(self._ID)
    return DBSetName(UniqueName)

(值得注意的是DBSetName返回它的论点本身并不是非常Pythonic ......)


如果您想知道为什么 Python以这种方式工作,请参阅官方常见问题解答中的Why can't I use an assignment in an expression?

更一般地说,表达式语句的区别,以及返回list.sort而不是None的变异方法(例如self)等相关功能,会导致更简单,更常规的语言。当然会有成本,因为它会导致语言不那么流畅。有一个明显的权衡,Python可以达到极致。 (与JavaScript相比,它与相反极端相差甚远。)但是大多数喜欢Python的人认为它做出了正确的权衡。

答案 1 :(得分:0)

我从一个类似的问题开始,但是我只需要从设置者那里获取“通用”信息就可以自动创建GUI。 GUI代码浏览属性列表,找到具有设置器的属性,然后创建输入字段。但是,某些输入是字符串,其他输入是浮点型,等等,并且GUI代码会生成适当的输入字段。我知道这很麻烦,但是我将这些信息放入了获取程序的文档字符串中。

我意识到这不是您问题的答案,但可能会帮助看起来像我的人!

class Dog():
    def __init__(self):
        self._name = None
        return
    @property
    def name(self):
        """Doggos are the best!"""
        return self._name
    @name.setter
    def name(self, n):
        self._name = n
        return
def main():
    terrier = Dog()
    terrier.name = "Rover"
    print("Dog's name is ", terrier.name)
    print(type(terrier).name.__doc__)
    # also works with...
    print(getattr(type(terrier), 'name').__doc__)
    return
if __name__ == '__main__':
    main()