【问题标题】:How do I bring instance attributes into a @staticmethod如何将实例属性带入 @staticmethod
【发布时间】:2021-02-12 07:49:09
【问题描述】:

我有一个基类,如下所示:

class coordinates(object):
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

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

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

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

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

    @property
    def z(self):
        return self.z

    @z.setter
    def z(self, z):
        self.z = z

然后我创建一个继承自坐标的子类,并在其中包含一个静态方法,该方法将使用实例属性,如 x、y 和 z ...,如下所示:

class volume(coordinates):
    def __init__(self, x, y, z):
        super().__init__(x, y, z)
        self.volume = self.calculate_volume()

    def calculate_volume(self):
        return self.x * self.y * self.z

    @staticmethod
    def goes_through(x, y, z, h, l):
        if x < l and y < h:
            return f"Use surface {x}{y} to go through"
        elif y < l and x < h:
            return f"Use surface {y}{x} to go through"
        elif x < l and z < h:
            return f"Use surface {x}{z} to go through"
        elif z < l and x < h:
            return f"Use surface {z}{x} to go through"
        elif z < l and y < h:
            return f"Use surface {z}{y} to go through"
        elif y < l and z < h:
            return f"Use surface {y}{z} to go through"
        else:
            return "Object can't go through"

然后我实例化一个对象并尝试获取它的体积并查看它是否通过以及如何通过:

obj1 = volume(100, 200, 400)
print(obj1.volume)
print(obj1.goes_through(obj1.x, obj1.y, obj1.z, 200, 350))

但是我得到了这个错误:

[上一行重复了 993 次以上] RecursionError: 最大值 超出递归深度

非常感谢任何帮助。

【问题讨论】:

标签: python oop descriptor


【解决方案1】:

正确的 setter/getter 设置是:

class Obj(object):

    def __init__(self, value):
        self._value = value

    @property
    def value(self):
        return self._value

    @value.setter
    def value(self, value):
        self._value = value

但是,您无需这样做。在您的情况下,__init__ 函数就足够了。

【讨论】:

  • 感谢@sarartur 抽出时间回答并分享一个有效的例子。非常感谢
【解决方案2】:

问题在于您的 getter 和 setter 正在调用自己。当您在构造函数中执行 self.x = x 时,这将调用您的 x 设置器。然后在您的 x setter 中,您还可以执行 self.x = x。这会再次调用您的 x setter。这会再次调用您的 x setter,依此类推,直到您的堆栈空间不足并且 Python 引发 RecursionError。

你可以摆脱所有的 setter 和 getter,你的代码就可以正常工作了。

class coordinates(object):
    def __init__(self, x, y, z):
        self.x = x
        self.y = y
        self.z = z

或者,您可以使用不同的属性名称将数据存储在您的 getter 和 setter 中,这样它们就不会调用自己。

class coordinates(object):
    def __init__(self, x, y, z):
        self._x = x
        self._y = y
        self._z = z

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

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

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

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

    @property
    def z(self):
        return self._z

    @z.setter
    def z(self, z):
        self._z = z

但是,如果您没有特殊的理由做这样的事情,那么首先不使用 getter 和 setter 会更简单。

【讨论】:

    【解决方案3】:

    希望它可以在不使用 getter 或 setter 的情况下工作。

    class coordinates(object):
        def __init__(self, x, y, z):
            self.x = x
            self.y = y
            self.z = z
    
    class volume(coordinates):
        def __init__(self, x, y, z):
            super().__init__(x, y, z)
            self.volume = self.calculate_volume()
    
        def calculate_volume(self):
            return self.x * self.y * self.z
    
        @staticmethod
        def goes_through(x, y, z, h, l):
            if x < l and y < h:
                return f"Use surface {x}{y} to go through"
            elif y < l and x < h:
                return f"Use surface {y}{x} to go through"
            elif x < l and z < h:
                return f"Use surface {x}{z} to go through"
            elif z < l and x < h:
                return f"Use surface {z}{x} to go through"
            elif z < l and y < h:
                return f"Use surface {z}{y} to go through"
            elif y < l and z < h:
                return f"Use surface {y}{z} to go through"
            else:
                return "Object can't go through"
    
    
    obj1 = volume(100, 200, 400)
    print(obj1.volume)
    print(obj1.goes_through(obj1.x, obj1.y, obj1.z, 200, 350))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-04-28
      • 1970-01-01
      • 2021-12-07
      • 2010-10-31
      • 1970-01-01
      • 2023-01-30
      • 1970-01-01
      • 2011-10-30
      相关资源
      最近更新 更多