将函数分配为类方法

时间:2018-08-03 13:21:20

标签: python pandas

我只想将有效参数传递给一个函数(“ read_excel”),但我尝试了以下代码,但出现错误...

import pandas as pd
expected_keys=['io', 'sheet_name','header', 'names', 'index_col', 'usecols', 'squeeze', 'dtype', 'engine', 
               'converters', 'true_values',  'false_values', 'skiprows', 'nrows', 'na_values', 'parse_dates',
               'date_parser', 'thousands', 'comment', 'skipfooter', 'convert_float']

def safe_read_excel(self,  *args, **kwargs):
    if set(kwargs.keys()).difference(set(expected_keys)): 
        raise ValueError('invalid parameter found')
    return self.read_excel(f_name, *args, **kwargs)

pd.safe_read_excel = safe_read_excel

当我使用默认的“ read_excel”方法时,将创建一个数据框...

df= pd.read_excel('sales_summary.xlsx', header=0)

但是我的自定义方法引发了错误...

df= pd.safe_read_excel('sales_summary.xlsx', header=0)
  

AttributeError:'str'对象没有属性'read_excel'

如何将我的函数分配为pandas方法?

3 个答案:

答案 0 :(得分:4)

您在Pandas库的顶级模块中添加了一个新的 function 。模块对象的函数属性不会被绑定,也不会像self那样传递模块对象(模块未实现descriptor protocol access。只需删除self参数,只需访问{{ read_excel对模块的引用上的1}}函数。

pd变量绑定到没有self属性的'sales_summary.xlsx'字符串。

请注意,在Python 3中,read_excel是可以直接用作集合 dictionary view object

dict.keys()

仅当def safe_read_excel(*args, **kwargs): if not kwargs.keys() <= expected_keys: raise ValueError('invalid parameter found') return pd.read_excel(f_name, *args, **kwargs) <=中名称的子集时,kwargs.keys()操作才为真。这比使用expected_keysset.difference()更为有效,因为不需要创建新的设置对象。在这里,我将set_object - set_object设为集合对象而不是列表,以提高集合操作的性能:

expected_keys

在Python 2中,您将改为使用expected_keys = { 'io', 'sheet_name','header', 'names', 'index_col', 'usecols', 'squeeze', 'dtype', 'engine', 'converters', 'true_values', 'false_values', 'skiprows', 'nrows', 'na_values', 'parse_dates', 'date_parser', 'thousands', 'comment', 'skipfooter', 'convert_float' } 来获得相同的功能。对于需要同时支持Python 2和3的库,可以使用six.viewkeys()或创建自己的what the six library does本地版本。

请注意,您无需绑定到模块;您已经需要访问模块才能将新功能添加到名称空间,并且模块是单例。您的函数将始终只处理一个模块对象,而不处理Pandas库的多个实例,因此这里不需要通过绑定支持使您的代码库复杂化。方法仅需要绑定,因为一个类可以拥有任意数量的实例,并且方法需要访问那些实例中的特定实例才能访问实例属性。

答案 1 :(得分:3)

这是因为您正在将safe_read_excel函数作为类的方法编写,而它却是“普通函数”(或静态方法)。

实际上,您不需要self

def safe_read_excel(f_name,  *args, **kwargs):
    if set(kwargs.keys()).difference(set(expected_keys)): 
        raise ValueError('invalid parameter found')
    return pd.read_excel(f_name, *args, **kwargs)

我将函数的第一个输入从self更改为f_name,并将返回值更改为pd.read_excel

答案 2 :(得分:1)

您可以使用types模块将新方法绑定到类,这将允许您进行自省/在新类方法内引用self

import pandas as pd
import types

expected_keys=['io', 'sheet_name','header', 'names', 'index_col', 'usecols', 'squeeze', 'dtype', 'engine',
               'converters', 'true_values',  'false_values', 'skiprows', 'nrows', 'na_values', 'parse_dates',
               'date_parser', 'thousands', 'comment', 'skipfooter', 'convert_float']

def safe_read_excel(self,  *args, **kwargs):
    if set(kwargs.keys()).difference(set(expected_keys)):
      raise ValueError('invalid parameter found')
    return self.read_excel(args[0], *args, **kwargs)

pd.safe_read_excel = types.MethodType(safe_read_excel, pd)

df = pd.safe_read_excel('sales_summary.xlsx', header=0)