Python:在静态范围内映射类的函数

时间:2016-12-03 13:54:10

标签: python python-3.x class

我想在静态范围内标记我的类函数的引用,即我想要类似的东西:

class MyClass:

    func_mapping = {
        'key_1': func_1,  # Not accessible in this scope
        'key_2': func_2
    }

    def func_1(self):     # instance's functions
        # Do something

    def func_2(self):
       # Do other things

如何映射我的功能?

基于用例的我想要的类结构如下:

class PlanTravel:
    travel_mapping = {
        'country_1': {
             'precondtion': ['condition_1', 'condition_2'],
             'planner': _travel_contry_1
            },
        'country_2': {
             'precondtion': ['condition_1', 'condition_2'],
             'planner': _travel_contry_2
            }
        }


    def __init__(self, conditions, country):
         self.conditions = conditions
         self.country = country

    def _verify_precondition(self):
        preconditions = PlanTravel.travel_mapping[self.country]['precondtion']
        for condition in preconditions:
            if condition not in self.conditions:
                raise Exception('You can not plan travel:', condition)

    def travel(self):
        self._verify_precondition()
        travel_func = PlanTravel.travel_mapping[self.country]['planner'] 
        travel_func()

    def _travel_contry_1(self):
        # Somthing

    def _travel_contry_2(self):
        # Somthing else        

编辑如@vaultah所述,我首先可以定义函数,然后将它们映射到dict,因为它们将在范围内可用。但我在课程开始时就想要它。如果有人想在将来浏览我的代码,那么他们可以在一开始就看到映射,他们知道要引用哪个函数。

5 个答案:

答案 0 :(得分:1)

我目前可以想到的另一种方式是通过名称解析,如果你在lambda中添加它并在查找期间求助于额外的函数调用:

func_mapping = {
    'key_1': lambda: MyClass.func_1, 
    'key_2': lambda: MyClass.func_2,
}

现在,必须使用以下方式进行不幸访问:

MyClass.func_mapping['key_1']()

另一个选项,将它包装在一个函数中,名称只在执行期间查找而不是编译:

def func_mapping(key):
    func_mapping = {
        'key_1': MyClass.func_1, 
        'key_2': MyClass.func_2,
    }
    return func_mapping[key]

这对眼睛来说有点好看,但你确实会把额外的功能当作负担。

答案 1 :(得分:1)

实现所需行为的直接方法是在类的func_mapping方法中定义__init__。当然,每次创建实例时都会重新定义,但那又如何呢?这只是一本小字典。

这是一个适用于Python 2和Python 3的演示。

class MyClass(object):
    def __init__(self, mode):
        func_mapping = {
            'key_1': self.func_1,
            'key_2': self.func_2,
        }
        self.func = func_mapping[mode]

    def func_1(self):
        return 'one'

    def func_2(self):
       return 'two'

a = MyClass('key_1')
print(a.func())

b = MyClass('key_2')
print(b.func())

<强>输出

one
two

答案 2 :(得分:1)

你的代码几乎可以工作,你只需要在映射之前定义方法,也不要通过类名引用它们,因为它还没有定义:

In [2]: class MyClass:
   ...:     def func_1(self):
   ...:         pass
   ...:     def func_2(self):
   ...:         pass
   ...:     func_mapping = {
   ...:         'key_1': func_1,
   ...:         'key_2': func_2
   ...:     }
   ...:     

In [3]: 

In [3]: MyClass.func_mapping
Out[3]: 
{'key_1': <function __main__.MyClass.func_1>,
 'key_2': <function __main__.MyClass.func_2>}

答案 3 :(得分:1)

另一种选择是将方法名称存储为字符串,然后使用getattr

class PlanTravel:
    travel_mapping = {
        'us': {
             'precondtion': ['condition_1', 'condition_2']
             'planner': '_us_planner'
            }    
    # --cut--        
    def travel(self):
        self._verify_precondition()
        getattr(self,
                PlanTravel.travel_mapping[self.country]['planner'])()

答案 4 :(得分:0)

在再次考虑这个问题时,我认为按照编码标准来实现它是不可能的。我解决这个问题的方法是:

class PlanTravel:

    def __init__(self, conditions, country):
         self.conditions = conditions
         self.country = country

    def _verify_precondition(self):
        country_preconditions = { 
            'country_1': ['condition_1', 'condition_2'],
            'country_2': ['condition_2', 'condition_2']
        }

        preconditions = country_preconditions[self.country]
        for condition in preconditions:
            if condition not in self.conditions:
                raise Exception('You can not plan travel:', condition)

    def travel(self):
        self._verify_precondition()

        travel_func = { 
            'country_1': self._travel_contry_1,
            'country_2': self._travel_contry_2
        }
        travel_func[self.country]()

    def _travel_contry_1(self):
        # Somthing

    def _travel_contry_2(self):
        # Somthing else

然后我可以称之为:

 plan_travel = PlanTravel('country_1')
 plan_travel.travel()

这堂课看起来很干净。但消极的是,我将在两个地方进行国家制图。但是在第二个想法中,这些映射是在需要这些字段的块处完成的,这对我来说非常有意义。

随意批评我。任何建议/批评都是最受欢迎的:)