[英]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.