• 请不要在回答技术问题时复制粘贴 AI 生成的内容
hellogbk
V2EX  ›  程序员

初学 Python,此函数求优化

  •  
  •   hellogbk · Jan 1, 2016 · 5852 views
    This topic created in 3960 days ago, the information mentioned may be changed or developed.

    大家新年快乐!
    我初学 Python 一个星期左右,求优化下面这个函数,此函数的作用在于生成 IP 列表:

    def parse_ip(ip):
        ips = []
        if '-' in ip:
            segments = ip.split(".")
            seg_index = 0
            for segment in segments:
                if '-' in segment:
                    prefix = ".".join(segments[:seg_index])
                    suffix = ".".join(segments[seg_index+1:])
    
                    start, end = map(int, segment.split("-"))
    
                    new_ips = [".".join(filter(lambda s: s, map(str,[prefix, ip_segment, suffix]))) for ip_segment in range(start, end +1)]
                    for new_ip in new_ips:
                        ips += parse_ip(new_ip)
    
                    break
    
                seg_index += 1
    
        else:
            ips += [ip]
    
        return ips
    
    
    if __name__ == "__main__":
        print "\n".join(parse_ip("192.168.1-2.1-10"))
    

    输出的结果是:

    192.168.1.1
    192.168.1.2
    192.168.1.3
    192.168.1.4
    192.168.1.5
    192.168.1.6
    192.168.1.7
    192.168.1.8
    192.168.1.9
    192.168.1.10
    192.168.2.1
    192.168.2.2
    192.168.2.3
    192.168.2.4
    192.168.2.5
    192.168.2.6
    192.168.2.7
    192.168.2.8
    192.168.2.9
    192.168.2.10
    

    求指点代码还可以怎么优化,谢谢!

    30 replies  •  2016-01-04 15:36:29 +08:00
    vanxining
    vanxining
    Jan 1, 2016 via Android
    1
    楼主是来炫耀的 :-)
    firebroo
    firebroo
    Jan 1, 2016
    2
    ddd
    hellogbk
    hellogbk
    OP
    Jan 1, 2016
    3
    @vanxining 额,不是啊。 我是想知道怎么用更少的代码来实现同样的功能。
    semut
    semut
    Jan 1, 2016❤️1
    4
    你所说的优化是指什么?运算速度么,还是计算逻辑,这是我的代码:
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-

    def expand(segment):
    if '-' not in segment:
    return [segment]
    else:
    start, end = map(int, segment.split('-'))
    return map(str, range(start, end+1))

    def parse_ip(ip):
    segments = ip.split('.')
    seg_list = map(expand, segments)
    return reduce(lambda lx, ly: [x+'.'+y for x in lx for y in ly], seg_list)

    if __name__ == "__main__":
    print "\n".join(parse_ip("192.168.1-2.1-10"))
    k9982874
    k9982874
    Jan 1, 2016 via iPhone❤️2
    5
    手机看代码自动换行太难看,所以就是没好好读。
    能给的建议就是把函数参数改成
    parse_ip(ip_header, first_start, first_end, second_start, second_end)

    函数内直接 for 循环拼接生成 ip ,不需要再去拆字符串。
    字符串操作成本永远是最贵的。
    holyzhou
    holyzhou
    Jan 1, 2016❤️1
    6
    感觉 一用上 filter , reduce , map , lambda ,列表推倒式这些,程序可读性立马就下去了
    hellogbk
    hellogbk
    OP
    Jan 1, 2016
    7
    @semut 谢谢,我指的是代码能不能再少一点。因为我以前学 JAVA 的,所以感觉我在写这个函数的时候还是 JAVA 的思维多一点,就想知道用 python 的想法应该怎么写。
    wowpanda
    wowpanda
    Jan 1, 2016
    8
    正则
    am241
    am241
    Jan 1, 2016
    9
    只求代码更少可以用正则吧
    syv2
    syv2
    Jan 1, 2016❤️2
    10
    回复不能写格式化的代码,我就不写函数了,反正就这么个意思:

    import itertools

    ip = "192.168.1-2.1-10"
    segs = [seg for seg in ip.split('.')]
    segs = [[int(iter) for iter in seg.split('-')] for seg in segs]
    ips = itertools.product(*segs)
    join_fuc = lambda l: '.'.join([str(i) for i in l])
    ips = [join_fuc(ip) for ip in ips]
    syv2
    syv2
    Jan 1, 2016
    11
    上面写错了。。修正一下:


    import itertools

    ip = "192.168.1-2.1-10"
    segs = [seg for seg in ip.split('.')]
    segs = [[int(iter) for iter in seg.split('-')] for seg in segs]
    segs = [range(seg[0], seg[1]+1) if len(seg)==2 else range(seg[0], seg[0]+1) for seg in segs]
    ips = itertools.product(*segs)
    join_fuc = lambda l: '.'.join([str(i) for i in l])
    ips = [join_fuc(ip) for ip in ips]
    syv2
    syv2
    Jan 1, 2016❤️1
    12
    map 改良版,关键地方还是那个 itertools.product 计算笛卡尔积

    import itertools

    ip = "192.168.1-2.1-10"
    segs = [seg for seg in ip.split('.')]
    segs = [[int(iter) for iter in seg.split('-')] for seg in segs]
    segs = [range(seg[0], seg[1]+1) if len(seg)==2 else range(seg[0], seg[0]+1) for seg in segs]
    ips = itertools.product(*segs)
    ips = ['.'.join(map(str, ip)) for ip in ips]
    asxalex
    asxalex
    Jan 1, 2016
    13
    ```python
    def parse_ip(ip):
    return reduce(lambda x,y: [str(i) + "." + str(j) for i in x for j in y],[[int(k)] if k.find("-") < 0 else range(*map(int, *([int(a), int(b)+1] for (a, b) in [k.split("-")]))) for k in ip.split(".")])
    ```
    firebroo
    firebroo
    Jan 1, 2016
    14
    @asxalex ddddddddddddd
    F7EXi3C25zGhO40b
    F7EXi3C25zGhO40b
    Jan 1, 2016
    15
    @asxalex 膜拜 +1
    langyu
    langyu
    Jan 1, 2016❤️2
    16
    有个库 叫 IPy 你直接用就行了
    ringzero
    ringzero
    Jan 1, 2016❤️1
    17
    def ip2num(ip):
    ip = [int(x) for x in ip.split('.')]
    return ip[0] << 24 | ip[1] << 16 | ip[2] << 8 | ip[3]

    def num2ip(num):
    return '%s.%s.%s.%s' % (
    (num & 0xff000000) >> 24,
    (num & 0x00ff0000) >> 16,
    (num & 0x0000ff00) >> 8,
    num & 0x000000ff
    )

    def gen_ips(start, end):
    """生成 IP 地址"""
    # if num & 0xff 过滤掉 最后一段为 0 的 IP
    return [num2ip(num) for num in range(start, end + 1) if num & 0xff]
    Mark3K
    Mark3K
    Jan 1, 2016❤️1
    18
    from itertools import product

    def parse_ip(ip_str):
    return ['.'.join(map(lambda x: str(x), t)) for t in product(*map(lambda x: range(int(x.split('-')[0]), int(x.split('-')[1])+1) if '-' in x else [int(x)], ip_str.split('.')))]
    haroldwu
    haroldwu
    Jan 1, 2016❤️1
    19
    如果像 clojure 一樣有 thread macro ,函數式寫法( reduce map )其實更好用 www
    quietin
    quietin
    Jan 1, 2016❤️1
    20
    4 楼的答案把字符拼接改成'.'.join 就是很好的答案了
    congeec
    congeec
    Jan 1, 2016❤️1
    21
    @ringzero from Python 3.2 we have int.to_bytes
    >>> int.from_bytes(socket.inet_aton('192.168.1.1'), byteorder='big')
    3232235777

    >>> _.to_bytes(length=4, byteorder='big')
    b'\xc0\xa8\x01\x01'

    >>> socket.inet_ntoa(_)
    '192.168.1.1'
    congeec
    congeec
    Jan 1, 2016❤️1
    22
    Python 号称 battery included, 你应该用自带的 ipaddress 库,写起来方便性能还不错
    poke707
    poke707
    Jan 1, 2016❤️1
    23
    基本就是参考 4 楼与 10 楼的优化计算逻辑(分段解析再求笛卡尔积)。
    我来再尝试把代码意图写得更明显些
    https://gist.githubusercontent.com/Ginhing/aae1096546e94921990b/raw/8f5ab916950381f2e433e752b10be8f99c72ba65/ip_segment_parser.py
    hellogbk
    hellogbk
    OP
    Jan 1, 2016
    24
    @poke707
    数学真的很重要啊。 我得去学学数学。
    tt0411
    tt0411
    Jan 1, 2016❤️1
    25
    看来主要技巧是 itertools.product ,我的代码

    https://gist.github.com/7c00/9216518c4e7c35b296b8
    kalsir
    kalsir
    Jan 1, 2016❤️1
    26
    大神们都在炫技
    congeec
    congeec
    Jan 1, 2016 via iPad❤️1
    27
    @syv2 还是你屌。 python 的 itertools, functools, collection 这三个库真是必须掌握呢
    Orzpls
    Orzpls
    Jan 2, 2016 via Android
    28
    马克之。
    menc
    menc
    Jan 3, 2016
    29
    别的不说

    new_ips = [".".join(filter(lambda s: s, map(str,[prefix, ip_segment, suffix]))) for ip_segment in range(start, end +1)]

    这行代码你觉得这个可读性过关么
    Braid
    Braid
    Jan 4, 2016
    30
    @asxalex ddd
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1907 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 87ms · UTC 00:05 · PVG 08:05 · LAX 16:05 · JFK 19:05
    ♥ Do have faith in what you're doing.