【问题标题】:How to use properties and setters the Pythonic way如何以 Pythonic 方式使用属性和设置器
【发布时间】:2019-06-03 05:16:03
【问题描述】:

我正在关注python course 中的此代码示例:

class P:

    def __init__(self,x):
        self.x = x

    @property
    def x(self):
        return self.__x

    @x.setter
    def x(self, x):
        if x < 0:
            self.__x = 0
        elif x > 1000:
            self.__x = 1000
        else:
            self.__x = x

我尝试在我自己的代码中实现这种模式:

class PCAModel(object):
    def __init__(self):
        self.M_inv = None

    @property
    def M_inv(self):
        return self.__M_inv

    @M_inv.setter
    def set_M_inv(self):
        M = self.var * np.eye(self.W.shape[1]) + np.matmul(self.W.T, self.W)
        self.__M_inv = np.linalg.inv(M)

请注意,在我第一次运行 setter 之前,我希望 M_inv 属性为 None。此外,setter 仅依赖于类对象的其他属性,而不依赖于输入参数。

setter 装饰器产生错误:

NameError: name 'M_inv' is not defined

这是为什么?

【问题讨论】:

标签: python properties


【解决方案1】:

您的 setter 方法应如下所示:

@M_inv.setter
def M_inv(self):
    M = self.var * np.eye(self.W.shape[1]) + np.matmul(self.W.T, self.W)
    self.__M_inv = np.linalg.inv(M)

装饰器@M_inv.setter和函数def M_inv(self):名称应该相同

【讨论】:

    【解决方案2】:

    例子错了。

    编辑:示例是故意在__init__ 中使用设置器。

    Getter 和 setter,即使它们的行为类似于属性,也只是访问私有属性的方法。该属性必须存在。 在示例中,从未创建过 self.__x

    这是我的建议用途:

    class PCAModel(object):
        def __init__(self):
            # We create a private variable
            self.__M_inv = None
    
        @property
        def M_inv(self):
            # Accessing M_inv returns the value of the previously created variable
            return self.__M_inv
    
        @M_inv.setter
        def M_inv(self):  # Keep the same name than your propery
            M = self.var * np.eye(self.W.shape[1]) + np.matmul(self.W.T, self.W)
            self.__M_inv = np.linalg.inv(M)
    

    【讨论】:

    • __init__函数中隐式使用setter的例子不就是这样吗?
    • 确实,我没这么看。是否有理由使用 setter 来初始化变量?
    • 我个人会坚持在__init__ 方法外部使用getter 和setter。否则很难遵循。
    • __init__里面使用setter没有问题;事实上,使用它意味着您要么需要在__init__ 中复制边界检查,要么__init__ 可能违反setter 应该强制执行的任何约束。
    • 您似乎是对的,请注意。但是,将私有变量初始化为None 应该没问题,这样在第一次阅读时可以更好地理解。
    猜你喜欢
    • 2015-06-16
    • 2021-06-22
    • 2023-01-03
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 2021-05-20
    相关资源
    最近更新 更多