初学 Python,此函数求优化

2016-01-01 12:48:06 +08:00
 hellogbk

大家新年快乐!
我初学 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

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

4729 次点击
所在节点    程序员
30 条回复
vanxining
2016-01-01 13:06:35 +08:00
楼主是来炫耀的 :-)
firebroo
2016-01-01 13:11:28 +08:00
ddd
hellogbk
2016-01-01 13:12:38 +08:00
@vanxining 额,不是啊。 我是想知道怎么用更少的代码来实现同样的功能。
semut
2016-01-01 13:13:05 +08:00
你所说的优化是指什么?运算速度么,还是计算逻辑,这是我的代码:
#!/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
2016-01-01 13:16:29 +08:00
手机看代码自动换行太难看,所以就是没好好读。
能给的建议就是把函数参数改成
parse_ip(ip_header, first_start, first_end, second_start, second_end)

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

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
2016-01-01 13:36:22 +08:00
上面写错了。。修正一下:


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
2016-01-01 13:45:45 +08:00
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
2016-01-01 14:06:21 +08:00
```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
2016-01-01 14:06:47 +08:00
@asxalex ddddddddddddd
rim99
2016-01-01 14:25:58 +08:00
@asxalex 膜拜 +1
langyu
2016-01-01 14:42:47 +08:00
有个库 叫 IPy 你直接用就行了
ringzero
2016-01-01 14:44:09 +08:00
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
2016-01-01 15:01:07 +08:00
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
2016-01-01 15:26:08 +08:00
如果像 clojure 一樣有 thread macro ,函數式寫法( reduce map )其實更好用 www
quietin
2016-01-01 16:04:02 +08:00
4 楼的答案把字符拼接改成'.'.join 就是很好的答案了

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

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

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

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

© 2021 V2EX