python 语法杂记

模块

相对导入

当前执行文件不能进行相对导入,
只有被导入包里的文件可以进行相对导入
和被执行文件同一目录的包是顶层包,顶层包之间不能互相引用

inspect

def v2():
    for frame in inspect.stack():
        print(frame[3])
def v1():
    v2()
def main():
    v1()
if __name__ == "__main__":
    main()
v2
v1
main
<module>

语法

闭包

用比较容易懂的人话说,就是当某个函数被当成对象返回时,夹带了外部变量,就形成了一个闭包。看例子

如果想在闭包中修改外部函数变量,需要加nolocal关键字。这个和global关键字类似。

def nonlocal_test():
    count = 0
    def test2():
        nonlocal count
        count += 1
        return count
    return test2
 
val = nonlocal_test()
print(val())
print(val())
print(val())

装饰器

装饰器函数其实是这样一个接口约束,它必须接受一个callable对象作为参数,然后返回一个callable对象

简单的装饰器

def debug(func):
    def wrapper(*args, **kwargs):  # 指定宇宙无敌参数
        print "[DEBUG]: enter {}()".format(func.__name__)
        print 'Prepare and say...',
        return func(*args, **kwargs)
    return wrapper  # 返回

@debug
def say(something):
    print "hello {}!".format(something)

带参数的装饰器

其中变量level闭包

def logging(level):
    def wrapper(func):   
        def inner_wrapper(*args, **kwargs):
            print "[{level}]: enter function {func}()".format(
                level=level,  #  ****这里是闭包****
                func=func.__name__)
            return func(*args, **kwargs)
        return inner_wrapper
    return wrapper

@logging(level='INFO')
def say(something):
    print "say {}!".format(something)

类装饰器

class logging(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print "[DEBUG]: enter function {func}()".format(
            func=self.func.__name__)
        return self.func(*args, **kwargs)
@logging
def say(something):
    print "say {}!".format(something)

上下文管理器

from contextlib import contextmanager
class MyResource:
    def query(self):
        print('query data')

@contextmanager
def make_myresource():
    print('start to connect')
    yield MyResource()
    print('end connect')
    pass

@contextmanager 需要配合with … as 使用, yield之前定的语句在进入with 之前调用,紧跟着yield 的函数将返回值传递该as 后的参数,yield之后的语句在退出with之前执行

带参数类装饰器

class logging(object):
    def __init__(self, level='INFO'):
        self.level = level
        
    def __call__(self, func): # 接受函数
        def wrapper(*args, **kwargs):
            print "[{level}]: enter function {func}()".format(
                level=self.level,
                func=func.__name__)
            func(*args, **kwargs)
        return wrapper  #返回函数

@logging(level='INFO')
def say(something):
    print "say {}!".format(something)

@functools.wraps(func)

一般情况下wrap后函数名也会发生改变,functools.wraps的功能就是保留原函数名

import time
import functools
 
def log(kind):
    def add_log(func):
        @functools.wraps(func)
        def wrapper(*args,**kwargs):
 
            start_time = time.time()
            res = func(*args,**kwargs)
            end_time = time.time()
            print('<%s> [%s] 函数名:%s,运行时间:%.6f,运行返回值的结果'
              ':%d' %(kind,time.ctime(),func.__name__,
                      end_time-start_time,res))
            return res
        return wrapper
    return add_log
 
@log('debug')
def add():
    time.sleep(1)
    return 1+1
@log('debug')
def sub():
    time.sleep(1)
    return 2-1
 
print(add())
print(sub())

propoerty

class C(object):
    def __init__(self):
        self._x = None
 
    @property
    def x(self):
        """I'm the 'x' property."""
        return self._x
 
    @x.setter
    def x(self, value):
        self._x = value
 
    @x.deleter
    def x(self):
        del self._x

c.x 将触发 getter,c.x = value 将触发 setter , del c.x 触发 deleter。

types.SimpleNamespace()

今天看到代码使用了SimpleNamespace, 他是和argparse模块一起出现的,很好奇这个是什么东西。经过一般摸索,大概掌握了基本的用法。 我们知道了argparse使用,他是最后返回来了个Namespace,而其实我们这个SimpleNamespace也是返回一个命名空间了。他可以接受命名关键字参数,然后我们就可以使用.运算符。

>> from types import SimpleNamespace
>>> d = {'a': 1, 'b':2}
>>> sn = SimpleNamespace(**d)  # 这里的**不可以少,表示命名关键字参数
>>> sn
namespace(a=1, b=2)
>>> sn.a
1

泛型

from typing import TypeVar, Generic

T = TypeVar('T')

class Stack(Generic[T]):
    def __init__(self) -> None:
        # Create an empty list with items of type T
        self.items: List[T] = []

    def push(self, item: T) -> None:
        self.items.append(item)

    def pop(self) -> T:
        return self.items.pop()

    def empty(self) -> bool:
        return not self.items
# Construct an empty Stack[int] instance
stack = Stack[int]()
stack.push(2)
stack.pop()
stack.push('x') # Type error

多态

from abc import ABCMeta, abstractmethod
class Transform(metaclass=ABCMeta):
  • 多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。
  • 在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)
  • 也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
  • 上述代码子类是约定俗称的实现这个方法,加上@abc.abstractmethod装饰器后严格控制子类必须实现这个方法

多进程

python 多进程传参时默认按值传递,如果想多个进程共享list或dict数据结构需要专门声明
进程之间共享数据(dict,list):

import multiprocessing
 
def func(mydict,mylist):
    mydict["index1"]="aaaaaa"   #子进程改变dict,主进程跟着改变
    mydict["index2"]="bbbbbb"
    mylist.append(11)        #子进程改变List,主进程跟着改变
    mylist.append(22)
    mylist.append(33)
 
if __name__=="__main__":
    with multiprocessing.Manager() as MG:   #重命名
        mydict=multiprocessing.Manager().dict()   #主进程与子进程共享这个字典
        mylist=multiprocessing.Manager().list(range(5))   #主进程与子进程共享这个List
 
        p=multiprocessing.Process(target=func,args=(mydict,mylist))
        p.start()
        p.join()
 
        print(mylist)
        print(mydict)

hydra

├───conf
│   │   evaluate.yaml
│   │   preprocess.yaml
│   │   train.yaml
│   │
│   ├───data
│   │       vectornet_train.yaml
│   │       vectornet_val.yaml
│   │
│   ├───hparams
│   │       vectornet_baseline.yaml
│   │
│   ├───model
│   │       vectornet.yaml
│   │
│   └───status
│           debug.yaml
│           train.yaml

hydra主要负责读取层次化的.yaml文件。 在顶层的train.yaml中只要用

resume:
save_dir: models/
log_dir: ${name}/

defaults:
  - data: vectornet_train
  - model: vectornet
  - hparams: vectornet_baseline

  - status: train

就可以读取到data,model,hparams文件夹下的vectornet_train.yaml,vectornet.yaml以及vectornet_baseline。 data,model,hparams这三个参数并不会保存到config对象中,但是可以利用main函数的运行时参数进行修改。

如果给出多个运行时参数当做输入参数,即此脚本会自动运行多次,比如:

❯ python main.py lr=1e-3,1e-2 wd=1e-4,1e-2 -m
[2021-03-15 04:18:57,882][HYDRA] Launching 4 jobs locally
[2021-03-15 04:18:57,882][HYDRA]        #0 : lr=0.001 wd=0.0001
[2021-03-15 04:18:58,016][HYDRA]        #1 : lr=0.001 wd=0.01
[2021-03-15 04:18:58,149][HYDRA]        #2 : lr=0.01 wd=0.0001
[2021-03-15 04:18:58,275][HYDRA]        #3 : lr=0.01 wd=0.01

matplot

在这里插入图片描述

draw dynamic polint cloud

def show_gif(pointsList1,pointsList2):
    from matplotlib import pyplot as plt
    import numpy as np
    import mpl_toolkits.mplot3d.axes3d as p3
    from matplotlib import animation
    fig = plt.figure()

    ax = p3.Axes3D(fig)
    ax.set_box_aspect([1,1,1])
    ax.set(xlim3d=(-300, 300), xlabel='X')
    ax.set(ylim3d=(-300, 300), ylabel='Y')
    ax.set(zlim3d=(-300, 300), zlabel='Z')
    azim=0
    if azim is not None:
        ax.azim = azim
    # if dist is not None:
    #     ax.dist = dist
    # if elev is not None:
    #     ax.elev = elev

    points1, = ax.plot(pointsList1[0][:,0], pointsList1[0][:,1], pointsList1[0][:,2], '.r')
    points2, = ax.plot(pointsList2[0][:,0], pointsList2[0][:,1], pointsList2[0][:,2], '.b')
    def update_points(i):
        # update properties
        points1.set_data(pointsList1[i][:,0], pointsList1[i][:,1])
        points1.set_3d_properties(pointsList1[i][:,2], 'z')

        points2.set_data(pointsList2[i][:,0], pointsList2[i][:,1])
        points2.set_3d_properties(pointsList2[i][:,2], 'z')

        # return modified artists
        return points1,points2
    ani=animation.FuncAnimation(fig, update_points, frames=50)
    ani.save('./interpo_gru/save3d/animation.gif', writer='imagemagick', fps=2)
    plt.show()

    return

plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
wspace=None, hspace=None)
subplots_adjus 可以调整所有子图在归一化figure坐标系中的位置,也可以调整子图之间的距离。

add_axes可以指定子图在figure中的位置,以及宽高占figure宽高的比例
#figure的百分比,从figure 10%的位置开始绘制, 宽高是figure的80%
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
#获得绘制的句柄
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, ‘r’)
ax1.set_title(‘area1’)
#新增区域ax2,嵌套在ax1内,看一看图中图是什么样,这就是与subplot的区别
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
#获得绘制的句柄
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(x,y, ‘b’)
ax2.set_title(‘area2’)
plt.show()
结果如下:
#figure的百分比,从figure 10%的位置开始绘制, 宽高是figure的80%
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
#获得绘制的句柄
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, ‘r’)
ax1.set_title(‘area1’)
#新增区域ax2,嵌套在ax1内,看一看图中图是什么样,这就是与subplot的区别
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
#获得绘制的句柄
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(x,y, ‘b’)
ax2.set_title(‘area2’)
plt.show()
结果如下:
#figure的百分比,从figure 10%的位置开始绘制, 宽高是figure的80%
left, bottom, width, height = 0.1, 0.1, 0.8, 0.8
#获得绘制的句柄
ax1 = fig.add_axes([left, bottom, width, height])
ax1.plot(x, y, ‘r’)
ax1.set_title(‘area1’)
#新增区域ax2,嵌套在ax1内,看一看图中图是什么样,这就是与subplot的区别
left, bottom, width, height = 0.2, 0.6, 0.25, 0.25
#获得绘制的句柄
ax2 = fig.add_axes([left, bottom, width, height])
ax2.plot(x,y, ‘b’)
ax2.set_title(‘area2’)
plt.show()
在这里插入图片描述
plt.axis(‘off’)
可以去除边框

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值