【问题标题】:python class: inner functions; acces via nested dotspython类:内部函数;通过嵌套点访问
【发布时间】:2017-11-26 15:20:27
【问题描述】:

下面是我做的一个简单的类。我想访问像

这样的内部函数
obj = TestClass().TestClass(data)
obj.preprocess.gradient()

很明显,这样的调用不会起作用,因为preprocess 是一个函数。我怎样才能达到我想要的(我希望你清楚)

编辑:这是一个简化的案例。我希望其他不熟悉机器学习的用户发现以正确的顺序应用正确的功能更容易(首先是预处理,然后是例如聚类,然后是绘图)。我刚刚删除了外部功能(预处理等),它工作正常。我仍然想知道这种方法是否合理。

import numpy as np
from sklearn.preprocessing import StandardScaler

class TestClass:

    def __init__(self, data):
        self.data = data
        self._preprocessed = data

    # should not be a function but rather a "chapter" which
    # separates preprocessing from analysis method
    def preprocessing(self):

        def gradient(self):
            self._preprocessed = np.gradient(self._preprocessed, 2)[1]

        def normalize(self):
            self._preprocessed = StandardScaler().fit_transform(self._preprocessed)

    def cluster_analysis(self):

        def pca(self):
            pass

【问题讨论】:

  • 我猜你的意思是obj = TestClass(data) ?另外,preprocess 方法是从哪里来的,你不是说preprocessing 吗?此外,我认为提出问题会对我们有所帮助。
  • 这是您要解决的问题的代表,还是只是简化了问题?因为如果这个方法单独存在以便它可以定义其他函数,那么有更好的方法来实现这一点。
  • gradient 不是preprocess 的返回值的属性;它只是preprocess 范围内的一个局部变量。 preprocess 需要返回具有 gradient 属性的内容。或者,preprocess 需要是简单的实例属性,而不是实例方法。
  • “很明显,这样的调用不会起作用,因为预处理是一个函数”。很不真实。函数是 Python 中的第一类对象,并且通常具有类似定义的属性(参见 numpy funcs 以获得一个流行的示例)。符号失败的原因是内部函数不是父命名空间中的任何其他瞬态对象的属性。
  • 对我的回答不满意?它按照你的要求做。也许有些精度?

标签: python


【解决方案1】:

第一种方法(可能比后面的第二种方法更好)是返回一个拥有这两种方法的类实例,从而有利于组合。

否则,返回一个typed dict呢,如下

    #...
    @property
    def preprocessing(self):

        def gradient(self):
            self._preprocessed = np.gradient(self._preprocessed, 2)[1]

        def normalize(self):
            self._preprocessed = StandardScaler().fit_transform(self._preprocessed)

        callables_dict = {
            'gradient':gradient,
            'normalize':normalize,
        }

        return type('submethods', (object,), callables_dict)
    #...

然后你可以调用你的子方法(我猜)你想要的,做

>>> TestClass(data).preprocessing.gradient
<unbound method submethods.gradient>

>>> TestClass(data).preprocessing.normalize
<unbound method submethods.normalize>

根据您想要做什么,缓存preprocessing 可能是个好主意,这样就不会在每次调用时重新定义其内部函数。


但正如已经说过的,这可能不是最好的方法。

【讨论】:

  • 当您可以使用class 语句代替时,为什么要在属性方法中笨拙地构建类型?用类预处理替换@property def preprocessing 并去掉callables_dictreturn 语句,你就有了等价的东西,但比你展示的要好。不知道这是否真的是提问者想要的......
  • @Blckknght。等效还是更好?实际上我这样做是因为Most Python developers do not nest classes, so when you do so you break convention and increase maintenance cost.。话虽这么说,我也不是 100% 肯定理解 OP 想要什么:)。
  • 我认为使用class 语句构建类几乎总是比在字典中抛出方法并在运行时手动调用type 来构建类要好。原因之一是您的版本将创建一堆单独的类。它们将具有相同的内容,但它们不会是同一个类,如果您尝试像isinstance(x.preprocessing(), x.preprocessing) 这样的东西,这可能会非常令人困惑。但我认为我们可能同意 Questioner 的设计不是很好,完全避免内部类会更好。
猜你喜欢
  • 1970-01-01
  • 2014-02-11
  • 2014-10-30
  • 2018-10-23
  • 1970-01-01
  • 1970-01-01
  • 2017-01-25
  • 1970-01-01
  • 2012-01-17
相关资源
最近更新 更多