zoukankan      html  css  js  c++  java
  • python易错点2

    8. __init__函数内不可以使用return语句

    Python规定__init__函数只能返回None,否则会引起TypeError

    9. 在try…except…finally中return

    • try和except中return语句设定的返回值,可以在finally块中被修改;
    • 实践中不要在finally中使用return,这是一种不好的代码,容易让人产生疑惑。finally块主要用于进行清理工作。

    Python札记7:在try...except...finally中return

    不论try语句块中发生了什么异常,finally语句块中的代码都会被执行。所以我们通常在finally语句块中做清理工作,例如关闭文件等等

    请看下面的代码,输出是什么呢?

    def f():
      try:
        return 1
      finally:
        print("hehe")
    
    print(f())
    

      finally块中的代码必定执行,所以输出如下:

     也就是说,虽然try中有return语句,但是退出try...finally块之前,也一定会执行finally块中的语句。

     

     

     

     

    10. os.path的abspath()和realpath()区别

    • os.path.abspath 返回目标地址,会处理.,等相对路径,不处理软连接和快捷方式
    • os.path.realpath 返回的是使用软链的真实地址,它能在所有的平台上对所有别名、快捷方式以及符号链接进行一致地解析。
    # 特殊的文件名,比如 “..” 会被移除,这样输入在验证之前会被简化成其标准形式。
    当使用标准形式的文件路径来做验证时,攻击者将无法使用 ../ 序列来跳出特定目录

    11. python中and与or的逻辑

    首先,‘and’、‘or’和‘not’的优先级是not>and>or。

    其次,逻辑操作符and 和or 也称作短路操作符(short-circuitlogic)或者惰性求值(lazy evaluation):它们的参数从左向右解析,一旦结果可以确定就停止。例如,如果A 和C 为真而B 为假, A and B and C 不会解析C 。作用于一个普通的非逻辑值时,短路操作符的返回值通常是最后一个变量。因此,逻辑运算符的理解也与C语言中不同

    a = {1, 2, 3} and {4, 5, 6}
    b = {1, 2, 3} or {4, 5, 6}
    print(a) # {4, 5, 6}
    print(b) # {1, 2, 3}
    

    其实python中and并不是直接返回True/False,而是返回比较的值,具体如下逻辑:
    and:停止的目标为False, 如果有True,一直往下找,直到返回最后一个或者第一个False
    or: 停止的目标为True,如果有False,一直往下找,直到返回最后一个或者第一个True

    12. 字符串,bool,序列对象等都可以比较

    1.2 > True  # True
    1 > True  # False
    bool('0')  # True
    

    字符串也好,列表也好,都是可迭代对象。先比较两个对象的第0个元素,大小关系即为对象的大小关系(字典序),如果相等则继续比较后续元素,先终止迭代的认为是小的。序列对象通常可以与相同序列类型的其他对象比较。

    [1,5]<[3,4,6] # True
    [1,4,[5,6]]<[3,4,6] # True
    [3,4,[5,6]]<[3,4,6] # TypeError: '<' not supported between instances of 'list' and 'int'

    13. 字符串格式化

     https://blog.csdn.net/qq_27825451/article/details/105652244

    14. @classmethod与@staticmethod

     Python中的类也是一个普通对象,如果需要直接使用这个类,例如将类作为参数传递到其他函数中,又希望在实例化这个类之前就能提供某些功能,那么最简单的办法就是使用classmethod和staticmethod。这两者的区别在于在存在类的继承的情况下对多态的支持不同。

    类方法的作用:(不依赖于对象)

    因为只能访问类属性和类方法,所以,可以在对象创建之前如果需要做一些功能(动作),就可以放在类方法中

    私有属性只能通过类方法,在类内部进行访问

    静态方法:很类似类方法

    1.需要装饰器@staticmethod

    2.静态方法是无需传递参数(如,cls,self)

    3.静态方法里面也只能访问类的属性和方法,而对象的属性和方法是无法访问的(即,用self.xx访问属性和访问方法是不可以的)

    4.加载时机同类方法,即在对象还没有创建时,就已经加载了

    class Spam(object):
        numInstances = 0
     
        @staticmethod
        def count():
            Spam.numInstances += 1
     
        def __init__(self):
            self.count()
     
     
    class Sub(Spam):
        numInstances = 0
     
     
    class Other(Spam):
        numInstances = 0
     
     
    x = Spam()
    y1, y2 = Sub(), Sub()
    z1, z2, z3 = Other(), Other(), Other()
    # 对象调用
    print(x.numInstances, y1.numInstances, z1.numInstances)
    # 类调用
    print(Spam.numInstances, Sub.numInstances, Other.numInstances)
    

      

     总共六次加载对象,静态方法在对象还没有创建之前就已经加载了了,因此x.numInstances=6,而另外两个是Spam的子类,创建对象后,又执行了y1.numInstances,y2.numInstances,因此,y1.numInstances=0,y2.numInstances=0

    Spam.numInstances, Sub.numInstances, Other.numInstances分别是访问它们类的属性

     

     

    https://www.cnblogs.com/GumpYan/p/12381705.html

    15. 防范会话固定,应采取以下步骤:

    • 登录时,使当前会话无效,并建立一个新的会话。
    • 不要接受以GET 或POST参数方式提交的会话 ID,包括隐藏的表单变量。
    • 在所有cookie上设置HttpOnly属性为true,以防范脚本读取cookie内容。
    • 在所有cookie上将Secure(安全)属性设置为true,使其只能通过TLS连接发送。
    • 在会话cookie上设置合理的失效日期。

    15.1 系统环境变量是属于“不可信数据”,直接使用不可信数据可能会引入安全风险

    import  os
    home = os.getenv('APPHOME')
    cmd = os.path.join(home, INITCMD)
    os.system(cmd)
    

      其中环境变量APPHOME对应的路径是可修改的,直接使用会造成安全风险。

    16. shell命令

    Subprocess安全

    subprocess模块的用法, run/Popen/call/check_call/check_output 在使用时指定shell参数为False时,都会存在命令注入缺陷。(第一个参数禁止使用cmd/bash
    切记第1个参数中的list列表的第一个元素不允许是“bash”、“cmd”、“/bin/sh第二个元素不允许是“-c;只有满足了这两个前提条件,参数shell=True情况才是安全的。

    subprocess模块的用法, Popen/call/check_call/check_output 在使用时指定shell参数为False时,都会存在命令注入缺陷。(第一个参数禁止使用cmd/bash,第二个元素不允许是“-c”)。如果不可避免的要设置shell为true,应将命令作为单一字符串传递,并使用shelx.quote()手动转义所有shell元字符。

    Python安全编程规范V2.1

    规则 1.8 禁止使用subprocess模块中的 shell=True选项

     

     

     subprocess模块中的 shell=Flase场景的第1个参数为什么不能是cmd/bash/sh等系统命令

    17. 随机数的安全

    根据安全规范6.5:
    os.urandom在windows系统中生成的随机数是安全的,在linux系统环境中生成的随机数不安全。
    random模块生成的是伪随机数,不能应用于安全加密目的的应用中
    安全随机数可以使用:/dev/random,Python3.6以上的secrets模块

    18. 全局常量用全大写,全局变量用小写

    19. 避免直接使用dict[key]的方式从字典中获取value

    如果一定要使用,需要注意当key not in dict时的异常捕获和处理。应始终使用get,即dict.get(key),而不是dict[key]

    20. 避免变量在其生命周期内的对象类型发生变化。

    如:

    items = 'a,b,c,d' # 字符串
    items = items.split(',') # 变更为列表

    21. 验证路径之前应该先将其标准化

    使用os.path.realpath('test') 而非os.path.abspath('test')。 Path().resolve()好像类似。

    22. Server端发起网络请求前要验证是否存在SSRF漏洞。

    SSRF(Server-SideRequest Forgery, 服务端请求伪造)

    应该先对url做ssrf校验

    url = sys.argv[1]
    try:
        info = urllib.request.urlopen(url).info()
        print(info)
    except urllib.error.URLError as e:
        print(e)

    规避SSRF漏洞的思路:

    1. 解析目标URL,获取其Host
    2. 解析Host,获取Host指向的IP地址
    3. 检查IP地址是否为内网IP
    4. 请求URL
    5. 如果有跳转,拿出跳转URL,回到第1步循环此过程

    23. 禁止使用tempfile.mktemp创建临时文件

    使用tempfile.mkstemp()NamedTemporaryFile()mkdtemp(), 而非tempfile.mktemp()

    24. 禁止使用私有或者弱加密算法

    比如DES,MD5等

    25. 使用ssl.SSLSocket代替socket.Socket来进行安全数据交互

    26. 代码发布前务必删除开发者信息及包含开发者信息的注释内容

    Python代码中的注释不能体现的信息有:工号、姓名、部门、邮箱等。

    27. 在except分支里面的raise可以不带异常

    28. 防范会话固定的最佳实践

    用户成功登陆后,应立即使原有会话ID失效,并建立一个新的会话ID。

    29. 关于跨站脚本的一些叙述

    √假定所有输入都是不可信的
    ×应该对所有不可信数据进行十六进制编码,然后给字符串两边加等号
    ×JavaScrip在访问cookie内容时,如果数据已使用字符进行转义,JavaScrip应该被视为可信的
    √向网页内容注入恶意标记或脚本,会窃取cookie、劫持会话或将页面重定向到恶意网址

    30. 常用来维持对象状态一致性的手段

    • 优化代码逻辑,避免修改对象的状态
    • 调整逻辑顺序,使可能发生异常的代码在对象被修改前执行
    • 当业务操作失败时,进行回滚
    • 对一个临时的副本对象进行所需的操作,直到成功完成这些操作后,才把更新提交到原始的对象
    • 对参数进行校验,提前避免异常

    31. 避免SQL注入的推荐做法

    使用预处理语句或者参数化查询创建动态查询

    32. 最安全的序列化格式:JSON

    33. pdb基本用法

    使用pdb进行调试:

    pdb 是 python 自带的一个包,为 python 程序提供了一种交互的源代码调试功能,主要特性包括设置断点、单步调试、进入函数调试、查看当前代码、查看栈片段、动态改变变量的值等。pdb 提供了一些常用的调试命令,详情见表 

    python调试:pdb基本用法(转)

     下面结合具体的例子说明:

    import pdb
    a = "aaa"
    pdb.set_trace()
    b = "bbb"
    c = "ccc"
    final = a + b + c
    print(final)
    开始调试:直接运行脚本,会停留在 pdb.set_trace() 处,选择 n+enter 可以执行当前的 statement。在第一次按下了 n+enter 之后可以直接按 enter 表示重复执行上一条 debug 命令。
    n表示执行下一行

     退出 debug:使用 quit 或者 q 可以退出当前的 debug,但是 quit 会以一种非常粗鲁的方式退出程序,其结果是直接 crash。

    输入了q之后:

    33.1  pdb有2种用法:

    非侵入式方法(不用额外修改源代码,在命令行下直接运行就能调试)

    python3 -m pdb filename.py

    侵入式方法(需要在被调试的代码中添加一行代码然后再正常运行代码)

    import pdb;pdb.set_trace()

    当你在命令行看到下面这个提示符时,说明已经正确打开了pdb

    (Pdb)

    然后就可以开始输入pdb命令了,下面是pdb的常用命令

    34. 哈希表的查找

    哈希表:存放键值(地址)和数值的存储结构
    哈希函数:把数值映射(帮这个数值找一个地址)到地址的函数
    为了能有效运用查找技术,必须解决的问题是:构造一个好的哈希函数,确定一个解决冲突的方法

      • 哈希函数的构造方法:
        • 直接定址法:直接以关键字(本身数值)或关键字加上某个常量作为地址
          好处:计算简单
          缺点:关键字不连续的时候会造成内存浪费()就比如说:12跟134
        • 除留余数法:关键字除以一个整数p所得余数作为哈希地址(p小于等于哈希表长度m,但p最好小于m的素数,这种效果最好)
        • 数字分析法:提取关键字中取值较均匀的数字作为哈希地址
      • 哈希冲突的解决方法
        • 开放定址法:就是这个位置用不了,那我就去找用得了的位置)
          然后找用空闲位置的方法又有:
        • 线性探测法:就是这个位置用不了,那就从后面的位置依次寻找空闲的位置)
          缺点:容易发生堆聚现象;堆聚就是存入哈希表的若干个同义词(产生地址冲突的数据)在表中连成一片,占用了其他关键字的映射位置。
        • 平方探测法
        • 拉链法:把产生冲突的位置放在一个单链表里)

    例子1:

     例子2:

     例子3:

    30%7=2

    14%7=0

    40%7=5

    63%7=0

    22%7=1

    5%7=5

    34.1 二次探测再散列处理

    哈希表有14个桶,h(key)=key%11,现有18,37,55,61,79,如果用二次探测再散列处理冲突,则39位于第(D)个桶内。

    A 6  B 8   C 4  D 10

    解析:

    18,37,55,61,79  和11除余分别是:  7 4 0 6 2. 没有冲突,分别放入对应桶中

    39%11=6, 被占用,  按照+1, -1, +4, -4, +9, -9... 的规则探测

    (6 +1)%11 = 7 被占用

    (6 - 1)%11 = 5 没被占用,放入5号桶

    (6 +4)%11=10放入10号桶

  • 相关阅读:
    centos vps 安装socks5服务
    C#解析Json的类
    C# MD5 SHA1 SHA256 SHA384 SHA512 示例 标准版 专业版 旗舰版
    SunOS 4上MySQL详尽事变
    Solaris 2.7上MySQL 属意事故
    MySQL字符串
    MySQL安设布局
    运用PerlDBI/DBD接口的成绩
    MySQL 支撑的利用体系
    使用MySQL哪个版本
  • 原文地址:https://www.cnblogs.com/GumpYan/p/14140726.html
Copyright © 2011-2022 走看看