初学 Python,此函数求优化 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
请不要在回答技术问题时复制粘贴 AI 生成的内容
hellogbk

初学 Python,此函数求优化

  •  
  •   hellogbk Jan 1, 2016 5360 views
    This topic created in 3769 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
        1
    vanxining  
       Jan 1, 2016 via Android
    楼主是来炫耀的 :-)
    firebroo
        2
    firebroo  
       Jan 1, 2016
    ddd
    hellogbk
        3
    hellogbk  
    OP
       Jan 1, 2016
    @vanxining 额,不是啊。 我是想知道怎么用更少的代码来实现同样的功能。
    semut
        4
    semut  
       Jan 1, 2016   1
    你所说的优化是指什么?运算速度么,还是计算逻辑,这是我的代码:
    #!/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
        5
    k9982874  
       Jan 1, 2016 via iPhone   2
    手机看代码自动换行太难看,所以就是没好好读。
    能给的建议就是把函数参数改成
    parse_ip(ip_header, first_start, first_end, second_start, second_end)

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

    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
        11
    syv2  
       Jan 1, 2016
    上面写错了。。修正一下:


    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
        12
    syv2  
       Jan 1, 2016   1
    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
        13
    asxalex  
       Jan 1, 2016
    ```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
        14
    firebroo  
       Jan 1, 2016
    @asxalex ddddddddddddd
    rim99
        15
    rim99  
       Jan 1, 2016
    @asxalex 膜拜 +1
    langyu
        16
    langyu  
       Jan 1, 2016   2
    有个库 叫 IPy 你直接用就行了
    ringzero
        17
    ringzero  
       Jan 1, 2016   1
    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
        18
    Mark3K  
       Jan 1, 2016   1
    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
        19
    haroldwu  
       Jan 1, 2016   1
    如果像 clojure 一有 thread macro ,函式法( reduce map )其更好用 www
    quietin
        20
    quietin  
       Jan 1, 2016   1
    4 楼的答案把字符拼接改成'.'.join 就是很好的答案了
    congeec
        21
    congeec  
       Jan 1, 2016   1
    @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
        22
    congeec  
       Jan 1, 2016   1
    Python 号称 battery included, 你应该用自带的 ipaddress 库,写起来方便性能还不错
    poke707
        23
    poke707  
       Jan 1, 2016   1
    基本就是参考 4 楼与 10 楼的优化计算逻辑(分段解析再求笛卡尔积)。
    我来再尝试把代码意图写得更明显些
    https://gist.githubusercontent.com/Ginhing/aae1096546e94921990b/raw/8f5ab916950381f2e433e752b10be8f99c72ba65/ip_segment_parser.py
    hellogbk
        24
    hellogbk
    OP
       Jan 1, 2016
    @poke707
    数学真的很重要啊。 我得去学学数学。
    tt0411
        25
    tt0411  
       Jan 1, 2016   1
    看来主要技巧是 itertools.product ,我的代码

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

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

    这行代码你觉得这个可读性过关么
    Braid
        30
    Braid  
       Jan 4, 2016
    @asxalex ddd
    About     Help     Advertise     Blog     API     FAQ     Solana     5177 Online   Highest 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 133ms UTC 09:42 PVG 17:42 LAX 02:42 JFK 05:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86