defclock(label, cmd): res = timeit.repeat(cmd, setup=SETUP, number=TIMES) print(label, *(f'{x:.3f}'for x in res))
clock('listcomp :', '[ord(s) for s in symbols if ord(s) > 127]') clock('listcomp + func :', '[ord(s) for s in symbols if non_ascii(ord(s))]') clock('filter + lambda :', 'list(filter(lambda c: c > 127, map(ord, symbols)))') clock('filter + func :', 'list(filter(non_ascii, map(ord, symbols)))') ''' output: listcomp : 0.009 0.010 0.008 0.008 0.009 listcomp + func : 0.014 0.013 0.011 0.014 0.011 filter + lambda : 0.013 0.014 0.012 0.010 0.010 filter + func : 0.010 0.009 0.010 0.009 0.009 '''
1.2.3笛卡尔积
示例 使用列表表达式计算笛卡尔积
先按颜色再按尺寸排列,生成一个元组列表
1 2 3 4 5 6 7
colors = ['black', 'white'] sizes = ['S', 'M', 'L'] tshirts = [(color, size) for color in colors for size in sizes] tshirts ''' output:[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'), ('white', 'M'), ('white', 'L')] '''
双层循环打印
1 2 3 4 5 6
for color in colors: for size in sizes: print((color, size)) ''' output:('black', 'S') ('black', 'M') ('black', 'L') ('white', 'S') ('white', 'M') ('white', 'L') '''
先按尺寸再按颜色排列,只需调整for子句的顺序。
1 2 3 4 5 6
shirts = [(color, size) for size in sizes for color in colors] tshirts ''' output:[('black', 'S'), ('black', 'M'), ('black', 'L'), ('white', 'S'), ('white', 'M'), ('white', 'L')] '''
列表表达式的作用很单一,就是构建列表。如果想使用其它类型的序列,则应当使用生成器表达式。
1.3.4 生成器表达式
生成器表达式的句法跟列表表达式几乎一样,只不过把方括号换为圆括号而已。
示例
1 2 3 4 5
symbols = '$¢£¥€¤' tuple(ord(symbol) for symbol in symbols) ''' output:(36, 162, 163, 165, 8364, 164) '''
1 2 3 4 5
import array array.array('I', (ord(symbol) for symbol in symbols)) ''' output:array('I', [36, 162, 163, 165, 8364, 164]) '''
示例 使用生成器表达式计算笛卡尔积
1 2 3 4 5 6 7 8 9 10 11 12
colors = ['black', 'white'] sizes = ['S', 'M', 'L'] for tshirt in (f'{s}{c}'for c in colors for s in sizes): print(tshirt) ''' output:S black M black L black S white M white L white '''
注意,生成器表达式逐个产出项。这个示例不会构建包含六个T恤组合的列表。
1.3 元组不仅仅是不可变列表
1.3.1 用作记录
用元组存放记录,元组中的一项对应一个字段的数据,项的位置决定数据的意义。
示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
lax_coordinates = (33.9425, -118.408056) city, year, pop, chg, area = ('Tokyo', 2003, 32450, 0.66, 8014) traveler_ids = [('USA', '31195855'), ('BRA', 'CE342567'), ('ESP', 'XDA205856')] for passport insorted(traveler_ids): print('%s/%s' % passport) for country, _ in traveler_ids: print(country) ''' output: BRA/CE342567 ESP/XDA205856 USA/31195855 USA BRA ESP '''
defmain(): print(f'{"":15} | {"latitude":>9} | {"longitude":>9}') for name, _, _, (lat, lon) in metro_areas: if lon <= 0: print(f'{name:15} | {lat:9.4f} | {lon:9.4f}')
if __name__ == '__main__': main() ''' output: | latitude | longitude Mexico City | 19.4333 | -99.1333 New York-Newark | 40.8086 | -74.0204 São Paulo | -23.5478 | -46.6358 '''
1.5 序列模式匹配
match/case处理序列示例
1 2 3 4 5 6 7 8 9 10 11 12
# def handle_command(self, message): # match message: # case ['BEEPER', frequency, times]: # self.beep(times, frequency) # case ['NECK', angle]: # self.rotate_neck(angle) # case ['LED', ident, intensity]: # self.leds[ident].set_brightness(ident, intensity) # case ['LED', ident, red, green, blue]: # self.leds[ident].set_color(ident, red, green, blue) # case _: # raise InvalidCommand(message)
defmain(): print(f'{"":15} | {"latitude":>9} | {"longitude":>9}') for record in metro_areas: match record: case [name, _, _, (lat, lon)] if lon <= 0: print(f'{name:15} | {lat:9.4f} | {lon:9.4f}') main() ''' output: | latitude | longitude Mexico City | 19.4333 | -99.1333 New York-Newark | 40.8086 | -74.0204 São Paulo | -23.5478 | -46.6358 '''