简体   繁体   English

是否可以在不定义类的情况下以“ self”作为参数编写函数?

[英]Is it possible to write a function with “self” as an argument without defining a class?

I am trying to cut some lines of code by implementing functions. 我试图通过实现功能来减少一些代码行。 I was looking into functions that take themselves as an argument, as in oop. 我在研究以oop为参数的函数。 For example: 例如:

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

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

or 要么

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

df.print_shape()

But more sophisticated of course. 但是当然更复杂。 However, the code does not work. 但是,该代码不起作用。 If I feed it a data frame, it throws an error: AttributeError: 'DataFrame' object has no attribute 'print_shape' 如果我向其提供数据帧,则会引发错误: AttributeError: 'DataFrame' object has no attribute 'print_shape'

Is there a way to make this work? 有没有办法使这项工作?

When you call a method on an instance of a class, that instance passes itself as the first parameter. 在类的实例上调用方法时,该实例将自身作为第一个参数传递。 We usually call that parameter self , for convenience. 为了方便起见,我们通常将该参数称为self

This only works if the method is bound to the instance in the first place. 仅当方法首先绑定到实例时,这才起作用。 When you do df.print_shape() , it doesn't work, because you never attached print_shape() to df in any way. 当您执行df.print_shape() ,此操作将无效,因为您从未以任何方式将print_shape()附加至df

Both of the following will work, though: 但是,以下两项都将起作用:

# 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()

Approach 1 is preferred, as it's generally better practice not to modify objects that you didn't create yourself (and not to do so dynamically like this). 首选方法1,因为通常最好不要修改不是由您自己创建的对象(并且不要这样动态地进行修改)。 But knowing that Approach 2 exists gives some perspective/insight into how python works as a language. 但是,知道方法2的存在可以让人们对python作为一种语言的工作方式有一些看法。 If you were sitting inside print_shape() , unable to look at anything going on outside of it, you wouldn't be able to tell the difference between the two approaches. 如果您坐在print_shape()内部,无法查看其外部发生的任何事情,那么您将无法分辨出这两种方法之间的区别。

I think you are confusing classes and OOP with functions. 我认为您将类和OOP与函数混淆了。 In your case, don't treat your inputs as objects, rather arguments to your functions: 就您而言,不要将输入视为对象,而应将其视为函数的参数:

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

These calls should work. 这些电话应该可以正常工作。

Another approach here would be to subclass from DataFrame and build your convenience functions in this class: 这里的另一种方法是从DataFrame子类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)

And then you should be able to do like: 然后您应该能够做到:

在此处输入图片说明

So getting to the root of your problem: 因此,找出问题的根源:

However, the code does not work. 但是,该代码不起作用。 If I feed it a data frame, it throws an error: AttributeError: 'DataFrame' object has no attribute 'print_shape' 如果我向其提供数据帧,则会引发错误: AttributeError: 'DataFrame' object has no attribute 'print_shape'

We've now implemented our own class ( EnhancedDataFrame ) which is a DataFrame (well, ok, technically it inherits from DataFrame ). 现在,我们已经实现了自己的类( EnhancedDataFrame ),它一个DataFrame (好吧,从技术上讲,它继承自DataFrame )。 It implements all of the methods you'd normally expect in a DataFrame , but also now includes whatever convenience methods you might want to add! 它实现了通常在DataFrame期望的所有方法,但是现在还包括您可能想要添加的任何便捷方法!

在此处输入图片说明

Taking the second example... What you can do is: 以第二个示例为例...您可以做的是:

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

Now, call print_shape(Shape()) , or print_shape(Shape('circle')) . 现在,调用print_shape(Shape())print_shape(Shape('circle'))

Since, print shape is not bound to any class (or object), it can treat self as a parameter. 由于打印形状未绑定到任何类(或对象),因此可以将self作为参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM