【Python练习cookbook】小技巧集锦

0.

0.1 取反:

s=s[::-1]

s=inversed(s)

0.2 三目运算:

h = "变量1" if a>b else "变量2"

0.3 造数组

a1=[0]*8
a1=list(itertools.repeat(0,8))


a2=range(0,8)

a3=[[0]*3 for _ in range(0,5)] #5行3列0
a1=list(itertools.repeat([0]*3,5))



## 误区-浅拷贝
>>> mat=[[0]*3]*3 
>>> mat
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]
>>> mat[0][0]=1
>>> mat
[[1, 0, 0], [1, 0, 0], [1, 0, 0]]

0.4 正负无穷大

python中并没有特殊的语法来表示这些值,但是可以通过 float() 来创建它们:

>>> a = float("inf")
>>> b = float("-inf")
>>> a
inf
>>> b
-inf

0.5 True的数字含义,1

>>> sum([True,False])
1
>>> sum([True,False,True])
2
>>> 0+True
1
>>> 2+True
3

0.6 按列取元素

>>> a=[[1,2,3], [4,5,6]]
>>> a[:, 0]                   # 尝试用数组的方法读取一列失败,这是numpy的用法
TypeError: list indices must be integers or slices, not tuple

>>> b = [i[0] for i in a]     # 从a中的每一行取第一个元素。
>>> print(b)
[1, 4]


>>> a=[[1,2],[3,4],[5,6]]
>>> list(zip(*a))
[(1, 3, 5), (2, 4, 6)]
>>> list(zip(*a))[0]
(1, 3, 5)

# zip可同时zipN个可迭代对象,所以可以用*a来解包裹
>>> b=[[1,2,3],[4,5,6],[7,8,9]]
>>> list(zip(*b))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
>>> a=[1,2,3]
>>> b=[4,5,6]
>>> c=[7,8,9]
>>> list(zip(a,b,c))
[(1, 4, 7), (2, 5, 8), (3, 6, 9)]

0.7 多层循环生成器:

# grid=[[r1],[r2],...]
ans += sum(v > 0 for row in grid for v in row)

1.sum(), min(), max()等可接收iterable参数的,可直接用generator作为参数,可利用此特性减少内存开销。

由于min()和max()还可接收key函数,所以也可用key函数代替generator方式

s = sum((x * x for x in nums)) # 用生成器表达式
s = sum(x * x for x in nums) # 可更精简


portfolio = [
{'name':'GOOG', 'shares': 50},
{'name':'YHOO', 'shares': 75},
{'name':'AOL', 'shares': 20},
{'name':'SCOX', 'shares': 65}
]

# 原始--生成器: Returns 20
min_shares = min(s['shares'] for s in portfolio)
# 可代替: Returns {'name': 'AOL', 'shares': 20}
min_shares = min(portfolio, key=lambda s: s['shares'])

2.字符串连接用join 替代累加+=

 因为每次+=都会创建新的字符串对象,效率低:

s = ''
for p in parts:
    s += p

#不如
''.join(parts)

3.将要被用到的很多小字符串构造成生成器使用

def sample():
    yield 'Is'
    yield 'Chicago'
    yield 'Not'
    yield 'Chicago?'

text = ''.join(sample())

4.vars(),配合foramat_map使用、__missing__处理字典缺失值

#取local变量
>>> s = '{name} has {n} messages.'
>>> name = 'Guido'
>>> n = 37
>>> s.format_map(vars())
'Guido has 37 messages.'

#取对象属性
>>> class Info:
... def __init__(self, name, n):
... self.name = name
... self.n = n
...
>>> a = Info('Guido',37)
>>> s.format_map(vars(a))
'Guido has 37 messages.'

#避免没赋值报错
class safesub(dict):
    def __missing__(self, key):
        return '{' + key + '}'

>>> del n # Make sure n is undefined
>>> s.format_map(safesub(vars()))
'Guido has {n} messages.'

#构造实用函数
import sys
def sub(text):
    return text.format_map(safesub(sys._getframe(1).f_locals))

>>> name = 'Guido'
>>> n = 37
>>> print(sub('Hello {name}'))
Hello Guido
>>> print(sub('You have {n} messages.'))
You have 37 messages.
>>> print(sub('Your favorite color is {color}'))
Your favorite color is {color}

注释:

sys._getframe([depth]):https://docs.python.org/zh-cn/3/library/sys.html#module-sys

depth默认值为0。用于获取frame object(帧对象)情况

def get_cur_info():
    print(sys._getframe().f_code.co_filename)  # 当前文件名,可以通过__file__获得
    print(sys._getframe(0).f_code.co_name) # 当前函数名
    print(sys._getframe(1).f_code.co_name)  # 调用该函数的函数名字,如果没有被调用,则返回<module>
    print(sys._getframe(0).f_lineno) #当前函数的行号
    print(sys._getframe(1).f_lineno) # 调用该函数的行号
    print(sys._getframe(1).f_locals)# 调用该函数的本地变量字典

frame object(帧对象)

帧对象表示执行帧。它们可能出现在回溯对象中 (见下文),还会被传递给注册跟踪函数。

特殊的只读属性: f_back 为前一堆栈帧 (指向调用者),如是最底层堆栈帧则为 Nonef_code 为此帧中所执行的代码对象; f_locals 为用于查找本地变量的字典f_globals 则用于查找全局变量; f_builtins 用于查找内置 (固有) 名称; f_lasti 给出精确指令 (这是代码对象的字节码字符串的一个索引)。

特殊的可写属性: f_trace,如果不为 None,则是在代码执行期间调用各类事件的函数 (由调试器使用)。通常每个新源码行会触发一个事件 - 这可以通过将 f_trace_lines 设为 False 来禁用。

具体的实现 可能 会通过将 f_trace_opcodes 设为 True 来允许按操作码请求事件。请注意如果跟踪函数引发的异常逃逸到被跟踪的函数中,这可能会导致未定义的解释器行为。

f_lineno 为帧的当前行号 --- 在这里写入从一个跟踪函数内部跳转的指定行 (仅用于最底层的帧)。调试器可以通过写入 f_lineno 实现一个 Jump 命令 (即设置下一语句)。

帧对象支持一个方法:

     frame.clear()

此方法清除该帧持有的全部对本地变量的引用。而且如果该帧属于一个生成器,生成器会被完成。这有助于打破包含帧对象的循环引用 (例如当捕获一个异常并保存其回溯在之后使用)。

如果该帧当前正在执行则会引发 RuntimeError

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值