• python 杂记


     swagger:https://mp.weixin.qq.com/s/0TzOKmxI3vxN50CYMtxCdQ

     在Python 3中,异常对象在 except代码块作用域之外是无法访问的

    模块之间出现循环依赖(circular dependencies)

    假设你有两个文件,分别是 a.pyb.py,二者相互引用,如下所示:

    a.py文件中的代码:

    b.py文件中的代码:

    首先,我们尝试导入 a.py模块:

    代码运行正常。也许这出乎了你的意料。毕竟,我们这里存在循环引用这个问题,想必应该是会出现问题的,难道不是吗?

    答案是,仅仅存在循环引用的情况本身并不会导致问题。如果一个模块已经被引用了,Python可以做到不再次进行引用。但是如果每个模块试图访问其他模块定义的函数或变量的时机不对,那么你就很可能陷入困境。

    那么回到我们的示例,当我们导入 a.py模块时,它在引用 b.py模块时是不会出现问题的,因为 b.py模块在被引用时,并不需要访问在 a.py模块中定义的任何变量或函数。 b.py模块中对a模块唯一的引用,就是调用了a模块的 foo()函数。但是那个函数调用发生在 g()函数当中,而 a.pyb.py模块中都没有调用 g()函数。所以,不会出现问题。

    但是,如果我们试着导入 b.py模块呢(即之前没有引用 a.py模块的前提下):

    糟糕。情况不太妙!这里的问题是,在导入 b.py的过程中,它试图引用 a.py模块,而 a.py模块接着又要调用 foo()函数,这个 foo()函数接着又试图去访问 b.x变量。但是这个时候, b.x变量还没有被定义,所以才出现了AttributeError异常。

    解决这个问题有一种非常简单的方法,就是简单地修改下 b.py模块,在 g()函数内部才引用 a.py

    现在我们再导入 b.py模块的话,就不会出现任何问题了

    ================================

     在遍历列表时更改列表:能够做到这点的一个编程范式就是列表解析式

    ==================

    错误理解Python中的变量名解析

    上述错误的出现,是因为当你在某个作用域内为变量赋值时,该变量被Python解释器自动视作该作用域的本地变量,并会取代任何上一层作用域中相同名称的变量。

    正是因为这样,才会出现一开始好好的代码,在某个函数内部添加了一个赋值语句之后却出现了 UnboundLocalError,难怪会让许多人吃惊。

    foo1函数并没有为 lst变量进行赋值,但是 foo2却有赋值。我们知道, lst+=[5]只是 lst=lst+[5]的简写,从中我们就可以看出, foo2函数在尝试为 lst赋值(因此,被Python解释器认为是函数本地作用域的变量)。但是,我们希望为 lst赋的值却又是基于 lst变量本身(这时,也被认为是函数本地作用域内的变量),也就是说该变量还没有被定义。

    =====================

    可选参数默认值的设置在Python中只会被执行一次,也就是定义该函数的时候。因此,只有当 foo()函数被定义时, bar参数才会被初始化为默认值(也就是,一个空列表),但是之后每次 foo()函数被调用时,都会继续使用 bar参数原先初始化生成的那个列表

    一个常见的解决办法就是:

    ==============================

    1 导入模块多次和导入一次的效果是一样的

    2 若希望模块能像程序一样被执行,可以使用-m切换开关来执行,如python -m progname args (运行带命令行参数args的progname程序)

    3 模块真正的用处在于它可以保持自己的作用域

    4 告知模块本身是作为程序运行还是导入到其他程序,需要使用__name__变量,被当做程序执行时,__name__的值是__main__,被导入时,值为模块的名字

    5 模块存储在文件中,包就是模块所在的目录,为了让python将目录作为包对待,目录必须包含一个__init__.py的文件(模块)

    6若将__init__.py作为普通模块导入的话,__init__.py模块的内容就是包的内容。如constants包的__init__.py包括PI=3.14,那么可以像下面这样做:import constants  print constants.PI

    7 非常重要的一个知识点,一定要记住

    8 __all__

    __all__定义了模块的公有接口

    若模块有__all__变量,则__all__代表from 模块 import * 代表什么含义

    不在__all__变量中的函数无法通过import *导入,如copy模块中的dispatch_table 不在__all__中,要使用dispatch_table就要通过 from copy import dispatch_table 实现,或先导入copy,再copy.dispatch_table

    若模块没有__all__,则import * 默认导入模块中所有不以下划线开头的全局变量

    9 想看函数的使用说明,可以打印__doc__,如 print(range.__doc__)

    10 找到源码的位置:print copy.__file__

    11 sys.argv列表中,脚本的名字为sys.argv[0]

    12 利用heapq可以求出前N个最大最小值

    import heapq
    
    lyst = [-3, 22, 45, 34, 99, 102, -44]
    low3 = heapq.nlargest(3, lyst)
    top3 = heapq.nsmallest(3, lyst)

    13 

    为了让特殊字符表现得像普通字符一样,需要对它进行转义

    profile模块可用于代码片段效率分析;trace模块可以提供总的分享

    cmd 可以编写命令行解释器

    14 
    re.search 寻找匹配的字符,找到了返回true,没找到返回false
    re.match 从字符串开头匹配,

    =========================

    1 open第3个参数控制着文件的缓冲,取值0则表示无缓冲,直接写磁盘;取值1则表示直接写内存,只有flush或close时才写磁盘;大于1时代表换届区大小(单位是字节),-1(或其他负数)代表使用默认缓冲区大小

    2 sys.stdin sys.stdout sys.stderr :它们都是文件,大部分文件对象的方法它们也可以使用(如read)

    3 随意读取使用seek:seek(offset,whence),其中offset表示偏移的字节数,whence默认是0,表示从文件开头开始偏移,取值1时表示从当前位置开始偏移,取值2时表示从文件结尾移动

    4 tell返回当前文件的位置

     5 读取大文件的方法:

    with open(path,'r') as f:
        for line in f:
            print(line)
    print("+++++++++++")
    with open(path,'r') as f:
        while True:
            line=f.readline()
            if line:
                print(line)
            else:
                break
    print("+++++++++++")

     6 有双下划线的方法是私有方法

    7 前面有下划线的名字都不会被带星号的Import语句导入(from module import *)

    8 判断一个类是否是另一个类的子类:issubclass

    9 在多重继承中,若父类中有相同名字的方法,则先继承的类中的方法会重写后续继承的类中的方法

    10 判断方法是否存在:hasattr(Zcy,'haha')

    调用方法:getattr(Zcy(),'haha')()

    设置方法:

    setattr(Zcy,'oo','ouou')
    print(Zcy.oo)
    
    def pp():
        print('pp')
    setattr(Zcy,'rr',pp)
    Zcy.rr()

    11 

    12 自己的异常类要继承自 Exception

    13 若想将捕获的异常 传递出去,只需调用不带参数的raise

    try:
        print(1/0)
    except ZeroDivisionError:
        print("sdf")
        raise 

    14 捕获多个异常

    try:
        print(1/'sdf')
    except (ZeroDivisionError,TypeError):
        print("sdf")

    15 访问异常对象本是,下面示例中e就是异常对象本身

    try:
        ss=1
        print(ss.split(','))
    except (ZeroDivisionError,TypeError,AttributeError) as e:
        print(e)

     捕获所有异常用   except Exception as e:

    16  调用时间不可知,不建议使用

    17 若子类重写了构造方法,那么一定要调用父类的构造方法,否则子类可能不能正确的初始化

    18 x[-n] 和 x[ len(x)-n] 是一样的

    19 迭代器

    class DD(object):
        def __init__(self):
            self.age=0
        def __iter__(self): #返回一个迭代器
            return self
        def __next__(self): # 实现了__next__ 方法的才是迭代器
            if self.age<5:
                self.age  +=1
                return self.age
            raise StopIteration
    
    sdf=DD()
    try:
        for age in sdf:
            print(age)
        print ('hello')
    
    except Exception as ex:
        print(ex) #没有走到这里

    20 生成器:任何包含yield语句的函数称为生成器

    21 当使用一个负数作为步长时,必须让开始点大于结束点,如:

    y=[11,22,33,5,6,7,8]
    print y[6:0:-2]
    输出:[8, 6, 33]

    22  any: 有一个是真就返回true   【0或“”或false或None 都算是假】

         all:全部是真才返回true     

    23 

     @property装饰器必须先于@setter,@deleter使用,且三者说装饰的函数必须同名

     如果一个方法被@classmethod所装饰,就代表该方法与类绑定,而不是与实例对象绑定

    被@staticmethod所装饰的方法为静态方法,静态方法一般使用场景就是和类相关的操作,但是又不会依赖和改变类、实例的状态,比如一些工具方法

     24

    在 queue 模块中提供了 3种同步的、线程安全的队列,分别由 3个类 Queue【先进先出】、LifoQueue【先进后出】 和 PriorityQueue【优先级队列】,它们的唯一区别是元素取出的顺序不同。并且,LifoQueue 和 PriorityQueue 都是 Queue 的子类。

    25

    event对象的一个重要特点是它被设置为True时会唤醒所有等待它的线程,如果唤醒单个线程的最好用Condition

     
  • 相关阅读:
    PAT L2-014【二分】
    CodeForces 137C【贪心+优先队列】
    CodeForces 131D【图特性+BFS】
    CodeForces 125D【鸽巢原理】
    PAT1060【大模拟啊】
    CodeForces 124C【连通块】
    PAT 1071【STL string应用】
    CodeForces 116C 【BFS】
    CodeForces 116B【二分匹配】
    CodeForces 118C 【模拟】
  • 原文地址:https://www.cnblogs.com/testzcy/p/11065771.html
Copyright © 2020-2023  润新知