【问题标题】:Is it possible to write a function with "self" as an argument without defining a class?是否可以在不定义类的情况下编写一个以“self”为参数的函数?
【发布时间】:2019-12-08 07:17:25
【问题描述】:

我试图通过实现函数来减少一些代码行。我正在研究将自身作为参数的函数,例如 oop。例如:

def drop_columns(self, columns):
    return self.drop(columns, axis = 1)

df.drop_columns(['id', 'date'])

def print_shape(self):
    print(self.shape)

df.print_shape()

但当然更复杂。但是,代码不起作用。如果我给它一个数据框,它会抛出一个错误: AttributeError: 'DataFrame' object has no attribute 'print_shape'

有没有办法让它工作?

【问题讨论】:

  • 您可以随意命名函数的参数;从类实例(“方法”)中检索到的函数的行为与特定名称 self 完全无关
  • 您当然可以将print_shape(df) 用作实用函数。
  • 或者你可以继承 DataFrame

标签: python function oop object self


【解决方案1】:

当您在类的实例上调用方法时,该实例将自身作为第一个参数传递。为方便起见,我们通常将该参数称为self

这仅在方法首先绑定到实例时才有效。当您执行df.print_shape() 时,它不起作用,因为您从未以任何方式将print_shape() 附加到df

不过,以下两种方法都可以:

# approach 1: call it as a function
print_shape(df)

# approach 2: assign the function as an attribute of df, then call it as a method
setattr(df, 'print_shape', print_shape)
df.print_shape()

首选方法 1,因为通常最好不要修改不是您自己创建的对象(也不要像这样动态地这样做)。但是知道方法 2 的存在可以让我们对 Python 作为一种语言的工作方式有了一些看法/见解。如果你坐在print_shape() 里面,看不到外面发生的任何事情,你就无法分辨这两种方法之间的区别。

【讨论】:

  • 谢谢!后续问题:是否可以映射对象方法,例如 drop,例如map(drop(['column'], axis = 1), df)?我正在寻找一种简洁的解决方案来从多个数据框中删除列。
  • 不是直接,但您可以使用 lambda 函数来解决问题,例如map(lambda d:drop(d, ['column'], axis=1), df) 什么的。 map() 的问题在于它只传递一个参数,所以如果你想调用带有多个参数的东西,你必须使用 lambda。
【解决方案2】:

我认为您将类和 OOP 与函数混淆了。在您的情况下,不要将您的输入视为对象,而是您的函数的参数:

drop_columns(df, ['id', 'date'])
print_shape(df)

这些调用应该可以工作。

【讨论】:

    【解决方案3】:

    以第二个例子......你可以做的是:

        def __init__(self, shape=None):
            self.shape = shape
    

    现在,请致电 print_shape(Shape())print_shape(Shape('circle'))

    由于打印形状不绑定到任何类(或对象),它可以将自身视为参数。

    【讨论】:

      【解决方案4】:

      这里的另一种方法是从DataFrame 子类化并在此类中构建您的便利功能:

      import pandas as pd
      import numpy as np
      
      class EnhancedDataFrame(pd.DataFrame):
          def __init__(self, *args, **kwargs):
              super().__init__(*args, **kwargs)
          def print_shape(self):
              print(self.shape)
          def print_foo(self):
              print('This is the \'foo\'')
      
      data = np.array(np.random.randint(0,100,(3,4)))
      columns = ['A','B','A','C']
      index = ['Row 1', 'Row 2', 'Row 3']
      frame = EnhancedDataFrame(data, index=index, columns=columns)
      

      然后你应该可以这样做:

      所以要找到问题的根源:

      但是,代码不起作用。如果我给它一个数据框,它会抛出一个错误:AttributeError: 'DataFrame' object has no attribute 'print_shape'

      我们现在已经实现了我们自己的类 (EnhancedDataFrame),它一个 DataFrame(好吧,从技术上讲,它继承自 DataFrame)。它实现了您通常在 DataFrame 中期望的所有方法,但现在还包括您可能想要添加的任何便利方法!

      【讨论】:

        猜你喜欢
        • 2011-10-26
        • 2019-08-26
        • 2015-05-28
        • 1970-01-01
        • 1970-01-01
        • 2022-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多