Python:动态向类实例添加属性,属性返回带输入的函数值

key*_*oss 5 python

我已经浏览了所有关于动态属性设置的 Stackoverflow 答案,但无论出于何种原因,我似乎无法让它发挥作用。

我有一个类,Evolution_Base它在其中init创建了一个实例Value_DifferencesValue_Differences应该properties根据我传递的列表动态创建,从以下位置返回函数值_get_df_change

from pandas import DataFrame
from dataclasses import dataclass
import pandas as pd
class Evolution_Base():
    
    def __init__(self, res_date_0 : DataFrame , res_date_1 : DataFrame):
        
        @dataclass
        class Results_Data():          
            res_date_0_df : DataFrame               
            res_date_1_df : DataFrame
            
    
        self.res = Results_Data(res_date_0_df= res_date_0,
                                res_date_1_df= res_date_1)
        
        property_list = ['abc', 'xyz']
        self.difference = Value_Differences(parent = self, property_list=property_list)
        
    
    # Shared Functions
    def _get_df_change(self, df_name, operator = '-'):
        df_0 = getattr(self.res.res_date_0_df, df_name.lower())
        df_1 = getattr(self.res.res_date_1_df, df_name.lower())
        return self._df_change(df_1, df_0, operator=operator)
        
    def _df_change(self, df_1 : pd.DataFrame, df_0 : pd.DataFrame, operator = '-') -> pd.DataFrame:
        """
        Returns df_1 <operator | default = -> df_0
        """        
        # is_numeric mask
        m_1 = df_1.select_dtypes('number')
        m_0 = df_0.select_dtypes('number')
        
        def label_me(x):
            x.columns = ['t_1', 't_0']
            return x
        
        if operator == '-':
            return label_me(df_1[m_1] - df_0[m_0])
        elif operator == '+':
            return label_me(df_1[m_1] + df_0[m_0])
        
        
class Value_Differences():    
    def __init__(self, parent : Evolution_Base, property_list = []):
        self._parent = parent
    
        for name in property_list:
                        
            def func(self, prop_name):
                return self._parent._get_df_change(name)
            
            # I've tried the following... 
            setattr(self, name, property(fget = lambda cls_self: func(cls_self, name)))
            setattr(self, name, property(func(self, name)))
            setattr(self, name, property(func))
Run Code Online (Sandbox Code Playgroud)

它让我发疯......任何帮助表示赞赏!

我想要的结果是:

evolution = Evolution_Base(df_1, df_2)
evolution.difference.abc == evolution._df_change('abc')
evolution.difference.xyz == evolution._df_change('xyz')
Run Code Online (Sandbox Code Playgroud)

编辑:简单的问题确实是,如何设置属性函数

小智 -1

调用时setattr,使用self.__class__而不是self

代码示例:

class A:
    def __init__(self,names : List[str]):
        for name in names:
            setattr(self.__class__,name,property(fget=self.__create_getter(name)))

    def __create_getter(self,name: str):
        def inner(self):
            print(f"invoking {name}")
            return 10
        return inner

a = A(['x','y'])

print(a.x + 1)
print(a.y + 2)
Run Code Online (Sandbox Code Playgroud)