python代码编码的一些常用规范

Posted by Qiyibaba on April 15, 2022

需要对入参进行合法校验

v = input("please input your ID card:")

if re.match("\d{17}[\d|x]|\d{15}",v):
    print("合法身份证号")
else:
    print("非法身份证号")

SQL参数化

为防止SQL注入,我们需要在传入参数时进行参数化

def select(sql,params= None):
    print("begin to run sql [{}]".format(sql))
    cnx = None
    cursor = None
    try:
        cnx = connector.connect(**cc)
        cursor = cnx.cursor(dictionary=True)
        cursor.execute(sql,params)
        records = cursor.fetchall()
        return records
    except connector.Error as err:
        if err.errno == connector.errorcode.ER_ACCESS_DENIED_ERROR:
            print("Something is wrong with your user name and password!")
        elif err.errno == connector.errorcode.ER_BAD_DB_ERROR:
            print("Database dosen't exist")
        else:
            print(err)
        exit(1)
    finally:
        if cursor:
            cursor.close()
        if cnx:
            cnx.close()

print(select("select * from test.tn where a = %s",("1",)))
print(select("select * from test.tn"))
# 尝试进行注入,返回结果仍是空
print(select("select * from test.tn where a = %s",("1 or 1 = 1",)))

获取文件路径要使用全路径

print(os.path.realpath("a.txt"))

避免使用os.system

os.system("cat /etc/passwd | grep root")

替换写法:

def run(commands, print_output=True):
    from subprocess import Popen, PIPE, STDOUT
    from io import StringIO

    sout = None

    for command in commands:
        popen = Popen(command,
                      stdin=sout,
                      stdout=PIPE,
                      stderr=STDOUT,
                      universal_newlines=True)
        sout = popen.stdout
    out = StringIO()
    for line in sout:
        if print_output:
            print(line, end='')
        else:
            out.write(line)

    popen.stdout.close()
    return_code = popen.wait()

    if not return_code == 0:
        raise RuntimeError(
            'The process call "{}" returned with code {}. The return code is not 0, thus an error '
            'occurred.'.format(list(command), return_code))

    stdout_string = out.getvalue()
    out.close()

    return stdout_string


run((["cat", "/etc/passwd"], ["grep", "root"]))
run(["ls"])

随机数生成

# 生成随机整数
import secrets
for i in range(0,20):
    print(secrets.randbelow(10))
# 生成随机密码
import string
allowed_chars = string.ascii_letters + string.digits + string.printable
pswd = ''.join(secrets.choice(allowed_chars) for i in range(8))
print("The generated password is: \n",pswd)

None值判断使用is或者not is

def checkNone(value=None):
    if value is None:
        print("is null")
    else:
        print("is not null")

checkNone() #is null
checkNone("abc") #is not null

class test():
    def __eq__(self, other):
        return True
        
t = test()
print(t is None) # False
print(t == None) # True
# is None是判断两个对象在内存中的地址是否一致,== None背后调用的__eq__(),而__eq__()可以被重载,万一被重载,会造成一定影响,如上例子里面的==判断就不正确
# None在Python里是个单例对象,一个变量如果是None,它一定和None指向同一个内存地址。None是python中的一个特殊的常量,表示一个空的对象,空值是python中的一个特殊值。数据为空并不代表是空对象,例如[],''等都不是None。None和任何对象比较返回值都是False,除了自己。

dict字典取值

dic={"a":1,"b":2}

#dict[]方式取值,当值不存在需要进行异常处理
try:
    print(dic["c"])
except KeyError:
    print("key not exists!")
#dict.get()方式不会抛出异常
print(dic.get("c"))

isinstance和type区别

class GrandFather:pass
class Father(GrandFather):pass
class Son(Father):pass
son = Son()
print(type(GrandFather)) #type
print(type(Father))#type
print(type(Son))#type
#上述代码结果都为<class 'type'>,type就是内置的元类,class关键字定义的所有的类以及内置的类都是由元类type实例化产生。

print(type(son) is Son) #True
print(type(son) is Father )#False
print(type(son) is GrandFather )#False

print(isinstance(son,Son))#True
print(isinstance(son,Father))#True
print(isinstance(son,GrandFather))#True

isinstance() 函数来判断一个对象是否是一个已知的类型,类似 type() isinstance() 与type() 区别: type() 不会认为子类是一种父类类型,不考虑继承关系 isinstance() 会认为子类是一种父类类型,考虑继承关系如果要判断两个类型是否...

使用推导式

'''
格式:
列表(list)推导式:[i for i in 可迭代对象 if 条件]
字典(dict)推导式:{i for i in 可迭代对象 if 条件}
集合(set)推导式 :{i for i in 可迭代对象 if 条件}
'''

print([i*i for i in range(10)]) # 计算1到10的平方
print([i*i for i in range(10) if i%2 == 0])# 计算1到10的偶数平方

'''
还可以配合lambda函数使用:lambda argument(s):expression
lambda可以有很多个参数,但是只能有一个表达式。lambda操作符不能有任何声明,它返回一个函数对象,我们可以将此函数对象赋值给任何变量。
'''

# 一个经典的case:
def multipliers1(): 
    return  [lambda x,: i * x for i in range(4)]
print([m(2) for m in multipliers1()])
# 返回6,6,6,6
def multipliers2(): 
    return [lambda x,y=i: y * x for i in range(4)]
print([m(2) for m in multipliers2()])
#返回0, 2, 4, 6
'''
为什么第一个返回的结果是6,6,6,6内,实际lambda只是生成了4个函数表达式,真正执行的时候是在print阶段了,而此时循环已经结束,i已经变成了最终数值3,所以返回的都是同一值
第二个的区别是在lambda参数中添加了一个常量,常量就需要在初始化的时候需要知道具体的数值,那生成出来的函数表达式就是带着循环数值进来的。
'''

使用tuple也可以元组是有序且不可更改的集合 Python 元组是用圆括号编写的