【问题标题】:attribute error, singleton pattern with property method属性错误,带有属性方法的单例模式
【发布时间】:2018-03-07 02:55:42
【问题描述】:

在处理数据库连接时,出于明显的原因,我使用了单例模式。为简化起见,我已经简化了类定义,问题还是一样。

班级:

class Point(object):
    _instance = None

    def __new__(cls, x, y):
        if Point._instance is None:
            Point._instance = object.__new__(cls)
            Point._instance.x = x
            Point._instance.y = y
        return Point._instance

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

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

    @x.setter
    def x(self, x):
        self._x = self._instance.x

    @property
    def y(self):
        return self._y

    @y.setter
    def y(self, y):
        self._y = self._instance.y

    def __str__(self):
        return 'x: {}, y: {} id.x: {}'.format(self.x, self.y, id(self.x))

它会产生以下错误:

AttributeError: 'Point' object has no attribute '_x'

我找到了以下解决方法:

class Point(object):
    _instance = None

    def __new__(cls, x, y):
        if Point._instance is None:
            Point._instance = object.__new__(cls)
            Point._instance.x = x
            Point._instance.y = y
        return Point._instance

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

pythonic 方法是使用属性方法,因此我仍然有那种痒,即使我有一个工作代码,有人可以向我解释为什么 - 为什么我会出现这样的错误。

【问题讨论】:

  • 缩进。很痛。
  • 为什么要让 Point 类成为单例?!
  • @jq170727 抱歉,我没注意缩进,我只是从我的编辑器中过去了代码。
  • @wim Point 类是题外话,而不是发布所有处理与数据库的连接的代码并失去重点,我在简单的事情上重复了同样的错误。

标签: python python-2.7 python-3.x


【解决方案1】:

在您的__init__ 中调用self.x 时,控制(通过描述符)被移动到x 的设置器:

self._x = self._instance.x

反过来,它会调用尝试做的getter:

return self._x 

在设置self._x 之前。 _y 也存在类似的情况。

我的印象是您不希望人们更改 xy 的值,如果是这样,请将它们设为 read-only properties

作为附录,没有理由在__new__ 中设置xy 的值,您可以在__init__ 中设置它们。

【讨论】:

  • 正如我的问题中提到的,原始类用于处理数据库连接,因此我防止了多次实例化,请耐心等待,将 x 想象为连接,将 y 想象为光标。
【解决方案2】:

虽然我不确定我是否理解您为什么要这样做,但您可以尝试:

_instance = None

def Point(x,y):
    class _Point(object):
        def __init__(self, x, y):
            self.x = x
            self.y = y
        def __str__(self):
            return 'x: {}, y: {} id.x: {}'.format(self.x, self.y, id(self.x))
    global _instance
    if _instance is None:
        _instance = _Point(x,y)
    return _instance    

p1 = Point(1,2)
print "p1", p1

p2 = Point(3,4)
p2.x = 10
print "p2", p2

print "p1", p1

输出

p1 x: 1, y: 2 id.x: 94912852734312
p2 x: 10, y: 2 id.x: 94912852734096
p1 x: 10, y: 2 id.x: 94912852734096

Try it online!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-29
    • 2014-03-02
    • 1970-01-01
    • 2021-07-17
    • 2021-09-25
    相关资源
    最近更新 更多