【问题标题】:AttributeError when creating an object with Tuple attribute创建具有元组属性的对象时出现 AttributeError
【发布时间】:2021-09-29 00:46:22
【问题描述】:

我刚开始在 Python 中使用 OOP,我被要求创建一个 名为 Square 的类,该类具有名为 position 的特定 属性,它是元组类型。因此,对于每个 Square 对象,都有一个特定的方法来打印它,给定 size 属性(打印 size*size 的“#”)和 position 属性 (从坐标 (x, y) 开始) 但是当我在 init 方法中有一个 AttributeError,它告诉我:

AttributeError: 'Square' 对象没有属性 '_Square__position'

代码如下:

class Square:
''' create Square instance with public attributes
size and position '''
def __init__(self, size=0, position=(0, 0)):
    self.size = size
    self.position = position

''' retrieve size and make it private'''
@property
def size(self):
    return self.__size

''' set private size attribute '''
@size.setter
def size(self, value):
    if type(value) is not int:
        raise TypeError("size must be an integer")
    if value < 0:
        raise ValueError("size must be >= 0")
    self.__size = value

''' retrieve position and make it private '''
@property
def position(self):
    return self.__position

''' set private position attribute '''
@position.setter
def position(self, value):
    if value[0] < 0 or value[1] < 0:
        raise TypeError("position must be a tuple of 2 positive integers")
    self.__position[0] = value[0]
    self.__position[1] = value[1]

''' calculates area of square '''
def area(self):
    return self.__size ** 2

''' print a square of # the size of self.__size'''
def my_print(self):
    if self.__size == 0:
        print()
    else:
        for line in range(self.__position[1]):
            print()
        for i in range(self.__size):
            for space in range(self.__position[0]):
                print(" ", end="")
            for j in range(self.__size):
                print('#', end="")
            print()

感谢任何帮助,谢谢!

【问题讨论】:

  • 请发布整个回溯,以便我们查看流程。
  • 您有第二个与第一个相关的问题。元组是不可变的。你想让__position 成为元组吗?如果是这样,你不能做self.__position[0] = value[0]。您可能只想在 setter 中执行 self.__position = value 。但是,为什么这完全是一个属性呢?
  • 属性比实例变量更昂贵。如果您想在获取或设置时运行额外的代码(也许您想在接受它之前验证该位置是一个元组),它们会很有用。否则,您不需要它们。 “私有”变量可能是有问题的。通过使用 2 个下划线,变量名与类名混淆。这使得继承更加困难。
  • 名称修改(双下划线前缀)不会使属性“私有”。无法将属性设为私有。使用单个下划线前缀来指示该属性不是公共 API。

标签: python


【解决方案1】:

你的__init__() 方法应该是这样的:

def __init__(self, size=0, position=(0, 0)):
    self.__size = size    #<-- dunder
    self.__position = position #<-- dunder

编辑

感谢@tdelaney 指出position 是一个不允许项目分配 的元组。所以,你的@position.setter 应该是这样的:

@position.setter
def position(self, value):
    if type(value) != tuple or value[0] < 0 or value[1] < 0:
        raise TypeError("position must be a tuple of 2 positive integers")
    self.__position = value

【讨论】:

  • 我不敢相信就是这样。由于我使用属性设置器将属性设为私有,因此我认为它可以在 init 函数中公开。成功了,谢谢!
  • @Anwarvic - 这可能不是答案。如果您稍后尝试再次设置位置,您将看到失败 - 也许您想移动一个正方形并稍后执行square.position = (3,4)。那将失败。一旦你解决了这个问题,那么你原来的 __init__ 也将重新开始工作。
  • @tdelaney 你是对的......让我们为他/她解决这个问题。
  • 我不喜欢这个解决方案,因为您仍然无缘无故地建议使用名称修饰。
  • @wim - 我同意它可能不需要,但我认为这是对问题的严格回答之外的设计决定。答案不一定需要解决没有被问到的问题。
猜你喜欢
  • 2022-01-01
  • 2013-06-21
  • 1970-01-01
  • 2021-07-30
  • 2013-07-29
  • 2020-08-29
  • 2015-04-22
  • 2019-04-27
相关资源
最近更新 更多