
大家新年快乐!
我初学 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 求指点代码还可以怎么优化,谢谢!
1 vanxining Jan 1, 2016 via Android 楼主是来炫耀的 :-) |
2 firebroo Jan 1, 2016 ddd |
4 semut Jan 1, 2016 你所说的优化是指什么?运算速度么,还是计算逻辑,这是我的代码: #!/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")) |
5 k9982874 Jan 1, 2016 via iPhone 手机看代码自动换行太难看,所以就是没好好读。 能给的建议就是把函数参数改成 parse_ip(ip_header, first_start, first_end, second_start, second_end) 函数内直接 for 循环拼接生成 ip ,不需要再去拆字符串。 字符串操作成本永远是最贵的。 |
6 holyzhou Jan 1, 2016 感觉 一用上 filter , reduce , map , lambda ,列表推倒式这些,程序可读性立马就下去了 |
7 hellogbk OP @semut 谢谢,我指的是代码能不能再少一点。因为我以前学 JAVA 的,所以感觉我在写这个函数的时候还是 JAVA 的思维多一点,就想知道用 python 的想法应该怎么写。 |
8 wowpanda Jan 1, 2016 正则 |
9 am241 Jan 1, 2016 只求代码更少可以用正则吧 |
10 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] ips = itertools.product(*segs) join_fuc = lambda l: '.'.join([str(i) for i in l]) ips = [join_fuc(ip) for ip in ips] |
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] |
12 syv2 Jan 1, 2016 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] |
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(".")]) ``` |
16 langyu Jan 1, 2016 有个库 叫 IPy 你直接用就行了 |
17 ringzero Jan 1, 2016 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] |
18 Mark3K Jan 1, 2016 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('.')))] |
19 haroldwu Jan 1, 2016 如果像 clojure 一有 thread macro ,函式法( reduce map )其更好用 www |
20 quietin Jan 1, 2016 4 楼的答案把字符拼接改成'.'.join 就是很好的答案了 |
21 congeec Jan 1, 2016 @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' |
22 congeec Jan 1, 2016 Python 号称 battery included, 你应该用自带的 ipaddress 库,写起来方便性能还不错 |
23 poke707 Jan 1, 2016 基本就是参考 4 楼与 10 楼的优化计算逻辑(分段解析再求笛卡尔积)。 我来再尝试把代码意图写得更明显些 https://gist.githubusercontent.com/Ginhing/aae1096546e94921990b/raw/8f5ab916950381f2e433e752b10be8f99c72ba65/ip_segment_parser.py |
25 tt0411 Jan 1, 2016 |
26 Gothack Jan 1, 2016 大神们都在炫技 |
28 Orzpls Jan 2, 2016 via Android 马克之。 |
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)] 这行代码你觉得这个可读性过关么 |