前言:在使用python过程中会遇到一些编程难题,使用下文提供的方法可以解决这些问题。下文是对自己在项目中遇到问题的总结,目的是以后再遇到相同问题就不用再上网查找了,直接使用下文的方法即可。
1. 将十六进制的字符串转化为整形,比如将“61a37538”转化为整数
>>> a="61a37538"
>>> b=int(a,16)
>>> print(b)
1638102328
解释:int(str,base),int()函数会将字符串str,base(默认是10进制,此处使用16,表示str是16进制)进制,转化为整数。
2. 将整数转化为十六进制字符串,且包含'0x'
>>> hex(12)
'0xc'
>>> hex(100)
'0x64'
解释:hex(int),返回int的十六进制表示字符串,且自带'0x'。
3. CSV文件处理
3.1 写csv文件
with open(filename,'w',newline='') as csvfile:
...
...
解释:
a. 例子中的'w'可以换成'r'——读取文件,'rb'——读取二进制文件
b. with...as...语句会自动帮助我们调用close()方法,所以,后面的代码中我们将不用再调用close函数了
c. newline=''的作用见3.2
3.2 向CSV文件中写入数据
比如我们想以下面的形式写入csv数据:
cw value
21 0x11
22 0x22
23 0x33
... ...
代码:
cw_field='CW'
value_field='Value'
headers=[cw_field,value_field]
with open(filename,'w',newline='') as csvfile:
writer = csv.DictWriter(csvfile,headers)
writer.writeheader()
writer.writerows(trinity_poc_table)
解释:
a. csv.DictWriter(csvfile,headers)以字典方式写入csv文件,且每一列的第一个元素是headers中的元素
b. writer.writeheader()在csv文件的首行写入[cw_field,value_field]:
CW Value
c. trinity_poc_table是一个list,每个元素都是一个字典:
[{'cw': '23', 'value': '0x69465'}, {'cw': '31', 'value': '0xbc000'}, {'cw': '59', 'value': '0x84210'} ,...]
d. 从第二行开始,将把trinity_poc_table按照字典中的对应关系写入csv文件:
CW Value
23 0x69465
31 0xbc000
59 0x84210
...
e. 如果open()中没有newline='',写入csv文件中每一行数据之间都会有一空行,如下所示
CW Value
23 0x69465
31
59
...
4. 删除list中重复元素
4.1 使用set()函数实现
python的set()和其它语言类似,是一个 无序不重复 的元素集,基本功能包括关系测试和 消除重复元素 。
>>> a=[1,2,3,4,1,2,3,4]
>>> b=set(a)
>>> b
{1, 2, 3, 4}
>>> c=list(b)
>>> c
[1, 2, 3, 4]
Note:
a). 该方法在删除重复元素的同时会改变原list的顺序。
>>> a=[4,3,2,1,4,3,2,1]
>>> set(a)
{1, 2, 3, 4}
>>> list(set(a))
[1, 2, 3, 4]
4.2 还有一种使用dict的方法
>>> a=[1,2,3,4,1,2,3,4]
>>> d={}.fromkeys(a).keys()
>>> d
dict_keys([1, 2, 3, 4])
>>> e=list(d)
>>> e
[1, 2, 3, 4]
该方法在删除重复元素的同时不会改变原list的顺序。
>>> a
[4, 4, 3, 3, 2, 2, 1, 1]
>>> b={}.fromkeys(a)
>>> b
{4: None, 3: None, 2: None, 1: None}
>>> b.keys()
dict_keys([4, 3, 2, 1])
>>> list(b.keys())
[4, 3, 2, 1]
Note:
a). dict.fromkeys(S[,v])的用法
fromkeys(...)
dict.fromkeys(S[,v]) -> New dict with keys from S and values equal to v.
v defaults to None.
dict.fromkeys(S[,v])创建了新的字典,其中,key由S决定,value由v决定。如果没有写参数v,value的默认值是None。如果写了参数v,所有key的value都是v。
>>> a=[1,2,3,4,1,2,3,4]
>>> aa={}.fromkeys(a)
>>> aa
{1: None, 2: None, 3: None, 4: None}
>>> a=[1,2,3,4,1,2,3,4]
>>> b="test"
>>> aa={}.fromkeys(a,b)
>>> aa
{1: 'test', 2: 'test', 3: 'test', 4: 'test'}
b). dict.keys()的用法
作用是返回字典的所有keys。返回的类型是dict_keys(),如果要转化为list,需要使用list()函数。
>>> aa
{1: 'test', 2: 'test', 3: 'test', 4: 'test'}
>>> aa.keys()
dict_keys([1, 2, 3, 4])
>>> list(aa.keys())
[1, 2, 3, 4]
c). [扩展]dict.values()的用法
作用是返回字典的所有values。返回的类型是dict_values(),如果要转化为list,需要使用list()函数。
>>> aa
{1: 'test', 2: 'test', 3: 'test', 4: 'test'}
>>> aa.values()
dict_values(['test', 'test', 'test', 'test'])
>>> list(aa.values())
['test', 'test', 'test', 'test']
4.3 使用遍历法
该方法同样不会改变list的顺序。
>>> a=[4,3,2,1,4,3,2,1]
>>> b=[]
>>> [b.append(i) for i in a if i not in b]
[None, None, None, None]
>>> b
[4, 3, 2, 1]
4.3.1 【补充知识】List Comprehensions
a). 目前有这样一个需求,求得序列[0,1,...,9]的平方
>>> squares = []
>>> for x in range(10):
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
可以使用更紧凑的方法:
squares = [x**2 for x in range(10)]
b). for和if搭配使用,if作为filter将不需要的数据排除在外
>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
c). 创建tuple,tuple元素需要用圆括号包起来。
>>> # create a list of 2-tuples like (number, square)
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> # the tuple must be parenthesized, otherwise an error is raised
>>> [x, x**2 for x in range(6)]
File "<stdin>", line 1, in <module>
[x, x**2 for x in range(6)]
^
SyntaxError: invalid syntax
d). 将二维list拆成一维list
>>> # flatten a list using a listcomp with two 'for'
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
5. enumerate()
如果在执行for循环的时候期望打印每一个元素对应的索引号,可以使用enumerate()函数,返回两个值,第一个值是索引号,第二个是索引对应的值。
>>> for i,j in enumerate(["a","b","c"]):
print(i,j)
0 a
1 b
2 c
6. zip()
如果想同时遍历多个( 两个及两个以上 )序列(可以是list,也可以是dict),可以使用zip()函数并将这些序列作为输入参数。
e.g.1 输入序列是list
>>> a=[1,2,3,4]
>>> b=["a","b","c","d"]
>>> c=[11,22,33,44]
>>> for i,j,k in zip(a,b,c):
print(i,j,k)
1 a 11
2 b 22
3 c 33
4 d 44
>>> aa={1,2,3,4}
>>> bb={"a","b","c","d"}
>>> cc={11,22,33,44}
>>> for i,j,k in zip(aa,bb,cc):
print(i,j,k)
1 d 33
2 c 11
3 a 44
4 b 22
7. @classmethod使用方法
classmethod是用来指定一个类的方法为类方法,没有此参数指定的类的方法为实例方法,使用方法为
class cls:
def f(cls,arg1,arg2,...):
7.1 一个例子
有一个类是计算器,可以计算输入list的和、求最大值和最小值。
class calculator:
def __init__(self,*v):
self.data=list(v)
def __sum__(self):
return sum(self.data)
def __max__(self):
return max(self.data)
def __min__(self):
return min(self.data)
calc=calculator(1,2,3,4,5)
print("sum={}".format(calc.__sum__()))
print("max={}".format(calc.__max__()))
print("min={}".format(calc.__min__()))
sum=15
max=5
min=1
一种办法是在使用类前使用一个函数将输入变量进行转化操作,可以将该函数放在类的外面,是否可以放在里面呢?这就要用到@classmethod。
7.2 @classmethod隆重登场
使用上面的例子,calculator类中新增了一个classmethod——convert2list(cls,s),系统默认第一个参数是类(必须有此参数),此时cls是calculator类,第二个参数是输入的字符串。
在实例中调用convert2list的时候,无需写入类的类型(cls),只需有输入参数即可。系统会在调用convert2list函数的时候自动让cls=calculator。
该函数的作用是将输入的字符串转化成int型,然后作为calculator的初始化参数实例化类。
讲解下convert2list()函数中“inst=cls(*d)”。
- cls()本质就是calculator()
- cls(arg1,arg2,arg3,...)是在调用__init__()函数,并将self.data初始化为[arg1,arg2,arg3,...]
- d是一个list,d前面的*是将d展开,并将展开后的元素作为入参。假设d=[1,2,3],如果没有使用*d,[1,2,3]将作为一个整体传入__init__(self, *v)中,即传入的参数是[1,2,3],则v=([1,2,3],)。实际上,我们希望传入的是三个参数1,2,3。*d的作用正是将[1,2,3]展开,传入三个参数,分别是1,2,3
- 最后返回inst,这是一个calculator的实例,其初始值data=[1,2,3]
class calculator:
def __init__(self,*v):
self.data=list(v)
def __sum__(self):
return sum(self.data)
def __max__(self):
return max(self.data)
def __min__(self):
return min(self.data)
@classmethod
def convert2list(cls,s):
if not isinstance(s,str):
raise TypeError
s1=s.split(',')
d=[int(i) for i in s1]
inst=cls(*d) #将list展开,否则,d将被看作一个整体传入
return inst
calc=calculator(1,2,3,4,5)
print("sum={}".format(calc.__sum__()))
print("max={}".format(calc.__max__()))
print("min={}".format(calc.__min__()))
calc=calculator.convert2list('1,2,3,4,5')
print("sum={}".format(calc.__sum__()))
print("max={}".format(calc.__max__()))
print("min={}".format(calc.__min__()))
8. python运算符重载
Python语言本身提供了很多魔法方法,它的运算符重载就是通过重写这些Python内置魔法方法实现的。这些魔法方法都是以双下划线开头和结尾的,类似于__X__的形式,python通过这种特殊的命名方式来拦截操作符,以实现重载。当Python的内置操作运用于类对象时,Python会去搜索并调用对象中指定的方法完成操作。
类可以重载加减运算、打印、函数调用、索引等内置运算,运算符重载使我们的对象的行为与内置对象的一样。Python在调用操作符时会自动调用这样的方法,例如,如果类实现了__add__方法,当类的对象出现在+运算符中时会调用这个方法。
类Vec可以让两个向量做运算,比如,Vec(1,2,3)+Vec(4,5,6)=Vec(5,7,9)
class Vec:
def __init__(self,*v):
self.data=list(v)
@classmethod
def fromlist(cls,v):
if not isinstance(v, list):
raise TypeError
inst=cls()
inst.data=v
return inst
def __add__(self,other):
v=[x+y for x,y in zip(self.data,other.data)]
return self.fromlist(v)
a=Vec(1,2,3)
print(a)
b=Vec(4,5,6)
print(a+b)
可以得到输出:
<__main__.Vec object at 0x020C61F0>
<__main__.Vec object at 0x02143590>
问题出在Vec类中没有__repr__()函数,该函数控制类结果的输出。下面的关于repr的介绍摘自python documententation:
repr
(
object
)
Return a string containing a printable representation of an object. For many types, this function makes an attempt to return a string that would yield an object with the same value when passed to eval(), otherwise the representation is a string enclosed in angle brackets that contains the name of the type of the object together with additional information often including the name and address of the object. A class can control what this function returns for its instances by defining a __repr__() method.
将__repr__函数加入到上述例子中:
class Vec:
def __init__(self,*v):
self.data=list(v)
@classmethod
def fromlist(cls,v):
if not isinstance(v, list):
raise TypeError
inst=cls()
inst.data=v
return inst
def __add__(self,other):
v=[x+y for x,y in zip(self.data,other.data)]
return self.fromlist(v)
def __repr__(self):
return "Vec({})".format(",".join([repr(i) for i in self.data]))
a=Vec(1,2,3)
print(a)
b=Vec(4,5,6)
print(a+b)
得到如下结果:
Vec(1,2,3)
Vec(5,7,9)
Note:
关于Vec类的demo源自 C:\Users\cherish\AppData\Local\Programs\Python\Python36-32\Tools\demo\vector.py