求助, 这段代码怎么复用

2019-12-26 15:50:00 +08:00
 plko345

麻烦大佬看看, 注 1 的函数是变化的, 其它部分基本一样, 有多个类似的统计, 菜鸟一枚, 先谢过

def cal_category_ecs_cpu_core_amount_by_tags(**tags):
    """合计机器 CPU 核心总数, 通过标签过滤"""
    amount = 0
    for instance_id in get_category_instance_id_by_tags(**tags):
        ecs_obj = ECSInstance(instance_id)
        cpu_core = ecs_obj.get_cpu_core()    # 注 1
        amount += cpu_core

    return amount

def cal_category_ecs_memory_amount_by_tags(**tags):
    """合计机器内存总数, 通过标签过滤"""
    amount = 0
    for instance_id in get_category_instance_id_by_tags(**tags):
        ecs_obj = ECSInstance(instance_id)
        memory = ecs_obj.get_memory()    # 注 1
        amount += memory

    return amount

我的想法是将这个类的实例方法作为参数传进去, 但这样处理似乎不是很合适, 而且这样处理的话方法是需要改成 类方法 或者静态方法吗?

4840 次点击
所在节点    Python
21 条回复
hebin
2019-12-26 16:14:44 +08:00
python 是可以直接函数做为参数传递的的

def stat(stat_fn, **tags) 类似这种
ipwx
2019-12-26 16:21:44 +08:00
为啥不一起统计?(手动狗头

def cal_category_ecs_amount_by_tags(stat_names: Sequence[str], **tags) -> Dict[str, int]:
....stat_values = {n: 0 for n in stat_names}
....for instance_id in get_category_instance_id_by_tags(**tags):
........ecs_obj = ECSInstance(instance_id)
........for n in stat_names:
............stat_values[n] += getattr(ecs_obj, f'get_{n}')()
....return stat_values
wuwukai007
2019-12-26 16:45:40 +08:00
怎么发代码?
tankren
2019-12-26 17:06:09 +08:00
@wuwukai007 新建主题的时候选 markdown 语法
lihongjie0209
2019-12-26 17:15:15 +08:00
```

def get_category_ecs_data_by_tags(**tags):
"""合计机器内存总数, 通过标签过滤"""
//amount = 0
datas = []
for instance_id in get_category_instance_id_by_tags(getDatafn, handleDatafn, **tags):
ecs_obj = ECSInstance(instance_id)
data= fn1(ecs_obj) # 注 1
datas.add(data)

return handleDatafn(datas)




调用方:

计算内存: get_category_ecs_data_by_tags(lamda ecs: ecs.get_memory(), lambda datas: sum(datas), tag1, tag2 )
计算 CPU: get_category_ecs_data_by_tags(lamda ecs: ecs.get_cpu_core(), lambda datas: sum(datas), tag1, tag2 )


```
lihongjie0209
2019-12-26 17:16:05 +08:00
data= fn1(ecs_obj) # 注 1
改为
data = getDatafn(ecs_obj)
wuwukai007
2019-12-26 17:22:36 +08:00
```python
def cal_category_ecs_memory_or_cpu_amount_by_tags(_type,**tags):
'''

:param _type: 类型
:param tags: other
:return: 数量
'''
"""合计机器内存总数, 通过标签过滤"""
amount = 0
for instance_id in get_category_instance_id_by_tags(**tags):
ecs_obj = ECSInstance(instance_id)
count = ecs_obj,get_memory() if _type == 'memory' else ecs_obj.get_cpu_core()
amount += count
return amount
```
Orenoid
2019-12-26 17:51:27 +08:00
这种模式还有很多的话,用楼上的 if-else 显然是不现实的。
如果你的 get_memory/get_cpu_core 都不需要操作 self 的话,我觉得转成静态方法没啥问题啊,然后把方法作为参数传进来就好了。
如果必须要用实例方法的形式调用的话,就用内置的 getattr 函数,把方法名传进来,比如:
data_fetcher = getattr(ecs_obj, 'get_memory')
data = data_fetcher()
然后把函数名和一些变量改为更通用的名字就行了。
plko345
2019-12-26 18:21:00 +08:00
@ipwx 因为并不是全都需要统计, 有的只需要其中的一个, 有的需要多个
plko345
2019-12-26 18:27:27 +08:00
谢谢各位
@ipwx
@Orenoid
我试试这个 getattr 方法, 应该是我想要的, 这个类里的方法有 self 操作, 必须是实例方法
ipwx
2019-12-26 18:38:42 +08:00
@plko345 你像我写的那样一起统计,要统计的量通过 stat_names 传入,不是最优解么。

不然你要统计多个指标,就要查多次数据库,特别浪费时间。
plko345
2019-12-26 18:47:37 +08:00
@ipwx 有道理, 我想想看, 主要我需要对不同的 tag 匹配, 不知道这样全统计会不会不灵活, 因为有的 tag 类型的不需要某些数据, 有的又需要, 不过我没多少数据, 这样全统计好像也没什么大问题

`-> Dict[str, int]` 你代码里的这个是什么意思
mind3x
2019-12-26 19:04:10 +08:00
Lambda 了解一下。
arvinsilm
2019-12-26 19:33:40 +08:00
不太懂 Python,参数加个 tag,循环里加个 switch ?
luozic
2019-12-26 20:51:28 +08:00
@ipwx 這個 python 魔法用得有點多啊。
@plko345 這個是返回值注解, 不過有點點問題想請教一下,這裏面的 ecs_obj = ECSInstance(instance_id)默認是去重了麽?
ipwx
2019-12-26 22:22:52 +08:00
@plko345 python 3.6 以上的类型注解,配合 ide 智能提示的体验简直飞起。因为习惯所以给你加上了
ipwx
2019-12-26 22:23:54 +08:00
@luozic 没觉得,3.6+ 这不都是基本操作么
zwzmzd
2019-12-26 22:25:34 +08:00
把 lambda 作为函数参数传进去
plko345
2019-12-26 22:59:35 +08:00
@luozic 类里没有去重, 默认传入的是唯一的, 不过似乎应该加上, 多谢提醒
luozic
2019-12-27 00:02:48 +08:00
@ipwx python 后面都是在向 typescript 学习类型推断和标记,这个才是最近 python 的主要方向吧。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/632579

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX