my python voyage


__dict__ | vars()

  1. 今天看cyclegan代码框架,经常使用这个属性,结合importlib,用来使用变量导图模块和模块里面的类
    model.__dict__ 会输出model的所有属性,字典key是属性名,value是属性所代表的具体类、方法
    model._dict__.items()将属性字典的key-value打包成可迭代的元组
    可以看看这个博客
  2. vars获取对象object的所有属性和属性值的字典对象,同样items()返回可迭代的元组

@staticmethod

也是cyclegan代码里的,用在类里面,在实例化类之前修改一些参数
这是python的一个内置函数,返回函数的静态方法,我也不是很理解这个词,但是用这个作为装饰器装饰类里面的函数,就宣布这个函数变成了一个静态函数,这样通过类名就可调用这个函数,而不需要通过实例化这个类,这样就可以对每个模型在实例化之前赋予不同的配置
RUNOOB.COM的例子吧


parser.set_default()

解析器级别的默认值会覆盖参数级别的默认值

import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--zz', default='233')
parser.set_default(zz='1023')
print(parser.parse_args)

python抽象类和抽象方法abc

python的类可以通过继承将方法继承到子类,而抽象类的子类必须完全实现抽象类的抽象方法
即抽象类继承的子类必须实现所有抽象父类中所有的抽象方法
简书知乎

抽象类中有抽象方法,该类不能被实例化,只能被继承,且子类必须实现抽象方法


np.title

title意思为瓷砖,将矩阵想瓷砖一样铺开

t = np.title(array, (2, 3, 1))

array表示矩阵,后面表示每个维度铺开多少遍,2 表示复制两遍


np.random.choice

选择不重复的随机值,replace=False

import numpy as np
t = np.random.choice(range(1, 176), 20, replace=False)

python 通过变量动态导入package

    1. importlib
import importlib
module_name = 'your/package/name'
module_lib = importlib.import_module(module_name)
    1. __import__
model_name = 'your/package/name'
module_lib = __import__(model_name)

random.shuffle

import random
a = list(range(6))
print(a)
random.shuffle(a)
print(a)
[0, 1, 2, 3, 4, 5]
[2, 3, 0, 5, 1, 4]

由上面可以看出他是个原地操作


python 深/浅拷贝

python的深/浅其实是需要针对可变/不可变对象来看的
对可变对象, 对他们的操作一定要谨慎再谨慎
原地操作也是容易改变原始对象的常见操作,慎用


try … except … 捕获异常

try:
    print(1 + 'a')
except Exception as e:
    raise Exception(e) -------------- 操作1
    print(e) -------------------------操作2

print('会执行吗')

上述代码操作1 和操作2 的结果是不一样的
操作1:

Traceback (most recent call last):

  File "<ipython-input-1-f37fee24ea27>", line 1, in <module>
    runfile('E:/ggsddu/PI20200805/ex1.py', wdir='E:/ggsddu/PI20200805')

  File "d:\Anaconda3\envs\torch\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 827, in runfile
    execfile(filename, namespace)

  File "d:\Anaconda3\envs\torch\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 110, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "E:/ggsddu/PI20200805/ex1.py", line 11, in <module>
    raise Exception(e)

Exception: unsupported operand type(s) for +: 'int' and 'str'

操作2:

unsupported operand type(s) for +: 'int' and 'str'
会执行吗

按照需要自行选择操作,你是需要仅抛出错误继续执行还是抛出错误并终止


以下是看python magic 记录的一些东西


python 的链式比较

False == False == True
>>> False

他是怎么比较的呢?看下面这个,你就明白了

import random
score = random.randomint(0, 100)
if 80 <= score <90:
	print("liang")

argument 和parameter

parameter:形参(formal parameter),体现在函数内部,作用域是这个函数体。
argument :实参(actual parameter),调用函数实际传递的参数。


return 不一定是函数的终点

try…finally… 语法中,finally 都会执行;另外函数遇到return 会结束函数;那么如果return 写在try 中会是什么情况?

def func():
    try:
        return 'try'
    finally:
        return 'finally'

print(func())
finally

实验证明finally 可以执行,return 不一定是函数的终点。
那么try 中的return 是被忽略了吗?
并不,函数没有return,会隐式的返回None

def func():
    try:
        return 'try'
    finally:
        print('finally') 

print(func())
finally
try

实验证明,finally 没有显式的return,try 中的return 是有效的


局部变量和全局变量的疑惑

a = 233

def add():
    a += 1 ---------1)
    print(a) -------2)
    
add()
1) Traceback (most recent call last):
  File "test.py", line 7, in <module>
    print(add())
  File "test.py", line 5, in add
    a += 1
UnboundLocalError: local variable 'a' referenced before assignment
2) 233

a += 1 的执行机制到底是什么呢?


函数参数类型的检查问题

def test_dtype(inp: int):
    print(type(inp))
    print(a)

a = 'aaaaa'
test_dtype(inp=a)
<class 'str'>
aaaaa
  • 上面的函数参数没有进行类型检查吗?

rawpy color_desc 和 bayer_pattern

def read_dng(img_path):
    """
    dng 格式的, 可以被rawpy 解析的图像格式均可
    """
    img = rawpy.imread(img_path)
    print("打印raw 信息:")
    for i in dir(img):
        print(i, eval('img.' + i))
    return img

打印出来的信息有这样两项

color_desc b'RGBG'
raw_pattern [[2 3]
 [1 0]]

开始我以为 color_desc是我认知的bayer 排列,怎么也想不通怎么会有这样的排列呢?一般不是只有GBRG/GRBG/RGGB/BGGR 四种,后来发现这个可能是为了说明底下的raw_pattern 表示的是什么,0123 分别对应RGBG,所以raw_pattern 2310 表示的bayer 格式即为BGGR


pip 安装yaml 和opencv error

ERROR: Could not find a version that satisfies the requirement yaml

pip install pyyaml

ERROR: Could not find a version that satisfies the requirement cv2

pip install opencv-python

python 生成requirements.txt

参考这个博客

  1. 单虚拟环境
    pip freeze > requirements.txt

  2. 复杂环境
    使用pipreqs 包,只检测当前目录下程序的依赖

pip install pipreqs
pipreqs . --encoding=utf-8 --force

安装依赖的时候
pip install -r requirements.txt


logging 模块设置level 不生效

最近使用

import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
logger.debug(2333)
logger.warning(110)

不会输出2333, 搜索之,有人说当logging 的level 高于logger 设置时,会优先使用logging 的level,所以在子模块中使用较低的level 时,将logging level 设施为NOTSET

logging.basicConfig(logging.NOTSET)

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 9-10: ordinal not in range(1,128)

这个

import sys
import codecs
sys.stdout = codecs.getwriter("utf-8")(sys.stdout.detach())

python 导入上级目录的包

# 上级
import sys
sys.path.append('..')
# 上上级
sys.path.append('../..')

python 移位运算

  1. 左移>>
    数值除以2^n
  2. 右移
    数值乘以2^n

VSCode 添加python 模板

参考

{
	// Place your snippets for python here. Each snippet is defined under a snippet name and has a prefix, body and 
	// description. The prefix is what is used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
	// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders. Placeholders with the 
	// same ids are connected.
	// Example:
	// "Print to console": {
	// 	"prefix": "log",
	// 	"body": [
	// 		"console.log('$1');",
	// 		"$2"
	// 	],
	// 	"description": "Log output to console"
	// }
	"python script template":{
		"prefix": "annotation",
		"body":[
			"# coding=utf-8",
			"\"\"\"",
			"@filename   : $TM_FILENAME",
			"@author     : keda_wl",
			"@time       : $CURRENT_YEAR-$CURRENT_MONTH-$CURRENT_DATE $CURRENT_HOUR:$CURRENT_MINUTE:$CURRENT_SECOND",
			"@description: ${1}",
			"\"\"\"",
		],
		"description": "python 头注释模板"
	}
}

python 获取函数/类名称

参考

  1. 函数名
    1.1 函数外部获取函数名
# coding=utf-8
"""
@filename   : temp.py
@author     : keda_wl
@time       : 2021-09-29 09:19:52
@description: 测试获取函数名和类名
"""
import sys

# %%
# 函数名
# 1. 函数内部 `sys._getframe().f_code.co_name`
def get_func_in():
   print("在函数内部获取函数名为: %s" % sys._getframe().f_code.co_name)

get_func_in()

# 2. 函数外部 `__name__`
def get_func_ex():
   return

print("在函数外部获取函数名: ", get_func_ex.__name__)  # 好像多此一举?看下面测试

get_func_ex_copy = get_func_ex
# 获取的时原始函数的所有属性
print("函数副本的函数名属性为: ", get_func_ex_copy.__name__)

# %%
# 类名
# 1. 函数内外部理论上都一样使用 `__class__.__name__` 属性

class get_class_in_ex():
   def __init__(self):
       print("类内部获取类名: ", self.__class__.__name__)

get_class = get_class_in_ex()
print("类外部获取函数名: ", get_class.__class__.__name__)

"""
在函数内部获取函数名为: get_func_in
在函数外部获取函数名:  get_func_ex
函数副本的函数名属性为:  get_func_ex
类内部获取类名:  get_class_in_ex
类外部获取函数名:  get_class_in_ex
"""

isinstance 判断对象是否为某类

以下测试结果为: 可以同时判断多个归属,返回的结果是,即对象属于其中的某一类,那么结果就是True

isinstance(obj, class_or_tuple, /)
    Return whether an object is an instance of a class or of a subclass thereof.
    
    A tuple, as in ``isinstance(x, (A, B, ...))``, may be given as the target to
    check against. This is equivalent to ``isinstance(x, A) or isinstance(x, B)
    or ...`` etc.
# coding=utf-8
"""
@filename   : temp.py
@author     : keda_wl
@time       : 2021-09-29 10:53:54
@description: 测试isinstance 是否可以同时判断多个实例
"""

a = [1, 2]
b = (2, 3)
print('a type: ', type(a))
print('b type: ', type(b))

# help(isinstance)
print("a 是否为list: ", isinstance(a, list))
print("a 是否为tuple: ", isinstance(a, tuple))
print("b 是否为list: ", isinstance(b, list))
print("b 是否为tuple: ", isinstance(b, tuple))
print("a 是否为list**或**tuple: ", isinstance(a, (list, tuple)))
print("b 是否为list**或**tuple: ", isinstance(b, (list, tuple)))
"""
a type:  <class 'list'>
b type:  <class 'tuple'>

a 是否为list:  True
a 是否为tuple:  False
b 是否为list:  False
b 是否为tuple:  True
a 是否为list**或**tuple:  True
b 是否为list**或**tuple:  True
"""

eval 创建函数引用

# coding=utf-8
"""
@filename   : temp.py
@author     : keda_wl
@time       : 2021-09-29 16:53:58
@description: eval 是否能创建函数引用
"""

def test_func_eval():
    print('done')

func_str = 'test_func_eval'
func_copy = eval(func_str)
func_copy()
"""
done
实验证明好像是可行的
"""

获取类/函数的参数列表

func.__code__.co_varnames 获取全部参数
func.__defaults__ 获取默认参数(默认参数的key 呢)
注意类的函数参数列表可能会多出一个self

# coding=utf-8
"""
@filename   : temp.py
@author     : keda_wl
@time       : 2021-09-30 09:48:39
@description: 获取类/函数的参数列表
"""

def tfunc(args1, args2=1, *args, **kwargs):
    print(tfunc)

class tclass():
    def __init__(self, cargs1, cargs2=2, *args, **kwargs):
        print(tclass)


print('tfunc 的默认参数: ', tfunc.__defaults__)
print('tfunc 的所有参数: ', tfunc.__code__.co_varnames)

print("tcalss 的默认参数: ", tclass.__init__.__defaults__)
print("tclass 的所有参数: ", tclass.__init__.__code__.co_varnames)

"""
tfunc 的默认参数:  (1,)
tfunc 的所有参数:  ('args1', 'args2', 'args', 'kwargs')
tcalss 的默认参数:  (2,)
tclass 的所有参数:  ('self', 'cargs1', 'cargs2', 'args', 'kwargs')
"""

ATTENTION: 你以为上面就行了,其实不然,co_varnames 打印了所有变量的名称,包括函数中使用的变量

# coding=utf-8
"""
@filename   : temp.py
@author     : keda_wl
@time       : 2021-09-30 09:48:39
@description: 获取类/函数的参数列表
"""

def tfunc(args1, args2=1, *args, **kwargs):
    a = 1
    b = 2

class tclass():
    def __init__(self, cargs1, cargs2=2, *args, **kwargs):
        c = 4
        d = 5

print('tfunc 的参数个数:', tfunc.__code__.co_argcount)
print('tfunc 的所有参数: ', tfunc.__code__.co_varnames)

print('tfunc 的参数个数:', tclass.__init__.__code__.co_argcount)
print("tclass 的所有参数: ", tclass.__init__.__code__.co_varnames)

"""
tfunc 的参数个数: 2
tfunc 的所有参数:  ('args1', 'args2', 'args', 'kwargs', 'a', 'b')
tfunc 的参数个数: 3
tclass 的所有参数:  ('self', 'cargs1', 'cargs2', 'args', 'kwargs', 'c', 'd')
"""

看起来好像可以通过参数数量来取变量列表的前n 个参数(类注意self 变量)来实现获取所有参数列表
这是一个冒险的做法


python 获取代码运行处的绝对路径

使用os.path.realpath(__file__) 方法即可
在写代码的过程中遇到一个问题,如下文件组织结构在file2中读取yaml 配置,相对路径会出错(测试过如果读取txt 文件可以)

– dir1
|----file1.py
|----config1.yaml
|----config2.yaml
– dir2
|----file2.py

config1.yaml

config1: 2333

config2.yaml

config2: 5666

file1.py


from yacs.config import CfgNode as CN

def func1(filename):
    cfg = CN(new_allowed=True)
    # 获取绝对路径
    # filename = os.path.join(os.path.split(os.path.realpath(__file__))[0], filename)
    print(filename)
    cfg.merge_from_file(filename)
    print(cfg)
    return cfg

file2.py

import sys
sys.path.append('..')
from dir1.file1 import func1

def func2(filename):
    func1(filename)

func2('config1.yaml')
  1. 如果直接按照上面的file1 写则会抛出错误
    FileNotFoundError: [Errno 2] No such file or directory: 'config1.yaml'
  2. 尝试获取file1 的绝对路径传给func1
    见func1 注释部分 os.path.realpath(__file__) 可以获取代码所在位置的绝对路径,这样就可以获取当前路径下文件的绝对路径

__all__

导入一个包,默认导入所有的类、方法、属性(保护和私有除外)
如果使用__all__ 限制导入包的话,只会导入__all__ 中的包

# pakage
# dir utils
# __init__.py
from .func import *
__all__ = []
__all__ += ['func1']

# dir utils
# func.py
import sys
def func1():
	print(sys._getframe().f_code.co_name)

def func2():
	print(sys._getframe().f_code.co_name)

def _func3():
	print(sys._getframe().f_code.co_name)

def __func4():
	print(sys._getframe().f_code.co_name)

# dir .
# main.py
from utils import *
# test....


staticmethod 可以使用self 的属性方法吗

# coding=utf-8
"""
@filename   : test.py
@author     : keda_wl
@time       : 2021-11-10 16:21:36
@description: @staticmethod 可以使用self 的属性方法吗
"""


class TestStaticmethod():
    def __init__(self):
        self.aa = 233
        self.bb = 566
    
    @staticmethod
    def call_staticmethod():
        print(self.aa)
        self.func()

    def func(self):
        print(self.bb)

if __name__ == '__main__':
    TestStaticmethod().call_staticmethod()
    # 并不能
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值