当前位置: 首页 > news >正文

函数递归,匿名、内置行数,模块和包,开发规范

一、递归与二分法

  一)递归

  1、递归调用的定义

  递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身 

  2、递归分为两类:直接与间接
#直接
def func():print('from func')func()func()
# 间接
def foo():print('from foo')bar()def bar():print('from bar')foo()
  3、递归调用的特点和使用的注意点
递归调用:在调用一个函数的过程中,直接或间接地调用了函数本身
python中的递归效率低,需要在进入下一次递归时保留当前的状态
在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475;但是python又没有尾递归,且对递归层级做了限制#总结递归的使用:
1. 必须有一个明确的结束条件
2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
3. 递归效率不高,递归层次过多会导致栈溢出
在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出
  4、递归的执行分为两个阶段:递推(询问的过程)和回溯(回答的过程)
 1 #获知age(5)的值2 # age(5)=age(4)+23 # age(4)=age(3)+24 # age(3)=age(2)+25 # age(2)=age(1)+26 # age(1)=187 #8 # age(n)=age(n-1)+2 #n>19 # age(1)=18 #n=1
10 
11 def age(n):
12     if n == 1:
13         return 18
14     return age(n-1)+2
15 
16 print(age(5))
  5、可以递归的最大深度
 1 #虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归2 import sys3 sys.getrecursionlimit()  ##获取目前默认递归的最大深度,默认深度是10004 sys.setrecursionlimit(500)  ##更改默认递归的最大深度5 n=16 def test():7     global n8     print(n)9     n+=1
10     test()
11 test()
  6、应用场景:有许多层的列表,要取出所有元素——设置结束条件使用递归
l =[1, 2,'list' ,[3, [4, 5, 6, [7, 8, [9, 10, [11, 12, 13, [14, 15,[16,[17,]],19]]]]]]]
def search(l):for item in l:# if type(item) is list:if isinstance(item,list): ##判断数据类型是否是列表search(item)else:print(item)search(l)

  二)二分法

  1、二分法的产生
一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
  2、 二分法的作用:不断将列表切分成两份,减小压力
 1 l = [1,2,5,6,77,1001,1165,2340]2 def search(l,num):3     print(l)4     if len(l) > 1:5         mid_index = len(l) // 2 #相除取整6         if num > l[mid_index]:7             #in the right8             l = l[mid_index+1:]9         elif num < l[mid_index]:
10             #in the left
11             l = l[:mid_index]
12         else:
13             print('find it')
14             return
15     else:
16         if l[0] == num:
17             print('find it')
18         else:
19             print('not exists')
20         return
21     search(l,num) #重复的可以放在if里面
22 search(l,77)

二、匿名函数

  一)什么是匿名函数

# 有名函数
def f1(m):
print(f1(3))
# 匿名函数
lambda n:n*2

  二)匿名函数的应用场景

匿名函数自带return,只能使用一次
#匿名函数即没有绑定名字的函数,意味着只能使用一次就会回收
应用场景:只使用一次的功能

  三)匿名函数的使用

salaries={'egon':3000,'alex':10000000,'wupeiqi':10000,'yuanhao':2000
}def f1(k):return salaries[k]
  1、max、min与 lambda结合
print(max(salaries,key=lambda k:salaries[k]))
print(min(salaries,key=lambda k:salaries[k]))
  2、sorted与lambda结合
print(sorted(salaries,key=lambda k:salaries[k]))
print(sorted(salaries,key=lambda k:salaries[k],reverse=True))
  3、map(映射)与lambda结合

  将原来的元素进行处理后,重新赋值给原变量

l=['alex','egon','wzs','yuanhao']
print(list(map(lambda x:x+'123',l)))
  4、reduce(合并)与lambda结合

  计算0到100数字的和

1 from functools import reduce
2 # reduce(lambda 表达式,计算范围,计算的初始值)
3 res=reduce(lambda x,y:x+y,range(1,100),100)
4 print(res)
  5、filter(过滤)与lambda结合

  过滤出列表中以123结尾的元素

l=['alex123','egon123','wzs123','yuanhao']
print(list(filter(lambda name:name.endswith('123'),l)))
  6、扩展: 拉链函数
l1=[1,2,3]
s1='hello'
res = zip(l1,s1)
print(list(res))res=zip(salaries.values(),salaries.keys())
print(max(res)[1])

元素比较大小:从左到右比较元素的大小

1 t1=(111,'a')
2 t2=(11,'b',123,'c')
3 print(t1 < t2)

三、内置函数

  一)什么是内置函数

内置函数:python将简单的功能内置到语言中,使用者不用定义,可以直接使用
内置函数链接:https://docs.python.org/3/library/functions.html?highlight=built#ascii

  二)常用的内置函数

  

 

  1、优先掌握的函数
max min sorted map filter sum bool chr divmod enumerate 
id input print isinstance iter len open pow type zip
from _functools import reduce
  2、数学运算
abs(-5)                          # 取绝对值,也就是5
round(2.6)                       # 四舍五入取整,也就是3.0
pow(2, 3)                        # 相当于2**3,如果是pow(2, 3, 5),相当于2**3 % 5
cmp(2.3, 3.2)                    # 比较两个数的大小
divmod(9,2)                      # 返回除法结果和余数,分页显示内容,计算页数
max([1,5,2,9]) # 求最大值 min([9,2,-4,2]) # 求最小值 sum([2,-1,9,12]) # 求和
  3、类型转换
int("5")                         # 转换为整数 integer
float(2)                         # 转换为浮点数 float
long("23")                       # 转换为长整数 long integer
str(2.3)                         # 转换为字符串 string
complex(3, 9)                    # 返回复数 3 + 9i
bytes()                          # 字节
list((1,2,3))                    # 转换为表 list
tuple([2,3,4])                   # 转换为定值表 tuple
dict(a=1,b="hello",c=[1,2,3])    # 构建词典 dictionary
set()                            # 转换成集合
slice(5,2,-1)                    # 切片操作

python str与bytes之间的转换

 1 # bytes object2 b = b"example"3 # str object4 s = "example"5 # str to bytes6 sc = bytes(s, encoding = "utf8")7 print(type(sb))8 # bytes to str9 bs = str(b, encoding = "utf8")
10 # an alternative(可替代的方法) method
11 # str to bytes
12 sc2 = str.encode(s)
13 # bytes to str
14 bs2 = bytes.decode(b)

  ASCII表中的字符和序号之间互相转好,应用场景:生成随机验证码

#65-90是大写A-Z
print(chr(65))
print(chr(90))
#97-122是小写a-z
print(chr(97))
print(chr(122))
print(ord('A'))
#48-57是数字0-9
print(chr(48))
print(chr(57))

   bool()布尔判断,在python中,为False的情况:空(字符 ‘’,列表 [],元组 (),字典 {}),0,0.0,None

bool(0)                          # 转换为相应的真假值,在Python中,0相当于False

  进制显示

bin(56)                          # 返回一个字符串,表示56的二进制数
hex(56)                          # 返回一个字符串,表示56的十六进制数
oct(56)                          # 返回一个字符串,表示56的八进制数

  判断元素是否为True

all([True, 1, "hello!"])         # 是否所有的元素都相当于True值
any(["", 0, False, [], None])    # 是否有任意一个元素相当于True值

  排序

sorted([1,5,3])                  # 返回正序的序列,也就是[1,3,5]
reversed([1,5,3])                # 返回反序的序列,也就是[3,5,1]
  4、类、对象、属性
# define class
class Me(object):def test(self):print "Hello!"
def new_test():print "New Hello!"
me = Me()
object()
hasattr(me, "test")               # 检查me对象是否有test属性
getattr(me, "test")               # 返回test属性
setattr(me, "test", new_test)     # 将test属性设置为new_test
delattr(me, "test")               # 删除test属性
isinstance(1,int)                 # 检查对象是否是类的对象,返回True或False
issubclass(Me, object)            # Me类是否为object类的子类
  5、hash哈希值 :应用——数据校验
hash(object)
如果对象object为哈希表类型,返回对象object的哈希值。哈希值为整数,在字典查找中,哈希值用于快递比价字典的键。
两个数值如果相等,则哈希值也相等。
  6、名称空间 局部名称vars()、locals(),全局名称空间global(),显示形式是字典
print(vars() is locals())
print(globals())
  7、__import__()  可以导入字符串,import不能导入字符串
# import "time" #不能导入字符串
# import time
m=input('>>:')
print(type(m))
obj=__import__(m)  ##这样就可以导入字符串了
obj.sleep(2)
print(m)
  8、compile编译,执行exec、eval (了解)
    1、compile编译

  语法

compile(str,filename,kind)
filename:用于追踪str来自于哪个文件,如果不想追踪就可以不定义
kind可以是:single代表一条语句,exec代表一组语句,eval代表一个表达式

  应用

s="for i in range(10):print(i)"
code=compile(s,'','exec')
exec(code)  ##有返回结果s1="1+2+3"
code1=compile(s1,'','eval')
eval(code1) ##没有返回结果
    2、eval与exec

  eval 提取字符串内的表达式执行,并返回结果(可执行语句会报错)
  exec 执行字符串内的表达式或语句,没有返回结果

  语法

eval(str,[,globals[,locals]])
exec(str,[,globals[,locals]])

  举例

1 s1="1+2+3"
2 # s1="['a','b','c']"
3 s2="for i in range(10):print (i)"
4 print(eval(s1))
5 print(exec(s1))
6 print(exec(s2))

四、模块

  一)模块介绍

  1、什么是模块
一个模块就是一个包含了python定义和声明的文件,文件名就是模块名字加上.py的后缀。
  2、为何使用模块
如果你退出python解释器然后重新进入,那么你之前定义的函数或者变量都将丢失,因此我们通常将程序写到文件中以便永久保存下来,需要时就通过python test.py方式去执行,此时test.py被称为脚本script。随着程序的发展,功能越来越多,为了方便管理,我们通常将程序分成一个个的文件,这样做程序的结构更清晰,方便管理。这时我们不仅仅可以把这些文件当做脚本去执行,还可以把他们当做模块来导入到其他的模块中,实现了功能的重复利用

  import加载的模块分为四个通用类别

1、使用python编写的代码(.py文件)
2、已被编译为共享库或DLL的C或C++扩展
3、好一组模块的包
4、使用C编写并链接到python解释器的内置模块
  3、导入模块都干了哪些事?
1、执行源文件
2、以一个源文件的全局名称空间
3、在当前位置拿到一个模块名,指向2创建的名称空间
   4、python文件的两种用途
.py文件的两种用途:1、当做脚本运行 2、当做模块被加载运行文件当做脚本运行时,__name__等于__main__
文件当做模块被加载运行时,__name__等于模块名
if __name__ == '__main__':# 当做脚本使用func1()func2()func3()
# main  #回车会导入if __name__ == '__main__':

  二)使用import导入模块

  模块代码文件:spam.py

#spam.py
# print('from the spam.py')
# 限制*的导入内容
# _money=1000 #对*隐藏,即*无法调用(from spam import *)
# __all__ = ['money','x'] # *只能调用赋予给__all__的名称 (from spam import *)
money=10000000000000
def read1():print('spam->read1->money',money)def read2():print('spam->read2 calling read')read1()def change():global moneymoney=0
  1、导入模块并执行

  test.py

import spam
money=100
spam.read1()
spam.read2()
spam.change()
spam.read1()
print(money)
  2、as取别名  
    用途:1、模块名非常长; 2、更改模块的功能

  测试文件

mysql.py

1 def sqlparse():
2     print('mysql sqlparse')

oracle.py

1 def sqlparse():
2     print('oracle sqlparse')

  导入模块,并执行

模块名比较长

1 import spam as s1
2 money = 10000000
3 spam.change()
4 print(spam.money)

传入的内容调用不同的模块

1 sql_type = input('sql_type>>')
2 if sql_type == 'mysql':
3     import mysql as sql  ##引用不同的模块,因为实现的功能是相同的,所以可以起相同的别名
4 elif sql_type == 'oracle':
5     import oracle as sql
6 sql.sqlparse()
  3、导入多个模块:模块之间用逗号隔开(不建议这么写,还是不同模块分行写为好)
import os,sys,requests
  4、模块导入的特点

  模块只在第一次导入时才会执行,之后的导入都是直接引用内存已经存在的结果

导入,并验证是否已在内存中 

 1 import spam2 import spam3 import spam4 import spam5 6 #验证是否已经在内存7 import sys8 # print(sys.modules) #存放的是已经加到内存的模块9 print('spam' in sys.modules)   #查看一个模块是否加到内存中
10 import spam
11 print('spam' in sys.modules)

  三)from....import...导入模块

  1、对比import导入模块,from....import...的优缺点
1 对比import spam,会将源文件的名称空间'spam'带到当前名称空间中,使用时必须是spam.名字的方式
2 而from 语句相当于import,也会创建新的名称空间,但是将spam中的名字直接导入到当前的名称空间中,在当前名称空间中,直接使用名字就可以了
3 优点:使用源文件内的名字时,无需加前缀,使用方便
4 缺点:容易与当前文件的名称空间内的名字混淆,会覆盖原来名字的值
  2、语法范例
1 from spam import money,read1,read2
2 money = 10
3 print(money)
4 # g=read1()
5 g=read2()
6 print(g)
  3、将模块导入并起别名
# # from spam import read1 as m
from spam import money as m
# print(m)
  4、*的使用  (不建议使用*)
#要引用的源文件里面的内容很多时,可以使用*代替所有(更容易与当前文件的名称空间冲突),但是不建议使用_money=1000 #将调用的名字前面加_,*就无法调用该名字(在源文件修改)
__all__ = ['money','x'] # *只能调用赋予给__all__的名称(在源文件修改)
from spam import *

  四)模块的搜索路径

  1、模块查找的顺序
查找顺序:内存---->>内置模块---->>硬盘

  范例

import time
import importlib
import spam
time.sleep(30)
# import spam
# print(spam.money)importlib.reload(spam)  ##重启加载spam,可以使用到测试环境
print(spam.money)
  2、模块的注意事项
注意:1、Python程序只有重新加载才能生效2、Python自带的模块名不能使用
  3、搜索路径和注意事项
当一个命名为spam的模块被导入时解释器首先会从内建模块中寻找该名字找不到,则去sys.path中找该名字
sys.path从以下位置初始化1 执行文件所在的当前目录2 PTYHONPATH(包含一系列目录名,与shell变量PATH语法一样)3 依赖安装时默认指定的
注意:在支持软连接的文件系统中,执行脚本所在的目录是在软连接之后被计算的,换句话说,包含软连接的目录不会被添加到模块的搜索路径中
在初始化后,我们也可以在python程序中修改sys.path,执行文件所在的路径默认是sys.path的第一个目录,在所有标准库路径的前面。这意味着,当前目录是优先于标准库目录的,需要强调的是:我们自定义的模块名不要跟python标准库的模块名重复
  4、添加到path环境变量
import sys
print(sys.path)
# 添加path环境变量
# 加到最后面
sys.path.append(r'G:\data\PyCharm_Project\s19\day5\模块\模块的搜索路径\aaa')
# 加到最前面
sys.path.insert(0,r'G:\data\PyCharm_Project\s19\day5\模块\模块的搜索路径\aaa')import spamfrom aaa import #模块的搜索路径

  五)模块的重载

  考虑到性能的原因,每个模块只被导入一次,放入字典sys.module中,如果你改变了模块的内容,你必须重启程序,python不支持重新加载或卸载之前导入的模块

  有的同学可能会想到直接从sys.module中删除一个模块不就可以卸载了吗,注意了,你删了sys.module中的模块对象仍然可能被其他程序的组件所引用,因而不会被清楚。

  特别的对于我们引用了这个模块中的一个类,用这个类产生了很多对象,因而这些对象都有关于这个模块的引用。

  如果只是你想交互测试的一个模块,使用 importlib.reload(), e.g. import importlib; importlib.reload(modulename),这只能用于测试环境。

aa.py

1 def func1():
2     print('func1')

reload.py

1 import time,importlib
2 import aa
3 
4 time.sleep(20)
5 # importlib.reload(aa)
6 aa.func1()

五、包

  1、什么是包
##官网的解释
包是一种通过使用‘.模块名’来组织Python模块名称空间的方式
##详细解释
包就是一个含有__init__.py文件的文件夹,所以我们创建包的目的就是为了用文件/模块组织起来。
1. 无论是import形式还是from...import形式,凡是在导入语句中(而不是在使用时)遇到带点的,都要第一时间提高警觉:这是关于包才有的导入语法
2. 包是目录级的(文件夹级),文件夹是用来组成py文件(包的本质就是一个包含__init__.py文件的目录)
3. import导入文件时,产生名称空间中的名字来源于文件,import 包,产生的名称空间的名字同样来源于文件,即包下的__init__.py,导入包本质就是在导入该文件
##强调:1. 在python3中,即使包下没有__init__.py文件,import 包仍然不会报错,而在python2中,包下一定要有该文件,否则import 包报错2. 创建包的目的不是为了运行,而是被导入使用,记住,包只是模块的一种形式而已,包即模块
包A和包B下有同名模块也不会冲突,如A.a与B.a来自俩个命名空间
  2、为何要使用包
随着功能越写越多,我们无法将所有功能都放到一个文件中,于是我们使用模块去组织功能,而随着模块越来越多,我们需要用文件夹将模块文件组织起来,依次来提供程序的结构性和可维护性
  3、注意事项
1.关于包相关的导入语句也分为import和from ... import ...两种,但是无论哪种,无论在什么位置,在导入时都必须遵循一个原则:凡是在导入时带点的,点的左边都必须是一个包,否则非法。可以带有一连串的点,如item.subitem.subsubitem,但都必须遵循这个原则。
2.对于导入后,在使用时就没有这种限制了,点的左边可以是包,模块,函数,类(它们都可以用点的方式调用自己的属性)。
3.对比import item 和from item import name的应用场景:
如果我们想直接使用name那必须使用后者。
  4、实战
实验一准备:执行文件为test.py,内容#test.pyimport aaa同级目录下创建目录aaa,然后自建空__init__.py(或者干脆建包)需求:验证导入包就是在导入包下的__init__.py解决:先执行看结果再在__init__.py添加打印信息后,重新执行2、实验二准备:基于上面的结果需求:aaa.xaaa.y解决:在__init__.py中定义名字x和y3、实验三准备:在aaa下建立m1.py和m2.py#m1.pydef f1():print('from 1')#m2.pydef f2():print('from 2')需求:aaa.m1 #进而aaa.m1.func1()aaa.m2 #进而aaa.m2.func2()解决:在__init__.py中定义名字m1和m2,先定义一个普通变量,再引出如何导入模块名,强调:环境变量是以执行文件为准4、实验四准备:在aaa下新建包bbb需求:aaa.bbb解决:在aaa的__init__.py内导入名字bbb5、实验五准备:在bbb下建立模块m3.py#m3.pydef f3():print('from 3')需求:aaa.bbb.m3 #进而aaa.bbb.m3.f3()解决:是bbb下的名字m3,因而要在bbb的__init__.py文件中导入名字m3,from aaa.bbb import m36、实验六准备:基于上面的结果需求:aaa.m1()aaa.m2()aaa.m3()进而实现aaa.f1()aaa.f2()aaa.f3()先用绝对导入,再用相对导入解决:在aaa的__init__.py中拿到名字m1、m2、m3包内模块直接的相对导入,强调包的本质:包内的模块是用来被导入的,而不是被执行的用户无法区分模块是文件还是一个包,我们定义包是为了方便开发者维护7、实验七将包整理当做一个模块,移动到别的目录下,操作sys.path

  二)包的使用

  1、测试文件:执行文件与测试文件在同级目录下
包
├── aaa
│   ├── bbb
│   │   ├── __init__.py
│   │   ├── m3.py
│   │   └── __pycache__
│   ├── __init__.py
│   ├── m1.py
│   ├── m2.py
│   └── __pycache__
└── run.py

文件内容

##文件内容#m1.py
def func1():print('f1')#m2.py
def func2():print('f2')#m3.py
def func3():print('f3')
  2、包的使用之import

  单独导入包名称时,不会导入包中的所有包含的所有子模块

#在与aaa同级的run.py
import aaa
aaa.m1.func1()执行结果会出现如下错误:
ModuleNotFoundError: No module named 'm1'

  解决方法

#与aaa底下的__init__.py
from .m1 import func1#导入模块,执行aaa同级的run.py的结果
import aaaf1

  需要注意的:

  from后import导入的模块,必须是明确的一个不能带点,否则会有语法错误,如:from a import b.c是错误语法

    from aaa.bbb.m3 import func3

   3、from aaa.bbb.m3 import * :从一个包中导入所有*

  在 Windows 平台上工作的就不是非常好,因为 Windows 是一个不区分大小写的系统。

  想从包api中导入所有,实际上该语句只会导入包api下__init__.py文件中定义的名字,我们可以在这个文件中定义__all___:

#在__init__.py中定义
x=10def func():print('from api.__init.py')__all__=['x','func','policy']
  4、绝对导入和相对导入

  最顶级包是aaa是给用户使用的,然后在aaa内部也会有彼此之间相互导入的需求,这时就有绝对和相对导入两种方式。

  绝对导入:以aaa作为起始

  相对导入:用.或者..的方式最为起始(只能在一个包中使用,不能用于不同目录内)

      

   例:想在aaa/bbb/func3.py中导入aaa/ccc/func4.py绝对导入在func3.py上写入下面的代码
from aaa.ccc.m4 import func4与run.py同级的__init__.pyd导入相应的模块
from aaa.bbb.m3 import func4在run.py上的写入下面的代码直接调用
aaa.func4()相对导入在func4.py上写入下面的代码
from ..ccc.m4 import func4与run.py同级的__init__.pyd导入相应的模块
from aaa.bbb.m3 import func4在run.py上的写入下面的代码直接调用
aaa.func4()
  5、包以及包所包含的模块都是用来被导入的,而不是被直接执行的。而环境变量都是以执行文件为准的

  添加环境变量

import sys
sys.path.append(r'C:\Users\wz\PycharmProjects\python36\s19\day5\包\xxx\yyy')
import aaa

aaa同级的__init__.py内容

1 from .m1 import func1
2 from .m2 import func2
3 from .bbb.m3 import func3
4 from .bbb.m3 import func4

m3.py文件内容

1 from ..ccc.m4 import func4
2 def func3():
3     print('f3')
4     func4()

运行run.py文件内容

1 import sys
2 sys.path.append(r'C:\Users\wz\PycharmProjects\python36\s19\day5\包\xxx\yyy')
3 import aaa
4 aaa.func1()
5 aaa.func2()
6 aaa.func3()

  运行文件使用import直接导入所需模块的功能(使用了解目录结构):

    导入:import aaa.ccc.m4 

    调用:aaa.ccc.c4.func4()

  6、包的分发(了解)

  学习链接网址:Packaging Python Projects - Python Packaging User Guide

六、软件开发规范

  一)软件目录规范如下

  

  二)常用模块的使用

常用模块的使用

  1  #=============>bin目录:存放执行脚本2 #sos.path.dirname(os.path.dirname(os.path.abspath(__file__)))6 sys.path.append(BASE_DIR)7 8 from core import core9 from conf import my_log_settings10 11 if __name__ == '__main__':12     my_log_settings.load_my_logging_cfg()13     core.run()14 15 #=============>conf目录:存放配置文件16 #config.ini17 [DEFAULT]18 user_timeout = 100019 20 [egon]21 password = 12322 money = 1000000023 24 [alex]25 password = alex371426 money=1000000000027 28 [yuanhao]29 password = ysb12330 money=1031 32 #settings.py33 import os34 config_path=r'%s\%s' %(os.path.dirname(os.path.abspath(__file__)),'config.ini')35 user_timeout=1036 user_db_path=r'%s\%s' %(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),\37                      'db')38 39 40 #my_log_settings.py41 """42 logging配置43 """44 45 import os46 import logging.config47 48 # 定义三种日志输出格式 开始49 50 standard_format = '[%(asctime)s][%(threadName)s:%(thread)d][task_id:%(name)s][%(filename)s:%(lineno)d]' \51                   '[%(levelname)s][%(message)s]' #其中name为getlogger指定的名字52 53 simple_format = '[%(levelname)s][%(asctime)s][%(filename)s:%(lineno)d]%(message)s'54 55 id_simple_format = '[%(levelname)s][%(asctime)s] %(message)s'56 57 # 定义日志输出格式 结束58 59 logfile_dir = r'%s\log' %os.path.dirname(os.path.dirname(os.path.abspath(__file__)))  # log文件的目录60 61 logfile_name = 'all2.log'  # log文件名62 63 # 如果不存在定义的日志目录就创建一个64 if not os.path.isdir(logfile_dir):65     os.mkdir(logfile_dir)66 67 # log文件的全路径68 logfile_path = os.path.join(logfile_dir, logfile_name)69 70 # log配置字典71 LOGGING_DIC = {72     'version': 1,73     'disable_existing_loggers': False,74     'formatters': {75         'standard': {76             'format': standard_format77         },78         'simple': {79             'format': simple_format80         },81     },82     'filters': {},83     'handlers': {84         #打印到终端的日志85         'console': {86             'level': 'DEBUG',87             'class': 'logging.StreamHandler',  # 打印到屏幕88             'formatter': 'simple'89         },90         #打印到文件的日志,收集info及以上的日志91         'default': {92             'level': 'DEBUG',93             'class': 'logging.handlers.RotatingFileHandler',  # 保存到文件94             'formatter': 'standard',95             'filename': logfile_path,  # 日志文件96             'maxBytes': 1024*1024*5,  # 日志大小 5M97             'backupCount': 5,98             'encoding': 'utf-8',  # 日志文件的编码,再也不用担心中文log乱码了99         },
100     },
101     'loggers': {
102         #logging.getLogger(__name__)拿到的logger配置
103         '': {
104             'handlers': ['default', 'console'],  # 这里把上面定义的两个handler都加上,即log数据既写入文件又打印到屏幕
105             'level': 'DEBUG',
106             'propagate': True,  # 向上(更高level的logger)传递
107         },
108     },
109 }
110 
111 
112 def load_my_logging_cfg():
113     logging.config.dictConfig(LOGGING_DIC)  # 导入上面定义的logging配置
114     logger = logging.getLogger(__name__)  # 生成一个log实例
115     logger.info('It works!')  # 记录该文件的运行状态
116 
117 if __name__ == '__main__':
118     load_my_logging_cfg()
119 
120 #=============>core目录:存放核心逻辑
121 #core.py
122 import logging
123 import time
124 from conf import settings
125 from lib import read_ini
126 
127 config=read_ini.read(settings.config_path)
128 logger=logging.getLogger(__name__)
129 
130 current_user={'user':None,'login_time':None,'timeout':int(settings.user_timeout)}
131 def auth(func):
132     def wrapper(*args,**kwargs):
133         if current_user['user']:
134             interval=time.time()-current_user['login_time']
135             if interval < current_user['timeout']:
136                 return func(*args,**kwargs)
137         name = input('name>>: ')
138         password = input('password>>: ')
139         if config.has_section(name):
140             if password == config.get(name,'password'):
141                 logger.info('登录成功')
142                 current_user['user']=name
143                 current_user['login_time']=time.time()
144                 return func(*args,**kwargs)
145         else:
146             logger.error('用户名不存在')
147 
148     return wrapper
149 
150 @auth
151 def buy():
152     print('buy...')
153 
154 @auth
155 def run():
156 
157     print('''
158 购物
159 查看余额
160 转账
161     ''')
162     while True:
163         choice = input('>>: ').strip()
164         if not choice:continue
165         if choice == '1':
166             buy()
167 
168 
169 
170 if __name__ == '__main__':
171     run()
172 
173 #=============>db目录:存放数据库文件
174 #alex_json
175 #egon_json
176 
177 #=============>lib目录:存放自定义的模块与包
178 #read_ini.py
179 import configparser
180 def read(config_file):
181     config=configparser.ConfigParser()
182     config.read(config_file)
183     return config
184 
185 #=============>log目录:存放日志
186 #all2.log
187 [2017-07-29 00:31:40,272][MainThread:11692][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
188 [2017-07-29 00:31:41,789][MainThread:11692][task_id:core.core][core.py:25][ERROR][用户名不存在]
189 [2017-07-29 00:31:46,394][MainThread:12348][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
190 [2017-07-29 00:31:47,629][MainThread:12348][task_id:core.core][core.py:25][ERROR][用户名不存在]
191 [2017-07-29 00:31:57,912][MainThread:10528][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
192 [2017-07-29 00:32:03,340][MainThread:12744][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
193 [2017-07-29 00:32:05,065][MainThread:12916][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
194 [2017-07-29 00:32:08,181][MainThread:12916][task_id:core.core][core.py:25][ERROR][用户名不存在]
195 [2017-07-29 00:32:13,638][MainThread:7220][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
196 [2017-07-29 00:32:23,005][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
197 [2017-07-29 00:32:40,941][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
198 [2017-07-29 00:32:47,222][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
199 [2017-07-29 00:32:51,949][MainThread:7220][task_id:core.core][core.py:25][ERROR][用户名不存在]
200 [2017-07-29 00:33:00,213][MainThread:7220][task_id:core.core][core.py:20][INFO][登录成功]
201 [2017-07-29 00:33:50,118][MainThread:8500][task_id:conf.my_log_settings][my_log_settings.py:75][INFO][It works!]
202 [2017-07-29 00:33:55,845][MainThread:8500][task_id:core.core][core.py:20][INFO][登录成功]
203 [2017-07-29 00:34:06,837][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
204 [2017-07-29 00:34:09,405][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]
205 [2017-07-29 00:34:10,645][MainThread:8500][task_id:core.core][core.py:25][ERROR][用户名不存在]

相关文章:

函数递归,匿名、内置行数,模块和包,开发规范

一、递归与二分法 一&#xff09;递归 1、递归调用的定义 递归调用&#xff1a;在调用一个函数的过程中&#xff0c;直接或间接地调用了函数本身 2、递归分为两类&#xff1a;直接与间接 #直接 def func():print(from func)func()func() # 间接 def foo():print(from foo)bar…...

Springboot3 整合swagger

一、pom.xml <dependency><groupId>org.springdoc</groupId><artifactId>springdoc-openapi-starter-webmvc-api</artifactId><version>2.1.0</version></dependency> 二、application.yml # SpringDoc配置 # springdoc:swa…...

查看同一网段内所有设备的ip

使用命令提示符&#xff08;CMD&#xff09;进行扫描 查看本机IP地址 首先通过 ipconfig /all 命令查看本机的IP地址&#xff0c;确定你的网段&#xff0c;例如 192.168.1.。 Ping网段内每个IP地址 接着使用循环命令&#xff1a; for /L %i IN (1,1,254) DO ping -w 1 -n …...

Spark MLlib 特征工程(上)

文章目录 Spark MLlib 特征工程(上)特征工程预处理 Encoding:StringIndexer特征构建:VectorAssembler特征选择:ChiSqSelector归一化:MinMaxScaler模型训练总结Spark MLlib 特征工程(上) 前面我们一起构建了一个简单的线性回归模型,来预测美国爱荷华州的房价。从模型效果来…...

《SPSS零基础入门教程》学习笔记——03.变量的统计描述

文章目录 3.1 连续变量&#xff08;1&#xff09;集中趋势&#xff08;2&#xff09;离散趋势&#xff08;3&#xff09;分布特征 3.2 分类变量&#xff08;1&#xff09;单个分类变量&#xff08;2&#xff09;多个分类变量 3.1 连续变量 &#xff08;1&#xff09;集中趋势 …...

2024年杭州市网络与信息安全管理员(网络安全管理员)职业技能竞赛的通知

2024年杭州市网络与信息安全管理员&#xff08;网络安全管理员&#xff09;职业技能竞赛的通知 一、组织机构 本次竞赛由杭州市总工会牵头&#xff0c;杭州市人力资源和社会保障局联合主办&#xff0c;杭州市萧山区总工会承办&#xff0c;浙江省北大信息技术高等研究院协办。…...

SpringBoot参数校验详解

前言 在web开发时&#xff0c;对于请求参数&#xff0c;一般上都需要进行参数合法性校验的&#xff0c;原先的写法时一个个字段一个个去判断&#xff0c;这种方式太不通用了&#xff0c;Hibernate Validator 是 Bean Validation 规范的参考实现&#xff0c;用于在 Java 应用中…...

安全基础学习-SHA-1(Secure Hash Algorithm 1)算法

SHA-1(Secure Hash Algorithm 1)是一种密码学哈希函数,用于将任意长度的输入数据(消息)转换成一个固定长度的输出(哈希值或摘要),长度为160位(20字节)。SHA-1的主要用途包括数据完整性验证、数字签名、密码存储等。 1、SHA-1 的特性 定长输出:无论输入数据长度是多…...

leetcode350. 两个数组的交集 II,哈希表

leetcode350. 两个数组的交集 II 给你两个整数数组 nums1 和 nums2 &#xff0c;请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数&#xff0c;应与元素在两个数组中都出现的次数一致&#xff08;如果出现次数不一致&#xff0c;则考虑取较小值&#xff09;。可…...

基于YOLOv8的缺陷检测任务模型训练

文章目录 一、引言二、环境说明三、缺陷检测任务模型训练详解3.1 PCB数据集3.1.1 数据集简介3.1.2 数据集下载3.1.3 构建yolo格式的数据集 3.2 基于ultralytics训练YOLOv83.2.1 安装依赖包3.2.2 ultralytics的训练规范说明3.2.3 创建训练配置文件3.2.4 下载预训练模型3.2.5 训练…...

【upload]-ini-[SUCTF 2019]CheckIn-笔记

上传图片木马文件后看到&#xff0c;检查的文件内容&#xff0c;包含<? 一句话木马提示 检查的文件格式 用如下图片木马&#xff0c;加上GIF89a绕过图片和<?检查 GIF89a <script languagephp>eval($_POST[cmd])</script> .user.ini实际上就是一个可以由用…...

uniapp条件编译使用教学(#ifdef、#ifndef)

#ifdef //仅在xxx平台使用#ifndef //除了在xxx平台使用#endif // 结束 标识平台APP-PLUSAPPMP微信小程序/支付宝小程序/百度小程序/头条小程序/QQ小程序MP-WEIXIN微信小程序MP-ALIPAY支付宝小程序MP-BAIDU百度小程序MP-TOUTIAO头条小程序MP-QQQQ小程序H5H5APP-PLUS-NVUEApp nv…...

NXP i.MX8系列平台开发讲解 - 4.1.2 GNSS 篇(二) - 卫星导航定位原理

专栏文章目录传送门&#xff1a;返回专栏目录 Hi, 我是你们的老朋友&#xff0c;主要专注于嵌入式软件开发&#xff0c;有兴趣不要忘记点击关注【码思途远】 文章目录 关注星号公众号&#xff0c;不容错过精彩 作者&#xff1a;HywelStar Hi, 我是你们的老朋友HywelStar, 根…...

怎样在 SQL 中对一个包含销售数据的表按照销售额进行降序排序?

在当今数字化商业的浪潮中&#xff0c;数据就是企业的宝贵资产。对于销售数据的有效管理和分析&#xff0c;能够为企业的决策提供关键的支持。而在 SQL 中&#xff0c;对销售数据按照销售额进行降序排序&#xff0c;是一项基础但极其重要的操作。 想象一下&#xff0c;您面前有…...

DIAdem 与 LabVIEW

DIAdem 和 LabVIEW 都是 NI (National Instruments) 公司开发的产品&#xff0c;尽管它们有不同的核心功能和用途&#xff0c;但它们在工程、测试和测量领域中常常一起使用&#xff0c;以形成一个完整的数据采集、分析、处理和报告生成的解决方案。 1. 功能和用途 LabVIEW (Lab…...

UE虚幻引擎可以云渲染吗?应用趋势与挑战了解

虚幻云渲染技术是基于虚幻引擎的云端渲染技术&#xff0c;将虚幻引擎的渲染计算任务通过云计算的方式进行处理和渲染、并将渲染结果传输到终端设备上进行展示。虚幻引擎云渲染技术在近年来得到了迅猛的发展&#xff0c;并在各个领域得到了广泛的应用&#xff0c;包括游戏、电影…...

实战分享:DefenderUI在企业环境中的部署与应用

前言 想象一下&#xff0c;你的电脑就像一座坚固的城堡&#xff0c;但城门却时常被一些不速之客窥探甚至企图入侵&#xff1b;Defender&#xff0c;作为城堡自带的守护者&#xff0c;实力自然不容小觑&#xff1b;但你是否觉得它有时候太过低调&#xff0c;有些隐藏技能还没完…...

中英双语介绍金融经济中的鹰派 (Hawkish)和鸽派 (Dovish)

中文版 在金融和经济政策中&#xff0c;“鹰派”和“鸽派”是两种对货币政策和经济管理有不同立场的群体。 鹰派 (Hawkish) 鹰派倾向于担心通货膨胀的风险&#xff0c;通常支持较高的利率和更紧的货币政策&#xff0c;以防止经济过热和控制物价上涨。具体特征包括&#xff1…...

Android 开发中常用的布局类型及其选择指南

在 Android 开发过程中,选择正确的布局类型对于构建高效、美观且响应式的用户界面至关重要。本文将介绍 Android 中几种最常用的布局类型,并对比它们的特点和适用场景,帮助开发者们做出明智的选择。 1. LinearLayout - 线性布局 特点: LinearLayout 是最基本的布局类型之一…...

短视频SDK解决方案,降低行业开发门槛

美摄科技匠心打造了一款集前沿技术与极致体验于一体的短视频SDK解决方案&#xff0c;它不仅重新定义了短视频创作的边界&#xff0c;更以行业标杆级的短视频特效&#xff0c;让每一帧画面都闪耀不凡光芒。 【技术赋能&#xff0c;创意无限】 美摄科技的短视频SDK&#xff0c;…...

【C++】String常见函数用法

一、string类对象的常见构造 我们可采取以下的方式进行构造&#xff0c;以下是常用的接口&#xff1a; //生成空字符串 string; //拷贝构造函数 string(const string& str); //用C-string来构造string类对象 string(const char* s); //string类对象中包含n个字符c strin…...

LeetCode49.字母异位词分组

题目大意 给你一个字符串数组&#xff0c;请你将字母异位词组合在一起。可以按任意顺序返回结果列表。 字母异位词是由重新排列源单词的所有字母得到的一个新单词。 思路分析 示例 1: 输入: strs ["eat", "tea", "tan", "ate", &…...

Nginx日志按天分割

需求、日志按照天的单位进行分割存储。 如果你直接百度&#xff0c;可能会搜到很多教你用各种脚本或是三方插件来按天分割的&#xff0c;这边我用nginx服务本身来分割日志。 方法一 通过使用 $time_iso8601 变量和 map 指令&#xff0c;实现了日志文件按天分割的功能。以下是…...

文本摘要简介

文本摘要是从一段长文本中提取出最重要的信息&#xff0c;并生成一个简短而有意义的摘要。这个过程可以分为两种主要方法&#xff1a; 抽取式摘要&#xff08;Extractive Summarization&#xff09;&#xff1a;从原文中直接提取出关键句子或段落&#xff0c;组成摘要…...

3.MySQL面试题之Redis 和 Mysql 如何保证数据一致性?

Redis 和 MySQL 数据一致性是分布式系统中的一个常见挑战。保证数据一致性通常涉及几种策略&#xff0c;我会详细解释这些策略并提供相应的代码示例。 先更新数据库&#xff0c;再更新缓存 这种方法先更新 MySQL&#xff0c;然后更新或删除 Redis 缓存。 Transactional publ…...

浅谈TCP协议、UDP协议

一、介绍说明 TCP&#xff08;传输控制协议&#xff09; 面向连接&#xff1a;TCP在数据传输之前必须建立连接。这通过一个称为三次握手的过程来完成&#xff0c;确保连接的两端都准备好进行数据传输。 可靠性&#xff1a;TCP提供可靠的数据传输&#xff0c;确保数据包正确无…...

SQL业务题: 从不订购的客户

1️⃣题目 Customers 表&#xff1a; ---------------------- | Column Name | Type | ---------------------- | id | int | | name | varchar | ---------------------- 在 SQL 中&#xff0c;id 是该表的主键。 该表的每一行都表示客户的 ID 和名…...

怎么直接在PDF上修改内容?随心编辑PDF内容

PDF(Portable Document Format)作为一种专用于阅读而非编辑的文档格式&#xff0c;其设计的核心目的是保持文档格式的一致性&#xff0c;确保文档在不同平台和设备上都能以相同的布局和格式呈现。然而&#xff0c;在实际工作和生活中&#xff0c;我们经常需要对PDF文档进行编辑…...

聊天室项目测试报告

项目介绍 本项目是一个基于Spring Boot框架开发的聊天室应用。一个实时的文本消息交流平台&#xff0c;允许多个用户同时在线聊天。系统采用了Spring Boot作为后端框架&#xff0c;集成了WebSocket技术以实现消息的实时推送与接收提供一个简单、易用且功能完备的在线聊天环境。…...

语音识别(实时语音转录)——funasr的详细部署和使用教程(包括实时语音转录)

阿里达摩院开源大型端到端语音识别工具包FunASR&#xff1a; FunASR提供了在大规模工业语料库上训练的模型&#xff0c;并能够将其部署到应用程序中。工具包的核心模型是Paraformer&#xff0c;这是一个非自回归的端到端语音识别模型&#xff0c;经过手动注释的普通话语音识别…...

【网络编程】TCP机械臂测试

通过w(红色臂角度增大)s&#xff08;红色臂角度减小&#xff09;d&#xff08;蓝色臂角度增大&#xff09;a&#xff08;蓝色臂角度减小&#xff09;按键控制机械臂 注意&#xff1a;关闭计算机的杀毒软件&#xff0c;电脑管家&#xff0c;防火墙 1&#xff09;基于TCP服务器…...

笔记:在WPF中如何注册控件级全局事件和应用程序级全局事件

一、目的&#xff1a;在WPF中如何注册控件级全局事件和应用程序级全局事件 二、实现 应用程序级全局事件 //注册应用程序级全局事件 EventManager.RegisterClassHandler(typeof(Button), Button.ClickEvent, new RoutedEventHandler(ic_event_Click)); 如上代码既会注册全局…...

【Linux系列】telnet使用入门

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

音视频相关知识

H.264编码格式 音频 PCM就是要把声音从模拟信号转换成数字信号的一种技术&#xff0c;他的原理简单地说就是利用一个固定的频率对模拟信号进行采样。 pcm是无损音频音频文件格式...

数据结构--第七天

递归 -递归的概念 递归其实就是一种解决问题的办法&#xff0c;在C语言中&#xff1a;递归就是函数自己调用自己 -递归的思想 递归的思考方式就是把大事化小的过程 递归的递就是递推的意思&#xff0c;归就是回归的意思 &#xff08;递归是少量的代码完成大量的运算&#xff09…...

代码随想录Day34:62.不同路径、63.不同路径II、343.整数拆分、96.不同的二叉搜索树

62. 不同路径 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&…...

【信息学奥赛一本通】1008:计算(a+b)/c的值

1008&#xff1a;计算(ab)/c的值 时间限制: 1000 ms 内存限制: 66536 KB 提交数:164836 通过数: 142434 【题目描述】 给定3个整数a、b、c&#xff0c;计算表达式abc的值。 【输入】 输入仅一行&#xff0c;包括三个整数a、b、c, 数与数之间以一个空格分开。(&#xff0d;10,…...

使用 jstat 进行 Java 应用程序性能监控

jstat 使用经验笔记 1. 简介 jstat 是 Java 开发工具包 (JDK) 中的一个命令行工具&#xff0c;用于监控 Java 虚拟机 (JVM) 的运行时状态&#xff0c;特别是垃圾回收 (Garbage Collection, GC) 的行为。通过使用 jstat&#xff0c;你可以监控和诊断 Java 应用程序的内存使用情…...

Prompt指令调优大揭秘

Hey&#xff0c;技术达人们&#xff01;今天咱们就来聊聊Prompt指令调优的那些事儿。想象一下&#xff0c;你有一个超级智能的AI小伙伴&#xff0c;但要让它更懂你&#xff0c;更给力&#xff0c;那就得靠点“魔法”——Prompt指令调优。准备好了吗&#xff1f;让我们一探究竟&…...

C语言中的⽂件操作

1. 为什么使⽤⽂件&#xff1f; 如果没有⽂件&#xff0c;我们写的程序的数据是存储在电脑的内存中&#xff0c;如果程序退出&#xff0c;内存回收&#xff0c;数据就丢失了&#xff0c;等再次运⾏程序&#xff0c;是看不到上次程序的数据的&#xff0c;如果要将数据进⾏持久化…...

黑马前端——days14_js

案例 1 页面框架文件 <!DOCTYPE html> <html lang"zh-CN"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</title>&l…...

【自动驾驶】ROS中参数服务器通信(c++)

目录 通信过程新建参数服务器包编写测试文件修改cmakelist:搭配launch文件启动测试及结果 通信过程 1.Talker 设置参数 Talker 通过 RPC 向参数服务器发送参数(包括参数名与参数值)&#xff0c;ROS Master 将参数保存到参数列表中。 2.Listener 获取参数 Listener 通过 RPC 向…...

零基础5分钟上手亚马逊云科技核心云开发知识 - 网络基础

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…...

Unity Recttransform操作

1、拉伸铺满 RectTransform rect GetComponent<RectTransform>();rect.anchorMin Vector2.zero;rect.anchorMax Vector2.one;rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, Screen.width);rect.SetSizeWithCurrentAnchors(RectTransform.Axis.Verti…...

MIT线性代数P5

置换矩阵 置换矩阵是行重新排列的单位矩阵。 置换矩阵用P表示&#xff0c; 性质&#xff1a; n阶置换矩阵共有n!个...

patroni+etcd开启SSL认证(三个节点证书一致 使用openssl命令)

瀚高数据库 目录 环境 文档用途 详细信息 环境 系统平台&#xff1a;Linux x86-64 Red Hat Enterprise Linux 7 版本&#xff1a;14 文档用途 本文主要介绍Patroni架构中如何开启etcd的ssl证书认证。 详细信息 一、前提说明 patroni版本&#xff1a;3.0.2 etcd版本&#x…...

Eureka入门指南:微服务注册与发现的基础概念

Eureka入门指南&#xff1a;微服务注册与发现的基础概念 引言 随着微服务架构的普及&#xff0c;微服务之间的高效通信和管理成为了开发和运维的核心挑战之一。为了解决服务发现和管理问题&#xff0c;Netflix推出了Eureka&#xff0c;一个功能强大的服务注册和发现工具。Eur…...

Linux:动态库和静态库

静态库与动态库 A&#xff1a;静态库&#xff08;.a&#xff09;&#xff1a;程序在编译链接的时候把库的代码链接到可执行文件中。程序运行的时候将不再需要静态库。 B&#xff1a;动态库&#xff08;.so&#xff09;&#xff1a;程序在运行的时候才去链接动态库的代码&#…...

8.13网络编程

笔记 多点通信 一、套接字属性 套接字属性的获取和设置 #include <sys/types.h> /* See NOTES */#include <sys/socket.h>int getsockopt(int sockfd, int level, int optname,void *optval, socklen_t *optlen);int setsockopt(int sockfd, int level…...

蚂蚁AL1 15.6T 创新科技的新典范

● 哈希率&#xff1a;算力达到15.6T&#xff08;相当于15600G&#xff09;&#xff0c;即每秒能够进行15.6万亿次哈希计算&#xff0c;在同类产品中算力较为出色&#xff0c;能提高WA掘效率。 ● 功耗&#xff1a;功耗为3510W&#xff0c;虽然数值看似不低&#xff0c;但结合其…...