【问题标题】:Resolving how to give an attribute in a class in Python解决如何在 Python 中的类中赋予属性
【发布时间】:2013-02-28 13:25:28
【问题描述】:

我有以下课程:

class Point(object):
    __slots__= ("x","y","z","data","classification")
    def __init__(self,x,y,z,n=None):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    def set_classification(self,n):
        self.classification = n

p = Point(10,20,30)
p.data
[10.0, 20.0, 30.0]
p.set_classification(0)
p.data
[10.0, 20.0, 30.0]

我有以下问题:

首先,创建Point对象的参数是x,yzClassification 是一个附属参数(有时是文件内的报告其他没有)。如果可能的话,我希望找到一种方法 p.data = [10.0, 20.0, 30.0, 50.0](设置分类时)或p.data = [10.0, 20.0, 30.0](未设置分类时)。

其次,我用set_classification

def set_classification(self,n):
      self.classification = n

这是正确的 Python API 风格吗?看了几篇论坛帖子,还是一头雾水。

【问题讨论】:

  • 您可以在设置后立即在您的set_classification 方法中添加if(self.classification == 1): self.data.append(50)
  • 请注意,如果您只是学习 Python,我非常怀疑您是否需要 __slots__。这是一项高级功能,只有知道自己在做什么的人才能使用。
  • Thnaks Daniel,我正在关注一些我在互联网上阅读的示例,我希望建立自己的课程。我们随时欢迎每条建议。

标签: python api class optimization coding-style


【解决方案1】:

您可以改用property 来处理分类:

class Point(object):
    __slots__= ("x", "y", "z", "data", "_classification")
    def __init__(self, x, y, z):
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)
        self.data = [self.x,self.y,self.z]

    @property
    def classification(self):
        return getattr(self, '_classification', None)

    @classification.setter
    def classification(self, value):
        self._classification = value
        if value:
            self.data = self.data[:3] + [value]
        else:
            self.data = self.data[:3]

这为classification 属性设置了一个getter 和一个setter;访问classification 属性将转换为第一个被调用的方法。设置 classification 属性在 setter 中进行转换,第二种方法被调用:

p = Point(1, 2, 3)
p.classification = 50  # calls the second `classification` method, the setter, for you.
print p.classification # calls the first `classification` method, the getter.

我在这里选择了classification 属性作为属性,但您也可以将data 设为属性。您将哪一个变成属性取决于使用模式和意图。如果classification 很少更改,则将其设置为属性会更有效。

【讨论】:

  • 嘿,Martijn,谢谢。我在互联网上寻找@property,但老实说这对我来说并不清楚。
  • 我测试并收到此错误消息 p = Point(10,20,30) p.classification(50) Traceback(最近一次调用最后一次):文件“”,第 1 行, 在 TypeError: 'list' object is not callable
  • @Gianni 这是一个属性。你可以用p.classification = 50调用它
  • @Gianni:您不是将它用作方法,而是用作属性。
  • 感谢 Martjin.=,我开始理解并乐于每天学习(感谢您的帮助)。我有最后一个问题要更好地理解@property 的使用。如果我想添加一个新参数es“位置”(数值),我需要创建一个@location.setter吗?在这种情况下我如何使用 self.data?我需要写出所有可能的组合吗?
【解决方案2】:

Getter 和 setter 方法通常不受欢迎。您可以使用属性来实现此目的,但是我建议您始终在返回值中包含 classification,因为脚本的其他部分可能期望 data 始终是 4 项列表。 API 应该是一致的。

这是我使用属性的看法:

class Point(object):
    __slots__= ("x", "y", "z", "data", "classification")
    def __init__(self, x, y, z, n=None):  ## what's n for?
        self.x = float(x)
        self.y = float(y)
        self.z = float(z)

        self.classification = None

    @property
    def data(self):
        if self.classification:
            return [self.x, self.y, self.z, self.classification]
        else:
            return [self.x, self.y, self.z]

p = Point(10, 20, 30)
print p.data   ## [10.0, 20.0, 30.0]
p.classification = 50.0
print p.data   ## [10.0, 20.0, 30.0, 50.0]

【讨论】:

  • 感谢费边。我开始明白了。就一个问题。如果我想添加一个新参数 es: "location" 是否需要添加 if self.location?
  • @Gianni 如果您想在data 属性的返回值中包含一个新的可选属性,那么是的,您需要相应地修改 if 语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-05
  • 1970-01-01
  • 2021-11-21
  • 2015-02-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多