3

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

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

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")

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

4

3 回答 3

6

setter 当然可以返回一个值。

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

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

您可以改为显式调用 setter……但在这种情况下,将其编写为常规方法而不是属性 setter 会更清晰。


在您的情况下,我认为常规方法正是您想要的。您完全忽略了传递给 setter 的值。这会让你的代码的读者感到困惑(包括 6 个月后的你)。它根本不是一个真正的 setter,它是一个创建唯一名称的函数。那么,为什么不这样称呼它呢?

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

(值得注意的是,DBSetName返回它的参数本身并不是很 Pythonic……)


如果您想知道Python为何以这种方式工作,请参阅为什么我不能在表达式中使用赋值?来自官方常见问题解答。

更一般地说,表达式-语句的区别,以及相关的特性,如变异方法(例如,list.sort)返回None而不是self,导致了一种更简单、更规则的语言。当然,这是有代价的,因为它会导致语言不那么流利。有一个明显的权衡,Python 已经达到了你所能达到的极限。(与 JavaScript 相比,它几乎可以达到相反的极端。)但大多数喜欢 Python 的人认为它做出了正确的权衡。

于 2013-05-17T18:45:27.510 回答
0

我从一个类似的问题开始,但我只需要从 setter 获取“通用”信息即可自动创建 GUI;GUI 代码查看属性列表,找到具有设置器的属性,然后创建输入字段。然而,有些输入是字符串,有些是浮点数等,并且 GUI 代码会生成适当的输入字段。我知道这是一个混乱,但我把这些信息放在了 getter 的文档字符串中。

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

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()
于 2020-10-12T17:29:49.973 回答
0

使用 Python3.8 或更高版本:

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)

Myinstance.Name = (Uniquename := Myinstance.Name) # Python >= 3.8
于 2021-12-23T14:07:23.910 回答