本次文章 通过一次python和Go示例代码 来解读如何避免多重逻辑判断
demo1:
# encoding: utf-8
"""
@author:辉辉
@email: 372148872@qq.com
@Wechat: 不要静音
@time: 2022/5/14 18:43
"""
"""
已知: 目前有一个需求, 需要通过上游数据, 来调用一个封装类中拥有的方法
上游数据格式为json(python中称为嵌套字典, Go语言中称为map):
{
""
}
"""
dist_data = {
"d1": {"name": "zhangsand1"},
"c2": {"name": "zhangsanc2"},
"a3": {"name": "zhangsana3"},
"pp6": {"name": "zhangsanpp6"}
}
class Dont1:
def d1(name):
print(f"d1:{name}")
def c2(name):
print(f"c2:{name}")
def a3(name):
print(f"a3:{name}")
那么很多刚刚开始接触编程的同学们 可能就会使用if判断来进行编写 如下:
首先是需求演示:
demo.py
def func1(obj_name: str, obj: Dont1, value: str) -> any:
if obj_name == "d1":
obj.d1(value)
elif obj_name == "c2":
obj.c2(value)
elif obj_name == "a3":
obj.a3(value)
else:
print(f"方法:{obj_name}不存在")
ob = Dont1()
for key, value in data.items():
func1(key, ob, value.values())
咋一看之下,以上代码并没有任何问题, 但是 扩展性差 后续如果需要在添加方法的话 就要再次添加更多的elif 该如何避免 并让代码更有规范性呢?
python:
# encoding: utf-8
"""
@author:辉辉
@email: 372148872@qq.com
@Wechat: 不要静音
@time: 2022/5/14 18:43
"""
"""
已知: 目前有一个需求, 需要通过上游数据, 来调用一个封装类中拥有的方法
且 有一定的规范性,需要该类中一定包含某些方法, 增加容灾 例如: 实现类中需要包含d1这个方法
那么我就对这个示例进行亿点点改造工作
"""
# 首先导入官方库中的Protocol类
from typing import Protocol
dist_data = {
"d1": {"name": "zhangsand1"},
"c2": {"name": "zhangsanc2"},
"a3": {"name": "zhangsana3"},
"pp6": {"name": "zhangsanpp6"}
}
class ProtocolClass(Protocol):
def d1(self, name: str): ...
class Dont1:
def d1(self, name):
print(f"d1:{name}")
def c2(self, name):
print(f"c2:{name}")
def a3(self, name):
print(f"a3:{name}")
def Func(obj: ProtocolClass, data: dict) -> any:
def CheckName(name: str) -> str:
if isinstance(name, str):
return name.lower()
raise ValueError(f"当前传入的不是字符串而是{type(name).__name__}类型")
try:
ch = CheckName
for k, v in data.items():
func = getattr(obj, ch(k), None)
func(**v)
except Exception as _:
print("执行方法失败")
ob = Dont1()
Func(ob, dist_data)
go语言完成:
/*
1 *
2 * @Author: Hui
3 * @Date: 2022/5/27 21:09
4
*/
package main
import (
"fmt"
"reflect"
)
/*
首先, 解题思路与python一致, 那么唯一不一致的点在于,Go语言中没有getattr方法, 而我们又需要这个方法进行承上启下
所以这里选择使用Go语言内置库 反射
*/
type ProtocolInterface interface {
A1(name string)
}
type Dont struct{}
func (Dont) A1(name string) {
fmt.Println("Dont-->a1:", name)
}
func (Dont) B2(name string) {
fmt.Println("Dont-->b2")
}
func (Dont) C3(name string) {
fmt.Println("Dont-->c3")
}
func Func(obj ProtocolInterface, Methods []string, value []string) {
v := reflect.ValueOf(obj)
if len(Methods) >= 1 && len(Methods) == len(value) {
for i, method := range Methods {
cl := v.MethodByName(method)
cl.Call([]reflect.Value{reflect.ValueOf(value[i])})
}
}
}
func NewSlice(str ...string) []string {
// 这里可以做一下验证, 将str参数首字母进行大写
return append(([]string)(nil), str...)
}
func main() {
var d Dont
methods := NewSlice("A1", "B2", "C3")
data := NewSlice("zhang", "wang", "zhao")
Func(d, methods, data)
}
最终的运行成功呈现:
go:
python:
通过我们的亿点点改造后 就 不在存在 if else等逻辑判断!
感谢观看!