【问题标题】:Why does Init function return Object type but other functions return the NoneType为什么Init函数返回Object类型而其他函数返回NoneType
【发布时间】:2019-04-24 09:16:40
【问题描述】:

我编写了一个 python 程序来尝试使用面向对象编程对我的机器学习预测进行评分,并且我正在尝试将函数链接在一起。就像说:

answers = predictionsGrader().merge_on('PassengerId').compare("Survived_x", "Survived_y").grade()

但是,我的代码开始抛出属性错误的错误。

AttributeError: 'NoneType' object has no attribute 'compare'

在尝试了解问题所在后,我意识到虽然初始化返回的是一个对象,

<class 'predictionsGrader.predictionsGrader'>

初始化后调用的函数(即merge_on 函数)返回NoneType

<class 'NoneType'>

请问有什么问题。完整代码如下:

import pandas as pd

class predictionsGrader():

    def __init__(self, predictions, target):
        self.correct = []
        self.predictions = predictions
        self.target = target
        return


    def merge_on(self, row):
        self.row = row
        self.md = pd.merge(self.predictions, self.target, on=[self.row])
        return


    def compare(self, predicted_target, confirmed_target):
        self.predicted_target = predicted_target or "predicted_target"
        self.confirmed_target = confirmed_target or "confirmed_target"
        return


    def grade(self):
        for x in range(len(self.md[self.predicted_target])):
            if (self.md[self.predicted_target][x] == self.md[self.confirmed_target][x]):
                self.correct.append("right")
            else:
                self.correct.append("wrong")
        return self.correct

【问题讨论】:

  • 因为__init__ 是特殊的(与其他双下划线函数一样)。另请参阅stackoverflow.com/questions/2491819/…
  • 如果你真的想要得到你想要的,你可以把return self放在你其他方法的末尾。但我建议不要这样做;至少不适用于不构造对象的常规方法。
  • 所有方法默认返回None。如果您想退回其他东西,这取决于您。 (顺便说一句,你的空returns 在你的问题中什么也不做)。

标签: python class oop object nonetype


【解决方案1】:

如果您想要这样的流畅界面,您的方法(__init__ 除外)需要返回 self

class predictionsGrader():

    def __init__(self, predictions, target):
        self.correct = []
        self.predictions = predictions
        self.target = target

    def merge_on(self, row):
        self.row = row
        self.md = pd.merge(self.predictions, self.target, on=[self.row])
        return self

    def compare(self, predicted_target, confirmed_target):
        self.predicted_target = predicted_target or "predicted_target"
        self.confirmed_target = confirmed_target or "confirmed_target"
        return self

    def grade(self):
        for x in range(len(self.md[self.predicted_target])):
            if (self.md[self.predicted_target][x] == self.md[self.confirmed_target][x]):
                self.correct.append("right")
            else:
                self.correct.append("wrong")
        return self.correct

__init__ 不应该返回任何东西——它是一个初始化器,而不是一个构造器。

【讨论】:

  • 解决了。在接下来的 10 分钟内无法接受答案,但我会尽快接受。谢谢。
  • 好的,我会从init中删除返回
  • 改变实例本身(即它的属性)并返回 self 的方法的问题在于,它可以使实例被改变的情况变得不那么明显。例如,比较listappend 方法返回None,特别是因为列表本身已更改(就地);相比之下,列表的 __add__ 方法 (+) 返回一个新列表。这是为了避免混淆 API,因为当实例本身被更改时,与返回更改后的副本时相比,它更清楚。因此,从方法中返回 self 对我来说并不常见。
  • Fluent 接口并不是 Pythonistas 常用的,这是真的,但它在其他地方是相当常见的模式 - 请参阅 en.m.wikipedia.org/wiki/Fluent_interface - 任何 python 都完全能够做到这一点。在适当的情况下,我非常喜欢这种模式。
【解决方案2】:

predictionsGrader()predictionsGrader.__init__() 不同。 __init__() 作为启动过程的一部分被一些 Python 魔术在后台调用。

【讨论】:

    猜你喜欢
    • 2012-12-01
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-18
    • 2023-03-28
    相关资源
    最近更新 更多