V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
plko345
V2EX  ›  Python

求助, 这段代码怎么复用

  •  
  •   plko345 · 2019-12-26 15:50:00 +08:00 · 4926 次点击
    这是一个创建于 1785 天前的主题,其中的信息可能已经有所发展或是发生改变。

    麻烦大佬看看, 注 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
    
    

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

    21 条回复    2019-12-27 09:58:10 +08:00
    hebin
        1
    hebin  
       2019-12-26 16:14:44 +08:00
    python 是可以直接函数做为参数传递的的

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

    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
        3
    wuwukai007  
       2019-12-26 16:45:40 +08:00
    怎么发代码?
    tankren
        4
    tankren  
       2019-12-26 17:06:09 +08:00
    @wuwukai007 新建主题的时候选 markdown 语法
    lihongjie0209
        5
    lihongjie0209  
       2019-12-26 17:15:15 +08:00   ❤️ 1
    ```

    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
        6
    lihongjie0209  
       2019-12-26 17:16:05 +08:00
    data= fn1(ecs_obj) # 注 1
    改为
    data = getDatafn(ecs_obj)
    wuwukai007
        7
    wuwukai007  
       2019-12-26 17:22:36 +08:00   ❤️ 1
    ```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
        8
    Orenoid  
       2019-12-26 17:51:27 +08:00   ❤️ 1
    这种模式还有很多的话,用楼上的 if-else 显然是不现实的。
    如果你的 get_memory/get_cpu_core 都不需要操作 self 的话,我觉得转成静态方法没啥问题啊,然后把方法作为参数传进来就好了。
    如果必须要用实例方法的形式调用的话,就用内置的 getattr 函数,把方法名传进来,比如:
    data_fetcher = getattr(ecs_obj, 'get_memory')
    data = data_fetcher()
    然后把函数名和一些变量改为更通用的名字就行了。
    plko345
        9
    plko345  
    OP
       2019-12-26 18:21:00 +08:00
    @ipwx 因为并不是全都需要统计, 有的只需要其中的一个, 有的需要多个
    plko345
        10
    plko345  
    OP
       2019-12-26 18:27:27 +08:00
    谢谢各位
    @ipwx
    @Orenoid
    我试试这个 getattr 方法, 应该是我想要的, 这个类里的方法有 self 操作, 必须是实例方法
    ipwx
        11
    ipwx  
       2019-12-26 18:38:42 +08:00
    @plko345 你像我写的那样一起统计,要统计的量通过 stat_names 传入,不是最优解么。

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

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


    def cal_category_ecs_cpu_core_amount_by_tags(**tags):
    return sum(stats('get_cpu_core', **tags))


    def cal_category_ecs_memory_amount_by_tags(**tags):
    return sum(stats('get_memory', **tags))


    其实应该修改的是 ECSInstance
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1947 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 21ms · UTC 16:25 · PVG 00:25 · LAX 08:25 · JFK 11:25
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.