python - 我可以定义如何处理访问 python 对象(而不仅仅是它的属性)吗?
问题描述
我在 python 中有一个自定义类,如果对象本身(即,如果它的方法/属性不是一个)被访问,我想以某种方式表现。
这是一个人为的最小工作示例来说明我的意思。我有一个包含各种pandas
DataFrame
s 的类,以便可以单独操作它们:
import pandas as pd
import numpy as np
class SplitDataFrame:
def __init__(self, df0, df1):
self._dfs = [df0, df1]
def increase(self, num, inc):
self._dfs[num] = self._dfs[num] + inc
@property
def asonedf(self):
return pd.concat(self._dfs, axis=1)
d = SplitDataFrame(pd.DataFrame(np.random.rand(2,2), columns=['a','b']),
pd.DataFrame(np.random.rand(2,2), columns=['q','r']))
d.increase(0, 10)
这行得通,我可以检查一下,d._dfs
现在确实是
[ a b
0 10.845681 10.561956
1 10.036739 10.262282,
q r
0 0.164336 0.412171
1 0.440800 0.945003]
到目前为止,一切都很好。
现在,我想更改/添加到类的定义,以便在不使用该.increase
方法时返回连接的数据帧。换句话说,在访问时d
,我希望它返回与键入时相同的数据框d.asonedf
,即
a b q r
0 10.143904 10.154455 0.776952 0.247526
1 10.039038 10.619113 0.443737 0.040389
这样,对象更紧密地遵循pandas.DataFrame
api:
- 而不是需要使用
d.asonedf['a']
,我可以访问d['a']
; - 而不是需要使用
d.asonedf + 12
,我可以做d + 12
; - 等等
那可能吗?
我可以SplitDataFrame
从继承pandas.DataFrame
,但这并不能神奇地添加所需的行为。
非常感谢!
解决方案
您当然可以根据需要将所有相关的魔术方法代理到连接的数据帧。如果你不想无休止地重复自己,你可以动态地做到这一点。
我不是说这是要走的路,但它有点工作:
import textwrap
import pandas as pd
import numpy as np
class SplitDataFrame:
def __init__(self, df0, df1):
self._dfs = [df0, df1]
def increase(self, num, inc):
self._dfs[num] = self._dfs[num] + inc
for name in dir(pd.DataFrame):
if name in (
"__init__",
"__new__",
"__getattribute__",
"__getattr__",
"__setattr__",
) or not callable(getattr(pd.DataFrame, name)):
continue
exec(
textwrap.dedent(
f"""
def {name}(self, *args, **kwargs):
return pd.concat(self._dfs, axis=1).{name}(*args, **kwargs)
"""
)
)
正如您可能猜到的那样,此解决方案附带各种字符串,并且使用了可怕的做法(使用exec
,使用dir
,...)。
至少我会实现__repr__
这样你就不会对自己撒谎这是什么类型的对象,也许你想显式枚举你想要定义的所有方法,而不是通过dir()
. 而不是exec()
您可以正常定义函数,然后使用setattr
.
推荐阅读
- javascript - Javascript - 分叉异步生成器
- python - 使用 Selenium 拒绝访问网站
- delphi - 如何在 FMX 中隐藏 TTabControl 的所有选项卡标题
- java - 如何在 Java 中查找模块名和包名
- html - 填充文本框后如何使浮动标签保持不变?
- sql-server - 通过考虑 order by 的数据将数据插入主表
- javascript - 在同一页面上运行 3 个幻灯片
- javascript - 如何使用 yargs 获取所有参数 exept '.$0' 和 '._'
- python - 如何将任意小部件添加到画布?
- r - R shiny ggplot - 如何不让年份标签超出网格?