文章目录
- `__dict__` | `vars()`
- `@staticmethod`
- `parser.set_default()`
- python抽象类和抽象方法`abc`
- `np.title`
- `np.random.choice`
- python 通过变量动态导入package
- `random.shuffle`
- python 深/浅拷贝
- try ... except .... 捕获异常
- python 的链式比较
- argument 和parameter
- return 不一定是函数的终点
- 局部变量和全局变量的疑惑
- 函数参数类型的检查问题
- rawpy color_desc 和 bayer_pattern
- pip 安装yaml 和opencv error
- python 生成requirements.txt
- logging 模块设置level 不生效
- UnicodeEncodeError: 'ascii' codec can't encode characters in position 9-10: ordinal not in range(1,128)
- python 导入上级目录的包
- python 移位运算
- VSCode 添加python 模板
- python 获取函数/类名称
- isinstance 判断对象是否为某类
- eval 创建函数引用
- 获取类/函数的参数列表
- python 获取代码运行处的绝对路径
- `__all__`
- `staticmethod` 可以使用self 的属性方法吗
__dict__
| vars()
- 今天看cyclegan代码框架,经常使用这个属性,结合
importlib
,用来使用变量导图模块和模块里面的类
model.__dict__
会输出model的所有属性,字典key是属性名,value是属性所代表的具体类、方法
model._dict__.items()
将属性字典的key-value打包成可迭代的元组
可以看看这个博客 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
-
importlib
import importlib
module_name = 'your/package/name'
module_lib = importlib.import_module(module_name)
-
__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
参考这个博客
-
单虚拟环境
pip freeze > requirements.txt
-
复杂环境
使用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 移位运算
- 左移
>>
数值除以2^n
值 - 右移
数值乘以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 函数外部获取函数名
# 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')
- 如果直接按照上面的file1 写则会抛出错误
FileNotFoundError: [Errno 2] No such file or directory: 'config1.yaml'
尝试获取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()
# 并不能