定义函数
(需要在使用前定义,最好函数名以小写字母开头)
位置传参
def 函数名(参数1[,参数2,...]):
'函数文档,不会打印出来,只有用:函数名.__doc__和help(函数名)才会打印出这引号里的话,只能写在函数下面第一行'
"""
多行函数文档
上面那个只能单行时使用,这个也必须写在函数定义下面第一行,这里写在了下面第二行,其实是不对的
"""
功能语句...
[return 参数]
关键字传参
def 函数名(参数1=默认值[,参数2=默认值,...]):
'给定默认参数(引用函数时如果没传参就用默认)'
...
*
传参
def 函数名(*参数名):
'给定收集多个非关键字参数(当不知道会传多少个参数进来时,该方法可以传很多参数),其将被转化成一个元组'
...
举例:
>>> def abc(a, *b):
print(a)
print('参数长度:',len(b))
print('第二个参数:',b[1]) #b是一个元组
>>> abc(1,'sad',3,4,435,23)
1
参数长度: 5
第二个参数: 3
注:
对*
传参来说,如果想要定义个确定的参数时,引用时就得用关键字传参,例如:def abc(*a,abc)
,那么传参时得这样:abc(1,2,'sa',abc='关键字传参')
**
传参
def 函数名(**参数名):
'给定收集多个关键字参数(当不知道会传多少个关键字参数进来时,该方法可以传很多参数),其将被转化成一个字典'
...
举例:
>>> def two(a=1,**b):
print(b) #b是一个字典
>>> two(a=1,b=2,c=3,d=4,e=5,f=6)
{'e': 5, 'd': 4, 'c': 3, 'b': 2, 'f': 6}
>>> di = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5, 'f': 6}
>>> two(**di)
{'b': 2, 'e': 5, 'c': 3, 'f': 6, 'd': 4}
# 可以看出有两种方式传参,一个是各种:键=值,另一种是:**字典
注:
在python3.8中,新增了传参限制的语法,如符号/
前仅允许位置传参,符号*
后仅允许关键字传参,举例:
def test(a, /, b, *, c):
pass
test(1, 2, c=3)
# a必须为位置传参,b随意,c必须为关键字传参
lambda函数
(也称为匿名函数,不需要取名,不需要提前定义,现定义现用方式)
格式:a = lambda 参数1[,参数2,...]: 功能语句(例如:参数1+参数2)
,意思就是传入前面的参数,并返回冒号后面的内容,举例:
>>> a = lambda x,y: x+y
>>> a(1,2)
3 #传入1和2,返回1+2
内嵌函数
(函数内部可以再定义函数,但是只有他的外面一层函数能调用他),举例:
def 函数名1(参数):
功能语句...
def 函数名2(参数):
功能语句...
函数名2(实参) #这里调用内嵌函数
引用函数
1.按顺序传参:函数名(实参1[,实参2])
2.关键字传参:函数名(形参=实参[,形参=实参])
注:
对于传参时,要注意函数中设置了默认值的参数,其在调用前就已经分配了一块地址,给其传参时,将会再开辟一个另外的地址存放,如果没传参时,就是直接用原来那个地址的参数来使用,举例:
def abc(a, lt=[]):
lt.append(a)
print(lt)
abc(1) #[1],此时用的是默认的lt,假设地址是1
abc(2, []) #[2] ,此时用的是自己传的lt,开设了另一个地址存放,假设是2
abc(3) #[1, 3],此时用的还是默认的lt,也就是地址为1的那个lt,所以是在第一次调用以后的基础上继续调用
递归函数
1.设置递归深度:
import sys
sys.setrecursionlimit(深度)
防止递归无限循环下去(Python默认最多递归1000次)
注:
递归虽然能使代码更加简洁,但效率相对来说可能没有迭代高
内置函数
可以通过dir(__builtins__)
查看所有的内置函数
list()
把一个数据变成列表,括号里得是元组、字符串或列表等(迭代器),举例:
#字符串
>>> str1='a b c'
>>> list(str1)
['a', ' ', 'b', ' ', 'c']
#元组
>>> tuple1=(1,2,'a')
>>> list(tuple1)
[1, 2, 'a']
注:
千万别给变量取名叫list、tuple、str等,不然这个函数就会被同名的局部变量覆盖而无法使用,可以看下面:
>>> type(list)
<class 'type'> # 原本获取的是一个内置函数类
>>> list = 1
>>> type(list)
<class 'int'> # 获取的是局部变量1
tuple()
把一个数据变成元组,跟list用法差不多,参考上面
str()
把数据变成字符串,但只是在外面单纯用引号括起来,举例:
>>> tuple1=(1,2,3)
>>> str(tuple1)
'(1, 2, 3)' #不是'123'
注:
如果想列表、元组之类的转字符串,用str()
是没用的,但是可以用字符串下的join()
方法,用空把他们连起来即可,举例:
>>> a = ['a', 'b', 'c']
>>> "".join(a)
'abc'
>>> a = [1,2,3]
>>> "".join(i for i in a)
TypeError: sequence item 0: expected str instance, int found
但是从第二个例子可以看出如果列表里元素不是字符串的话,就会报错,所以可以用链表推导式来全部转成str形式,然后再拼起来,举例:
>>> a = [1,2,3]
>>> "".join(str(i) for i in a)
'123'
len()
返回字符串长度,如果是列表和元组就是输出有几个
max()
返回参数或集合最大值,如果是一个字符串,则返回一个ASCII码值最大的,列表和元组的话必须里面全是一种变量类型;返回最小值用min()
,这两个还可以结合字典查询最值对应的键,格式为:max(字典, key=字典.get)
举例:
>>> d
{2: 2, 3: 6, 5: 1, 6: 1, 7: 1, 9: 1}
>>> max(d, key=d.get)
3
注:
在python中方法函数都是可传递的,因此上面key=d.get
其实就是把字典d
下的方法get
传入,然后依次对每一个值用get
方法,因此上面的代码也可以理解成:
max(d, key=lambda k: d.get(k))
# 依次传入所有的key,然后分别求出对应的value
sum()
计算参数和,针对列表和元组,且必须里面全是数字,sum后面还可以加个参数,表示计算的总和再加这个数,举例:
>>> list1=[1,2,3]
>>> sum(list1)
6
>>> sum(list1,2)
8 #总和再加上2,相当于:sum(list1) + 2
注:
python自带模块里没有求均值的(numpy
模块下有),用自带的求均值可以:
>>> sum(list1)/len(list1)
2.0 #总和除以总数
sorted()
跟sort()
方法差不多,可以对字符串、列表排序,对字符串排序后会变成一个列表,举例:
>>> str1='asb'
>>> sorted(str1)
['a', 'b', 's']
reversed()
跟reverse()
一样可以对字符串、列表倒序,但生成的是个对象而不是列表,例如直接:
>>> str1='asb'
>>> reversed(str1)
<reversed object at 0x03D30590>
所以如果要生成个列表就:
>>> list(reversed(str1))
['b', 's', 'a']
enumerate()
可以生成一个元组,包含各个的下标个和对应的值,跟reversed一样需要转下类型,举例:
>>> str1='asb'
>>> list(enumerate(str1))
[(0, 'a'), (1, 's'), (2, 'b')] #转列表
>>> dict(enumerate(str1))
{0: 'a', 1: 's', 2: 'b'} #转字典
该方法常用于迭代数据同时希望能够获取下标的场景,举例:
>>> for index, each in enumerate(['a', 'b', 'c']):
print(index, each)
0 a
1 b
2 c
zip()
把两个数据合起来生成一个一一映射的关系,映射长度取决于短的那个,举例:
>>> str1='asb'
>>> str2='csaf'
>>> list(zip(str1,str2))
[('a', 'c'), ('s', 's'), ('b', 'a')]
>>> dict(zip(str1,str2))
{'a': 'c', 'b': 'a', 's': 's'}
要注意的是对于转字典时,出现两个重复的键映射时,会被后一个映射的值给覆盖,例如:
>>> a = [1,3,4,5,2,5]
>>> b = ['a','fs','s','s','d','g']
>>> dict(zip(b,a))
{'g': 5, 'a': 1, 'd': 2, 's': 5, 'fs': 3} #s出现2次,第一次是4,第二次是5,所以最后就为5
注:
zip
不但可以将两个数据一一映射起来,还能进行反操作,即将一一映射的数据返回原来的样子,举例:
>>> x = list(zip([1,2,3], [4,5,6]))
>>> x
[(1, 4), (2, 5), (3, 6)]
>>> list(zip(*x))
# 使用*号代表反操作
[(1, 2, 3), (4, 5, 6)]
type()
输出变量类型,举例:
>>> type('a')
<class 'str'>
注:
该函数还能够创建类对象,在元类编程里会介绍
isinstance(a,b)
确定变量类型,a是你输入的变量,b是你输入的类型,然后会对比两个类型是否一样,一样就返回True,不一样返回False,举例:
>>> a = 'a'
>>> isinstance(a, int)
False
>>> isinstance(a, str)
True
range([start,],stop[,step=1])
生成一个从start参数值到stop参数值结束的数字序列,比如:range(1,5)
就是生成一个:1到4的序列(不包含5);如果只有stop,就会生成一个从0到stop-1的序列,比如:range(5)
就生成:0,1,2,3,4;step
表示每次加几,比如range(0,10,2)
,就是:0,2,4,6,8(每次递增2)。range经常和for结合使用,举例:
>>> for i in range(5) :
print(i, end='-')
0-1-2-3-4- #range()和for结合使用
filter(过滤函数,要过滤的内容)
将右边内容以左边函数方式计算,并将0或者False的过滤掉,举例:
>>> list(filter(lambda x: x % 2, range(10))) #过滤1到10里的偶数(把右边的数全部除2,结果为0都会被过滤)
[1, 3, 5, 7, 9]
过滤函数就写None,默认过滤0和False,举例:
>>> list(filter(None,range(10)))
[1, 2, 3, 4, 5, 6, 7, 8, 9] #把0过滤了
map(加工规则,要加工的内容)
把右边内容以左边规则加工,要注意的是右边加工的内容必须为可迭代的,举例:
>>> map(square, [1,2,3,4,5]) # 计算列表各个元素的平方
[1, 4, 9, 16, 25]
>>> list(map(lambda x: x*2 ,range(10))) #把1到10都乘2
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
并且map
函数还支持传入多个数据,举例:
>>> list(map(lambda x, y: x*y ,range(10), range(10, 20)))
# 同时传入两个迭代器进行乘积运算
[0, 11, 24, 39, 56, 75, 96, 119, 144, 171]
eval(expression[, globals[, locals]])
将字符串表达式转成他本应该是的类型,然后执行该表达式,并返回值,举例:
>>> eval('2')
2 #自动转int型
>>> eval('2+2')
4 #自动转为int型计算并返回
也可以用来实现简单数据类型的深拷贝,原理类似JS中先转JSON再解析从而实现深拷贝,举例:
>>> a = [1,2,[1,2,3]]
>>> b = eval(str(a))
# 先转字符串在eval,实现a的深拷贝
>>> b
[1, 2, [1, 2, 3]]
>>> a[2].pop()
3
>>> b
# 可以看到b没有随之改变
[1, 2, [1, 2, 3]]
但这种方式只支持内容都是基本数据类型的情况,对于内容当中存在类、函数等情况时,就会报错
abs()
计算绝对值
exec()
动态执行python代码,里面放的是字符串,但是会被解析成python代码运行,举例:
>>> exec("print('aaa')")
aaa #执行了里面的语句
这个当需要动态生成变量时就挺好用,举例:
>>> for each in range(10):
exec("x" + str(each) + "= each") #动态生成x0到x9变量,并赋值0到9
print("x" + str(each) + ":",eval("x" + str(each))) #使用eval将x0到x9从字符串变回原来的变量
x0: 0
x1: 1
x2: 2
x3: 3
x4: 4
x5: 5
x6: 6
x7: 7
x8: 8
x9: 9
>>> x0
0
这里再用exec()
来实现一个最基本的交互界面:
while 1:
try:
cmd = input(">>")
exec(cmd)
except Exception as e:
print(e)
round()
四舍五入数字,举例:
>>> round(3.5)
4
其还有第二个参数,代表四舍五入到第几位,比如四舍五入到小数点前两位,则:
>>> round(3.567,2)
3.57
__import__("package.module")
动态导入某个包的某个模块(当然直接导入模块也是可以的),例如:b = __import__("lib.ast")
,但要注意的是此时虽然导入了lib.ast并传给了b,但是b此时并不是lib.ast,b相当于是lib,所以要用ast还得从b里面调用,假如ast下有个类A,A下有属性m,举例:
b = __import__("Lib.ast")
Y = b.ast.A() #此时b只是Lib,所以要用b.ast
print(Y.m)
注:
使用importlib
模块下的import_module("module", "package")
也能实现同样的功能,而且和上面不同的是得到的不是包而是模块,举例:
import importlib
a = importlib.import_module("ast", "Lib")
X = a.A()
print(X.m)
chr()/ord()
ASCII转字符串/字符串转ASCII,举例:
>>> ord('a')
97
>>> chr(97)
'a'
format()
和字符串自带的format()
方法功能差不多,只是使用方法上稍微不同,可以将字符按规定格式输出,例如左右居中的对其输出、保留精度输出、进制转换输出等,例如:
>>> format("aaa", ">10") # 长度10位,向右居中
' aaa'
将上面的换成字符串下的format()
方法时,需要在括号中加入:
代表调用格式,举例:
>>> "{:>10}".format("aaa") # 和上面等效
' aaa'
更多使用参考:
https://www.cnblogs.com/mys6/p/10561416.html
any()
对于列表、数组这样的数据,里面内容只要任一不为False
则返回True
,否则返回False
,举例:
>>> any([1,0])
True
>>> any([0,0])
False
all()
对于列表、数组这样的数据,里面内容只要全不为False
则返回True
,否则返回False
,举例:
>>> all([1,0])
False
>>> all([1,1])
True
id()
获取内存地址
setattr
/getattr
添加/获取类属性,举例:
>>> class A:
pass
# 定义一个类
>>> a = A()
>>> setattr(a, "x", 1)
# 设置定义对象a的属性x
>>> a.x
1
>>> getattr(a, "x")
# 可以看出getattr和直接获取是一样的
1
>>> getattr(a, "y", 0)
# 获取a对象的y属性,不存在则返回默认值0
0
>>> setattr(A, "y", 1)
# 给类A设置属性y
>>> getattr(a, "y", 0)
1
dir()
查看某个内容的所有属性和方法等,如果不传值的话,则输出当前内存中的所有变量,举例:
>>> dir()
# 查看刚开启的shell里所有的变量
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
>>> a = 1
>>> dir()
# 上面定义了变量a,可以发现多了a
['__annotations__', '__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__', 'a']
>>> dir(a)
# 查看a的所有属性和方法
['__abs__', '__add__', '__and__', '__bool__', '__ceil__', '__class__', '__delattr__', '__dir__', '__divmod__', '__doc__', '__eq__', '__float__', '__floor__', '__floordiv__', '__format__', '__ge__', '__getattribute__', '__getnewargs__', '__gt__', '__hash__', '__index__', '__init__', '__init_subclass__', '__int__', '__invert__', '__le__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__', '__neg__', '__new__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__round__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'from_bytes', 'imag', 'numerator', 'real', 'to_bytes']
repr()
将内容变成供解释器读取的字符串,举例:
>>> a = {'x':1, 'y':[1,2,3]}
>>> repr(a)
# 变成对应的字符串
"{'x': 1, 'y': [1, 2, 3]}"
该方法的场景可以用来捕捉异常错误时看到更详细的内容,举例:
>>> try:
raise Exception("error")
except Exception as e:
print(e)
# 一般打印的只有错误信息
error
>>> try:
raise Exception("error")
except Exception as e:
print(repr(e))
# 可以看到错误所属的类
Exception('error',)
callable
判断传入的对象是否可调用,举例:
>>> callable(1)
False
>>> callable(lambda x: x+1)
True
>>> class A:
pass
>>> callable(A)
True
更多内置函数参考
https://www.cnblogs.com/linux-chenyang/p/6473820.html
函数、方法类
函数类
python中一切都是对象,包括函数、方法等,例如函数对象,我们可以查看其类:
def x():
print(1)
print(type(x))
# <class 'function'>
而定义函数,实质就是通过函数类实例化一个函数对象,其中需要传入code
对象,代表函数执行的代码,以及传入一个全局字典,记录需要使用到的全局属性举例:
def x():
print(1)
y()
def y():
print(2)
fun_class = type(x)
z = fun_class(x.__code__, {"print": print, "y": y})
# 定义一个函数z,传入x的__code__属性和函数映射
z()
print(z.__globals__)
print(y.__code__)
print(y.__globals__)
# 默认定义函数时将全局字典传入,相当于function_class(code, globals())
# 1
# 2
# {'print': <built-in function print>, 'y': <function y at 0x000001C0A6438598>}
# <code object y at 0x000001C0A61C2DB0, file "...xxx.py", line xxx>
# {'__name__': '__main__', ..., 'x': <function x at 0x000001C0A4563EA0>, 'y': <function y at 0x000001C0A6438598>}
一个函数的调用主要就是通过去指定属性__code__
里查找代码对象内容以及需要调用的函数等,所以我们也可以通过修改这些属性来改变函数的执行的内容,举例:
def x():
print(1)
def y():
print(2)
z = x
x.__code__ = y.__code__
# 将x指向的函数的执行代码改成y指向的函数代码,此时由于z和x指向的函数相同,所以z和x都是输出2
# 如果执行的是:x = y,则代表将x指向y,此时z还是指向原来的函数,所以z输出1
z() # 2
方法类
方法类实际上在内部定义了一个__func__
属性用于指向执行的函数对象,以及一个__self__
属性指向绑定的对象,举例:
class A:
def aaa(self):
pass
a = A()
print(type(A().aaa.__func__), type(A().aaa.__self__))
# <class 'function'> <class '__main__.A'>
参数机制
对于python中的函数和方法,设置的参数默认值都会被存放在当前类的__defaults__
和__kwdefaults__
属性里,举例:
class A:
def __init__(self, x, y=None, li=[]):
self.xxx = x
self.yyy = y
self.li = li
def test(self, m=1, *args, n=100, **kwargs):
pass
print(A.__init__.__defaults__, A.__init__.__kwdefaults__)
print(A.test.__defaults__, A.test.__kwdefaults__)
# (None, []) None
# (1,) {'n': 100}
可以看出如果没有设置*
传参,那么全部参数都存放在__defaults__
当中,而*
之后的参数则全部存放在__kwdefaults__
里
注:
如果设置的参数默认值是可变对象,就有可能会被复用,例如参数默认值是列表导致的问题:
def test(x, li=[]):
li.append(x)
print(li)
test(1)
test(2, [])
test(3)
print(test.__defaults__)
# [1]
# [2]
# [1, 3]
# ([1, 3],)
可以看到因为第一次和第三次调用test函数时没有传入列表,因此test函数使用了__defaults__
属性里的列表进行操作,结果导致第一次和第三次使用的是一个列表,而第二次使用的是另一个列表,因此参数的默认值尽量不要使用可变对象
code对象
参考:
https://www.cnblogs.com/wutaotaosin/articles/12525937.html
https://blog.csdn.net/qq_29695701/article/details/94194146
栈帧
栈帧是python用来管理函数的对象,每当创建一个函数,就会创建一个栈帧对象来记录当前函数的相关信息,如:函数名、当前执行到的行数、上一级函数等
获取栈帧
几种获取方式:
- 通过
inspect
模块的currentframe()
函数获取,举例:
import inspect
def test():
# 获取当前函数栈帧
frame = inspect.currentframe()
# 获取函数名
print(frame.f_code.co_name)
# 获取执行的行数
print(frame.f_lineno)
test()
# test
# 9
注:
该函数内部是通过sys
下的_getframe()
函数获取的,源码如下:
def currentframe():
"""Return the frame of the caller or None if this is not possible."""
return sys._getframe(1) if hasattr(sys, "_getframe") else None
- 通过捕获异常,此时
sys.exc_info()
里会接收异常的三个对象,然后通过sys.exc_info()[2].tb_frame
获取栈帧,举例:
import sys
def test():
try:
raise
except:
# 获取栈帧
frame = sys.exc_info()[2].tb_frame
print(frame.f_code.co_name)
print(frame.f_lineno)
test()
# test
# 10
栈帧示例-封装函数获取当前代码行数
在封装的方法里获取栈帧的上一级栈帧,然后返回栈帧对应的行数,举例:
import sys
def get_row():
try:
raise
except:
frame = sys.exc_info()[2].tb_frame
return frame.f_back.f_lineno
if __name__ == '__main__':
print(get_row())
# 12
用inspect.currentframe()
或者sys._getframe(1)
也都是可以的,这里的示例通过异常来获取是参考了logging
模块的实现方式
栈帧示例-print封装(自动输出文件、行数、时间)
import sys
import os
from datetime import datetime
class LogPrint:
"""日志输出封装类
"""
def __init__(self):
self._config()
def _config(self):
"""基本配置
"""
# 日志文件目录
self.log_dir = "./"
# print函数可接收的参数
self.output_options = ["sep", "end", "file", "flush"]
# 日志文件可接收的参数
self.log_options = ["encoding"]
def _get_frame(self):
"""获取栈帧"""
try:
return sys._getframe(5)
except:
return sys.exc_info()[2].tb_frame.f_back.f_back.f_back.f_back.f_back
def _get_cur_row(self):
"""获取日志行数
"""
return self._get_frame().f_lineno
def _get_file_name(self):
"""获取文件名
"""
return self._get_frame().f_code.co_filename
def _get_head(self):
"""输出语句头
"""
return f"[{self._get_file_name()}-{self._get_cur_row()}]: "
def _get_tail(self, time_f):
"""输出语句尾,包括打印输出和日志输出的(日志输出一定会加上时间)
@param:
- time_f 是否加上输出时间
"""
tail = ""
tail_l = f" ({datetime.now()})"
if time_f:
tail = tail_l
return tail, tail_l
def _format_output(self, s, head, tail):
"""格式化输出内容
"""
return head + " ".join(s) + tail
def _get_output(self, *s, time_f=True):
"""获取输出内容,包括打印输出和日志输出的
"""
head = self._get_head()
tail, tail_l = self._get_tail(time_f)
s_p = self._format_output(s, head, tail)
s_l = self._format_output(s, head, tail_l)
return s_p, s_l
def printf(self, *s, time_f=True, log=False, split=True, **config):
"""输出文件名,行数,时间
@param:
s: 输出字符串
split: 行分隔符
time_f: 是否输出时间
log: 是否保存进日志
config: print相关配置参数
"""
s_p, s_l = self._get_output(*s, time_f=time_f)
self._print_deco(s_p, split=split, **config)
if log:
self._write_to_log(s_l, **config)
def printl(self, *s, time_f=True, **config):
"""输出文件名,行数,时间到日志
@param:
同printf
"""
s_p, s_l = self._get_output(*s, time_f=time_f)
self._write_to_log(s_l, **config)
def _has_log_dir(self):
"""日志文件夹是否存在
"""
return hasattr(self, "log_dir") and os.path.isdir(self.log_dir)
def _get_log_file(self):
"""获取日志文件名
"""
now = datetime.now()
year, month, day = now.year, now.month, now.day
return f"{year}-{month}.log"
# return f"{year}-{month}-{day}.log"
def _write_to_log(self, s, **config):
"""写入到日志方法
"""
if not self._has_log_dir():
return
config = self._get_log_config(config)
encoding = config["encoding"] if "encoding" in config else "utf-8"
log_file = self._get_log_file()
with open(f"{self.log_dir}/{log_file}", "a", encoding=encoding) as lf:
lf.write(f"{s}\n")
def _print_split(self, config):
"""输出行分隔符
"""
if config.get("split"):
print("=" * 100)
def _get_config(self, type, config):
"""获取指定配置
"""
option_config = {}
self.options = getattr(self, f"{type}_options") or {}
for k in config:
if k in self.options:
option_config[k] = config[k]
return option_config
def _get_log_config(self, config):
"""获取日志输出参数配置
"""
return self._get_config("log", config)
def _get_output_config(self, config):
"""获取print参数配置
"""
return self._get_config("output", config)
def _print_deco(self, *s, **config):
"""输出装饰器,扩展相关功能
"""
self._print_split(config)
print(*s, **self._get_output_config(config))
self._print_split(config)
# 暴露输出方法
# =======================================
# 输出内容
printf = LogPrint().printf
# 输出到日志
printl = LogPrint().printl
if __name__ == '__main__':
printf("aaa", split=False, log=True)
printl("bbb")