我正在编写一个框架,我希望我的基类使用不同的函数在子类中重命名.我认为最好的方法是使用类属性,就像在的情况下一样A
,但是我TypeError
在运行它时会得到它rename_columns()
.然而,它与实现类似B
import pandas as pd
class A:
my_func_mask = str.lower
foo = 'bar'
def rename_columns(self, data):
return data.rename(columns=self.my_func_mask)
class B(A):
def rename_columns(self, data):
return data.rename(columns=self.__class__.my_func_mask)
Run Code Online (Sandbox Code Playgroud)
所以我尝试了上面的一点,我得到以下内容:
a = A()
a.foo # Works fine, gives back 'bar'
a.__class__.my_func_mask # Works as expected `a.__class__.my_func_mask is str.lower` is true
a.my_func_mask # throws TypeError: descriptor 'lower' for 'str' objects doesn't apply to 'A' object
Run Code Online (Sandbox Code Playgroud)
我的问题是为什么我可以使用常规类型(int,str等)值作为类属性并在实例上访问它们,而我不能为函数执行此操作?在这些情况下,在属性查找期间会发生什么?属性解析过程有什么区别?实际上,这两个foo
和my_func_mask
是__class__.__dict__
让我有点纳闷.谢谢你的澄清!
您正在类上存储未绑定的内置方法,这意味着它是一个描述符对象.当你再尝试访问上self
,结合描述,但适用的__get__
方法调用来完成绑定告诉你,它不能被绑定到你的自定义类的实例,因为该方法只上工作str
的情况.这是大多数内置类型方法的严格限制.
你需要以不同的方式存储它; 将它放在另一个容器(如列表或字典)中会避免绑定.或者您可以将其包装在staticmethod
描述符中以使其绑定并返回原始内容.另一种选择是不将其存储为类属性,只需在其中创建实例属性__init__
.
但在这种情况下,我根本不会存储str.lower
属性值.我会存储None
并回到str.lower
你还会遇到的时候None
:
return data.rename(columns=self.my_func_mask or str.lower)
Run Code Online (Sandbox Code Playgroud)
设置my_func_mask
为None
更好地指示将使用默认值,明确区别于明确设置str.lower
为掩码.