我只想将有效参数传递给一个函数(“ 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方法?
答案 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_keys
或set.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)