Python小技巧-杂

会持续更新

在更新变量前必须进行初始化

下面是统计一串字符串中各个字符出现次数的代码

1
2
3
4
5
6
7
8
9
n='aabbbcdeeee'
dic=dict()
for i in n:
if i not in dic: # _ in dictobj只会遍历其key
dic[i]=0
else:
dic[i]+=1
print(dic)

重点在dic[i]=0dic[i]+=1
错误的写法:

1
2
for i in n:
dic[i]+=1

dic[i]=0为初始化过程,没了这一步就会报错

如何判断数据类型

现在有s="abc"
判断:

1
2
3
4
5
6
7
8
#1
isinstance(s,str) # --> True

#2
type(s) # --> <class 'str'>

#所以可以这样写
type(s) is str # --> True

is的作用是用来检查两者引用的对象是否相同(或者说是指向的内存地址是否相同)

(列表的)切片除了返回一个副本,还可以表示一个范围来进行赋值

1
2
3
4
5
6
7
l = ['a', 'b', 'c', 'd', 'e']
l[1:3] = [1, 2]
print(l)
# --> ['a', 1, 2, 'd', 'e']
l[1:1]=[5,2,0]
print(l) #这种巧妙的方法可以用来插入元素,但可读性差
# --> ['a', 5, 2, 0, 1, 2, 'd', 'e']

字符串的比较

按照字典序,依次对应比较字符的ASCII码值,一旦比出来就不比了

1
print('abcdefg' < 'b')  # -->  True

一些列表和字符串方法的注意点

1
2
3
4
5
6
'a b'.strip()  # 正确

l = [1, 2, 3, 0]
l = l.sort() # 错误!!!l.sort() return None
# 正确写法:l.sort()
# 或者:l=l.sorted() l.sorted() return list

删除列表元素的各种方法

  1. listobj.pop(index) return 被删除的值
    举例:
    1
    2
    3
    4
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    result = l.pop(5)
    print(l)
    print(result)
    1
    2
    [1, 2, 3, 4, 5, 7, 8, 9, 10]
    6
  2. listobj.remove(value) return None
    举例:
    1
    2
    3
    4
    l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    result = l.remove(5)
    print(l)
    print(result)
    1
    2
    [1, 2, 3, 4, 6, 7, 8, 9, 10]
    None
  3. 直接del del listobj[index]del listobj[start_index:end_index]
    不会产生任何输出

for i in dictobj问题

只会变遍历字典中的键!!
若要遍历值for i in dictobj.values()
应用:

1
2
3
4
5
6
7
8
9
10
def reverse_loopup(dictobj, target_value, multi=True):
l = []
for key in dictobj:
if dictobj[key] == target_value:
if multi == False:
return key
l.append(key)
if len(l) != 0:
return l
raise LookupError("Can't Find The Key")

multi的作用是是否寻找出所有该值对应的键(因为一个值是可以被多个键所关联的)

局部变量问题

局部变量:一个缩进体中的变量即为这个块的局部变量

1
2
3
for i in range(10):
i+=1
print(i) #X

这是错误的,i只在for loop体里有效

1
2
3
4
5
6
7
been_called=False
def f():
been_called=True
print('bc in func:',been_called)

f()
print('bc in __main__:', been_called)

1
2
bc in func: True
bc in __main__: False

也就是说这两个同名的变量并不是同一个东西
如果一定要修改全局been_called的值,可以用global声明变量

1
2
3
4
5
6
7
8
9
10
11
been_called = False


def ff():
global been_called
been_called = True
print('bc in func:', been_called)


ff()
print('bc in __main__:', been_called)

1
2
bc in func: True
bc in __main__: True

元组、列表的分散和收集

1
2
3
4
def f(*args):
print(args)

f(1,2,3,4,5)

1
(1, 2, 3, 4, 5)

*在这里的作用是收集,把所有的参数合并为一个元组
其中按位实参用**收集,返回dict(按位实参就是上文reverse_loopup()中的multi=True)


举例:

1
2
3
4
5
6
def f(*args, **kargs):
print(args, kargs)


f(1, 2, 3, 4, 5, sixth=6)

1
(1, 2, 3, 4, 5) {'sixth': 6}

注:sixth不能打上引号,=后的数据类型不限制


对于列表的分散:

1
2
3
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
print(l)
print(*l)

1
2
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
1 2 3 4 5 6 7 8 9 10

元组的定义和交换

元组不一定要用()括起来,t=1,2也是个元组表达式,对于只有一个元素的元组需要以,结尾,t=1,

1
2
3
a=1
b=2
a,b=b,a

这里就用到了元祖的交换,不需要第三者变量就能实现swap

三元条件

1
2
3
4
5
6
7
8
import math
y = 0
x = int(input(':'))
if x > 0:
y = math.log(x)
else:
y = float('nan')
print(y)

可简化为:

1
2
3
4
import math
x = int(input(':'))
y=math.log(x) if x>0 else float('nan')
print(y)

语句 if 条件表达式 else 语句
如果if后的条件成立则执行最开始的语句,否则执行最后的语句

利用zip()同时遍历两个列表

zip()绑定两个序列中的元素为元组(一一对应,取两者中短的)

1
2
3
4
l1 = ['a', 'b', 'c', 'd', 'e']
l2 = [1, 2, 3, 4, 5]
for i in zip(l1, l2):
print(i)

得:

1
2
3
4
5
('a', 1)
('b', 2)
('c', 3)
('d', 4)
('e', 5)

不等长的时候:

1
2
3
4
l1 = ['a', 'b', 'c', 'd', 'e']
l2 = [1, 2, 3, 4, 5, 6, 7, 8, 9]
for i in zip(l1, l2):
print(i)

结果和上一个相同

#any()和all()
都接受由布尔值组成的序列,例如list和generation expression

1
2
any([False,True,False]) # -->  True
all([False,True,False]) # --> False

listobj.append()与listobj.extend()

  • listobj.append()接受单个元素
  • listobj.extend()接受列表

两者功能相似

1
2
3
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
l.append(114514)
print(l)


[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 114514]


1
2
3
l = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
l.extend([1, 1, 4, 5, 1, 4])
print(l)


[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 1, 4, 5, 1, 4]