当前位置: 首页 > 编程日记 > 正文

Python之装饰器

Python之装饰器

在不修改函数调用方式的前提下,也不能修改函数内部源代码!!!!

例如:

在每个季度公司发绩效,统计每个人的代码执行效率。咱们总不能是每个函数里加time模块吧。

import timedef test():start = time.time()     #开始时间time.sleep(0.1)      #睡一下,象征的表示函数的代码块很大,要0.1秒去执行print("hello")       #打印函数结果end = time.time()      #函数结束时间print(end-start)          #计算函数的执行时间,并打印
test()

但是,在公司,咱么不可能使每人都这么去执行代码,加time.time()。

原因很简单,就是这样已经更改了原函数的的内部代码。

并且,这个计算时间的功能只是在季度末用来算代码执行时间的,过阵子就不用了。咱么总不能在去每个函数里把time给注释或删了吧。要是那样,呵呵呵,真麻烦。

那问题来了。我们怎么去解决这个问题。

哈哈哈:在写一个函数呗,函数功能只是单纯的计算时间的。

import timedef timmer(func):#函数名可以当做函数的参数start = time.time()func()end = time.time()print(end-start)def test():time.sleep(0.1)print("hello")timmer(test)
#函数test作为参数传给timmer函数。

But ,问题又来了,这个样就改变了函数的调用方式。也是不可以的。

这样的话,就有了今天的换题。装饰器。

我们讲test = timmer 就是说,讲timmer的函数地址给test

在调用test函数 test() 实际就是在调用timmer函数

在这个时候,执行test等同于执行timmer,可是timmer里要有参数的。而参数是test,可以咱们又将test的地址指向了timmer。这样的话。在内存中就没有了test函数啦~~~~~~。咋办哩?

这里我们就用到了之前不知道干啥用的闭包了。

在timmer函数中,写一个闭包函数。

1 import time2 def timmer(func):# 函数名可以当做函数的参数5 def inner(x,y):9  start = time.time()10 func(x,y)     # 传入的test函数11 end = time.time()12 print(end-start)6 return inner     #  inner的地址给了test3 def test(a,b):time.sleep(0.1)print(a,b)7 h = 4 timmer(test)   #test为inner
#函数test作为参数传给timmer函数。
8 h(1,2) # 相当于执行inner

这样是闭包的内部函数去调用外部函数的值,使外部函数的值不消失。

在这里,以调用timmer,就返回一个inner。而这个inner就是现在的h。h传有参数1和2,就是传给inner函数1和2。1和2就是inner的x和y,但是inner的x和y是test函数需要的a和b。而test函数就是inner函数里的func(x,y)。

这就是一个带参数的装饰器。

但是在多个函数使用这个装饰器的时候,会因为参数的不固定。报错。

那么,怎么解决呐?

import time
def timmer(func):def inner(x,y):func(x,y)return innerdef test1(a,b):time.sleep(0.1)print(a,b)def test2(a):print(a)test1 = timmer(test1)
test1(1,2)test2 = timmer(test2)
test2(1)

报错信息:少位置参数。在inner函数里是两个参数。

1 2
Traceback (most recent call last):File "/Users/george/PycharmProjects/Python/Python函数/装饰器/test.py", line 85, in <module>test2(1)
TypeError: inner() missing 1 required positional argument: 'y'

解决方法:

使用 *args 和 **kwargs 动态传参。

import time
def timmer(func):def inner(*args,**kwargs): func(*args,**kwargs)return innerdef test1(a,b):time.sleep(0.1)print(a,b)def test2(a):print(a)test1 = timmer(test1)
test1(1,2)test2 = timmer(test2)
test2(1)

@timmer  ==  test1 = timmer(test1)

将@timmer加在函数的上一行。

import time
def timmer(func):def inner(*args,**kwargs):"""ret是返回值:param args::param kwargs::return:"""ret = func(*args,**kwargs)return retreturn innerdef test1(a,b):time.sleep(0.1)print(a,b)def test2(a):print(a)@timmer   #test3 = timmer(test3)
def test3():"""带返回值的函数,装饰器里的inner函数也要有返回才行。:return:"""return 123test1 = timmer(test1)
test1(1,2)test2 = timmer(test2)
test2(1)ret = test3()

装饰器的本质:闭包函数

功能:就是在不改变原函数调用方式的情况下,在这个函数前后加扩展功能

装饰器的使用:

wrapper(装饰)

def wrapper(func):def inner(*args,**kwargs):"""添加函数调用之前的扩展代码"""ret = func(*args,**kwargs)"""添加函数调用之后的扩展代码"""return retreturn inner####设计模式:# 原则:开放封闭原则# 对扩展是开放的# 对修改是封闭的

装饰器示范:

import timedef wapper(func):"""计算代码的运行时间。:param args::param kwargs::return: 时间差"""def inner():print(func)  # 打印的func是index的内存地址。#func函数被扩展前的调用代码start_time = time.time()# 被修饰的函数
        func()#func函数别扩展后的代码end_time = time.time()print("run time is %s " %(end_time-start_time))return inner@wapper    #  @wapper 实际上是    index = wapper(index)
def index():time.sleep(0.3)print(".......")index()     #index() 实际上是在执行inner

开放封闭原则:

1.对扩展是开放的

为什么要对扩展开放呢?

我们说,任何一个程序,不可能在设计之初就已经想好了所有的功能并且未来不做任何更新和修改。所以我们必须允许代码扩展、添加新功能。

2.对修改是封闭的

为什么要对修改封闭呢?

就像我们刚刚提到的,因为我们写的一个函数,很有可能已经交付给其他人使用了,如果这个时候我们对其进行了修改,很有可能影响其他已经在使用该函数的用户。

装饰器完美的遵循了这个开放封闭原则。

装饰器的主要功能和装饰器的固定结构

装饰器的主要功能:

在不改变函数调用方式的基础上在函数的前、后添加功能。

装饰器的固定格式:

1 def timer(func):
2     def inner(*args,**kwargs):
3         '''执行函数之前要做的'''
4         re = func(*args,**kwargs)
5         '''执行函数之后要做的'''
6         return re
7     return inner
装饰器的固定格式

1 from functools import wraps
2 
3 def deco(func):
4     @wraps(func) #加在最内层函数正上方
5     def wrapper(*args,**kwargs):
6         return func(*args,**kwargs)
7     return wrapper
装饰器的固定格式——wraps版

无参装饰器:示范

@wapper 后面么有跟参数。

import timedef wapper(func):"""计算代码的运行时间。:param args::param kwargs::return: 时间差"""def inner(*args,**kwargs):print(func)  # 打印的func是index的内存地址。#func函数被扩展前的调用代码start_time = time.time()# 被修饰的函数res = func(*args,**kwargs)#func函数别扩展后的代码end_time = time.time()print("run time is %s " %(end_time-start_time))return resreturn inner@wapper    #  @wapper 实际上是    index = wapper(index)
def index(*args,**kwargs):time.sleep(0.3)print(".......")@wapper
def home(name):time.sleep(0.2)print("home is %s " %(name))@wapper
def auth(name,password):"""认证:return:"""print(name,password)@wapper
def my_max(x,y):print("my_max function")res = x if x>y else yreturn resres = my_max(1,22)    # res = my_max(1,22)  就是在res = warpper(1,22)
print("===",res)

auth(
"wang","111") home("HZ") index() #index() 实际上是在执行inner

有参装饰器:示范

@wapper 后面有参数的。

将已有的装饰器再被嵌套一层函数进去,

def test1():

def wapper():

这样,test1就可是一个带参数的装饰器了。

def wapper(auth_type):"""参数装饰器了。:param auth_type::return:"""def wapper2(func):"""认证功能装饰器:param func::return:"""print(auth_type)def inner(*args,**kwargs):if auth_type == "file":print("func the function", func)name = input("username >>:")password = input("password >>:")if name == "george" and password == "111":print("ok successfull")res = func(*args,**kwargs)return reselse:print("error NO")elif auth_type == "SQL":print("MySQL,NB大了")return innerreturn wapper2@wapper(auth_type = "SQl")   #参数了。。。。。。。  将原有的wapper在嵌套进一层,把auth_type搞成参数 
def index():print("有参数了。不要脸了")index()

作业:

一:编写装饰器,为多个函数加上认证功能(用户的账号密码来源于文件)。

要求登录成功一次,后续的函数则无需再输入用户名和密码。

注意:从文件中读出字符串的字典,可以用eval({ ‘name’:‘George’,‘password’:‘123’})转成字典格式。

将字典写到一个文件中。名为conf.txt

在文件中读取的内容是字符串类型。

使用eval方法将类型进行转换:

最终结果:

#定义一个全局字典,告诉我user是谁,status状态是什么。
auth_status = {'user':None,'status':False
}def auth_wrapper(func):"""认证装饰器:param func::return:"""def inner(*args,**kwargs):"""如果status的状态是真,则无需输入密码。:param args::param kwargs::return:"""#判断登录状态if auth_status['status']:ret = func(*args, **kwargs)return retelse:# 认证功能:# 获取用户名和密码username = input('username:').strip()password = input('password:').strip()# 读文件获取用户信息f = open('conf')user_info = f.read()user_dict = eval(user_info)# 对比输入的用户名和密码和文件里的是否一致。# user_dict.get能get到username,说明有这个用户存在,然后再去user_dict的字典里去取用户名k,得到密码的值,再和输入的密码对比。if user_dict.get(username) and user_dict[username] == password:print('login successful')#登录成功,将auth_status的值进行修改auth_status['user'] = usernameauth_status['status'] = Trueret = func(*args, **kwargs)return retelse:print('login feiled')return inner@auth_wrapper
def index():"""首页函数:return:"""print('Welcome the world')@auth_wrapper
def home():"""主页函数:return:"""print('Welcome the home')index()
home()

二:编写下载页面内容的函数,要求功能是:用户传入一个URL,函数返回下载页面的结果。

编写装饰器,实现缓存页面内容的功能:

具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),

就优先从文件中读取页面内容,否则,就去下载,然后存到文件中。

先实现需求一,获取url。使用urllib模块

代码:

#先导入urllib模块。
from urllib.request import urlopendef get(url):"""给一个URL,返回结果:param url::return:"""return urlopen(url).read()url = get('http://www.cnblogs.com/george92/p/8629064.html')
print(url)

加装饰器实现缓存:

def get_cache(func):"""缓存装饰器:param func::return:"""def inner(*args,**kwargs):#取func中的URLurl = args[0]# 用hash转换url,在转换成字符串类型filename = str(hash(url))#判断url是否在url_l中。if url in url_l:f = open(filename,'rb')ret = f.read()else:#不在url_l中,就将url添加到url_l中。
            url_l.append(url)ret = func(*args,**kwargs)#打开文件f = open(filename,'wb')#将ret写到文件中
            f.write(ret)#关闭文件
        f.close()return retreturn inner

最终效果:

url_l = []#先导入urllib模块。
from urllib.request import urlopendef get_cache(func):"""缓存装饰器:param func::return:"""def inner(*args,**kwargs):#取func中的URLurl = args[0]# 用hash转换url,在转换成字符串类型filename = str(hash(url))#判断url是否在url_l中。if url in url_l:f = open(filename,'rb')ret = f.read()else:#不在url_l中,就将url添加到url_l中。
            url_l.append(url)ret = func(*args,**kwargs)#打开文件f = open(filename,'wb')#将ret写到文件中
            f.write(ret)#关闭文件
        f.close()return retreturn inner@get_cache
def get(url):"""给一个URL,返回结果:param url::return:"""return urlopen(url).read()url = get('http://www.cnblogs.com/george92/p/8629064.html')
print(url)
print(url)
print(url)
print(url)
print(url)
print(url)
print(url)
print(url)
print(url)

带参数的装饰器:

给装饰器加一个开关,想用的时候就用,不想的时候就不用。 好TM任(ren)性。

# F = True
F = False# 给wrapper装饰器见一个外层函数outer,在判断outer的参数是什么。在分别执行不同的代码块
def outer(flag):def wrapper(func):def inner(*args,**kwargs):#当被装饰的函数的值为flag时。if flag:print("before")ret = func(*args,**kwargs)print("after")#当被装饰的函数的值不为flag时:else:ret = func(*args,**kwargs)return retreturn innerreturn wrapper# @outer(True)  ===> @wrapper ===> test = wrapper(test) ===> test == inner 所以在调test时就等同于调inner
@outer(F)
def test():print('呵呵呵')@outer(F)
def test2():print('哈哈哈')test()
test2()
test()

 多个装饰器修饰一个函数:

#应用场景

#func
#1.计算func的执行时间 @timmer
#1.登录认证 #@auth

#@auth
#@timmer
#func

#解耦 尽量的让代码分离。小功能之间的分离
#解耦的目的 提高代码的重用性

def test1(func):def inner(*args,**kwargs):print('test1:before')ret = func(*args,**kwargs)print('test1:after')return retreturn innerdef test2(func):def inner(*args,**kwargs):print('test2:before')ret = func(*args,**kwargs)print('test2:after')return retreturn inner@test1
@test2
def test():print('幺妹')

结果是个俄罗斯套娃

流程:

在调用test时:

是test = test2(test)

再test = test1(test),但test = test1(test) ==》test = test1(test2(test))

而test = test1(test2(test))的结果是 test2(test) ==> test2_inner

test1(test2_inner) = test1_inner

所以 test() ==> test1_inner()

小功能:

实现统计当前程序中有多少个函数被此装饰器装饰。

统计当前程序中有多少个函数被装饰了

l = []def wrapper(func):l.append(func)def inner(*args,**kwargs):ret = func(*args,**kwargs)print('wrapper:after')return retreturn inner@wrapper
def test1():print('test1')# @wrapper
def test2():print('test2')@wrapper
def test3():print('tset3')@wrapper
def test4():print('test4')test1()
test2()
test3()
test4()
print(l)
print(len(l))

实现统计本次程序执行有多少个带这个装饰器的函数被调用。

l = []
def wrapper(func):    def inner(*args,**kwargs):l.append(func)ret = func(*args,**kwargs)print('wrapper:after')return retreturn inner@wrapper
def test1():print('test1')# @wrapper
def test2():print('test2')@wrapper
def test3():print('tset3')@wrapper
def test4():print('test4')test1()
test2()
test3()
test4()
print(l)
print(len(l))

总结;

装饰器

     def wrapper(func):
       def inner(*args,**kwargs):
         ret = func(*args,**kwargs)
         return ret
       return inner


  返回值
    def ret_func():
      print(111)
      return 222
    ret = ret_func()
    print(ret)

def func1():
      def func2():
        return 123
      r=func2()
      # r = func2()
      return r

func1()
    print(r)

def wrapper(func):
      def inner(*args,**kwargs):#定义函数的时候——*参数的聚合
        ret = func(*args,**kwargs) #调用函数的时候——*参数的打散
        #func是被装饰的函数,ret是被装饰函数的返回值
        return ret #把被装饰的函数的返回值返回给调用者
      return inner


    @wrapper #hahaha = wrapper(hahaha)
    def test(a,b):
      return a+1,b+1

ret = test(1,2)
    print(ret)

转载于:https://www.cnblogs.com/george92/p/8629064.html

相关文章:

Datawhale组队学习周报(第041周)

本周报总结了从 11月22日至11月28日&#xff0c;Datawhale组队学习的运行情况&#xff0c;我们一直秉承“与学习者一起成长的理念”&#xff0c;希望这个活动能够让更多的学习者受益。 第 31 期组队学习已经与大家见面了&#xff0c;这次组队学习一共 11 门开源课程&#xff0…

Redis介绍

redis是一个key-value存储系统。和Memcached类似&#xff0c;但是解决了断电后数据完全丢失的情况&#xff0c;它支持存储的value类型相对更多&#xff0c;包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hashs&#xff08;哈希类型&#xff09;。这…

oracle精度制的数据类型,ORACLE 中NUMBER 类型 低精度转换成高精度

Node&period;js的函数返回值先看一段代码: function select(sqlscript){ var result ""; sql.connect(config, function( ...LeetCode Range Sum Query 2D - Mutable原题链接在这里:https://leetcode.com/problems/range-sum-query-2d-mutable/ 题目: G…

cacti监控linux和windows磁盘IO

cacti监控linux和windows磁盘IO 标签&#xff1a;cacti linux磁盘IO windows磁盘IO原创作品&#xff0c;允许转载&#xff0c;转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://charlie928.blog.51cto.com/3741218/1331780一&#x…

2021 线性代数 第三章 习题课

第3章 向量空间 3.1 基本概念&#xff08;基础部分&#xff09;3.1 基本概念&#xff08;提高部分&#xff09; -> 插入视频 3.2 线性相关、线性无关&#xff08;基础部分&#xff09;3.2 线性相关、线性无关&#xff08;提高部分&#xff09;3.3 向量空间的基与维数、坐…

MYSQL修改配置,允许远程访问

1、 mysql -h localhost -u root //这样应该可以进入MySQL服务器 2、 GRANT ALL PRIVILEGES ON *.* TO root% WITH GRANT OPTION //赋予任何主机访问数据的权限 如果需要密码&#xff1a; GRANT ALL PRIVILEGES ON *.* TO roo…

ckeditor finder php,CKEDITOR CKFINDER的图片上传配置(C#/asp.net/php)

CKEDITORCKFINDER的图片上传配置(C#/asp教程.net/php教程)phpkeditor的代码全部重写&#xff0c;但里面没有了上传功能&#xff0c;只是一个纯粹的文件在线编辑器&#xff0c;如果需要上传图片&#xff0c;还需要下载ckfinder。首先去官方上下载源代码&#xff0c;然后分别解压…

Linux 常用命令——df, du, ln

1. df 列出文件系统的整体磁盘使用量 2. du 评估文件系统的磁盘使用量(常用在推估目录所占容量)&#xff0c;也可以计算文件或文件夹大小 3. ln 创建实体连接(hard link) 或 符号连接(Symbolic Link) 转载于:https://www.cnblogs.com/bigben0123/p/3238199.html

nio selector

为什么使用Selector? 仅用单个线程来处理多个Channels的好处是&#xff0c;只需要更少的线程来处理通道。事实上&#xff0c;可以只用一个线程处理所有的通道。对于操作系统来说&#xff0c;线程之间上下文切换的开销很大&#xff0c;而且每个线程都要占用系统的一些资源&…

青少年编程竞赛交流群周报(第039周)

2021年11月28日&#xff08;周日&#xff09;晚20:00我们在青少年编程竞赛交流群开展了第三十九期直播活动。 一、直播内容 我们直播活动的主要内容如下&#xff1a; 讲解了上次测试中小朋友们做错的题目 Scratch青少年编程能力等级测试模拟题&#xff08;四级&#xff09;。…

linux查找以h结尾的文件,【linux_笔记】Linux_文件查找(find)详解特殊权限

学习记录过程中难免出现错误&#xff0c;如有发现&#xff0c;还望大神们指出。示例操作部分有的与历史操作有关&#xff0c;如果先前的示例操作没有执行过的话&#xff0c;可能会有部分示例的操作无法执行。示例仅供参考(练习题在附录)。文件查找&#xff1a;locate(不常用):非…

AngulerJS学习(五)按需动态载入文件

在此之前我么年首先要先了解几个东西&#xff1a; $q 简单介绍&#xff1a; $q&#xff1a;主要解决的是异步编程的问题&#xff0c;是指描写叙述通过一个承诺行为与对象代表的异步运行的行动结果的交互。可能会也可能不会再不论什么时候完毕。 我们通过一个小故事理解 $q 服务…

【青少年编程竞赛交流】11月份微信图文索引

11月份微信图文索引 由于“组队学习”这个公众号的功能主要是组织Datawhale社群中的学习者们每个月的组队学习&#xff0c;所以&#xff0c;我另外新建了这个微信公众号“青少年编程竞赛交流”&#xff0c;在这个公众号上分享有关青少年编程方面的知识&#xff0c;以及通过编程…

linux内核创建节点,Linux内核驱动自动创建设备节点文件

Linux下生成驱动设备节点文件的方法有3个&#xff1a;1、手动mknod&#xff1b;2、利用devfs&#xff1b;3、利用udev在刚开始写Linux设备驱动程序的时候&#xff0c;很多时候都是利用mknod命令手动创建设备节点&#xff0c;实际上Linux内核为我们提供了一组函数&#xff0c;可…

javascript publish/subscribe or observer pattern

定义 定义一对多的对象封装&#xff0c;目标对象状态发生变化&#xff0c;它所有的接受者都会收到通知并做相应的更新。 使用频率&#xff1a;5/5 最高 概要 观察者模式&#xff0c;也就是发布者/订阅者模式&#xff0c;当发布者发布一个通知的时候&#xff0c;订阅者就会收到通…

图的遍历——DFS(邻接矩阵)

递归 标记 一个连通图只要DFS一次&#xff0c;即可打印所有的点。 #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <malloc.h>using namespace std;const int VERTEX_NUM 20; const int INFINITY 0x…

徐韬:CCF - 个贷违约预测Baseline

徐韬是华北电力大学数理系大四的学生&#xff0c;Datawhale成员/Dreamtech成员&#xff0c;参加了多期Datawhale的组队学习&#xff0c;也在天池/CCF/讯飞等比赛中取得了不错的成绩&#xff0c;现保送大连理工大学软件学院深造。 这篇图文是他在线下组队学习时&#xff0c;为大…

linux 创建crontab文件位置,[基础教程]linux系统的crontab计划任务添加和删除

在linux系统中&#xff0c;有时候为了节省人力&#xff0c;所以将一些脚本进行定时执行&#xff0c;通过crontab计划任务进行启动和停止&#xff0c;这样能方便大部分时间来做其他事情&#xff0c;下面主要介绍一下如何启动和删除crontab计划任务添加计划任务1.首先要准备好要添…

C#利用lambda在函数中创建内部函数

有使用过JS的朋友&#xff0c;相信都知道function。JS中的function是可以在里面在定义一个作为内部使用的。有时为了控制作用域&#xff0c;或者这种小函数只在这个函数体内会使用&#xff0c;所以就不希望在外部在作额外的定义。那C#中有没有这样类似的方式呢&#xff1f;答案…

IntellJ_打开选中的文件所在的文件夹

方法&#xff08;一&#xff09;最简单 idea 打开 setting 找到keymap 搜索 show in explorer 右键设置一个快捷键 我一般设置 alt v 然后点击项目其中一个文件位置 比如我点击一个 hellowworld.class 然后我按 alt v 就会自己打开他在本地的位置 方法&#xff08;二&#x…

姜子上:利用BiLSTM-CRF进行命名实体识别

姜子上是华北电力大学数理系大二的学生&#xff0c;LSGO软件技术团队&#xff08;Dreamtech算法组&#xff09;成员&#xff0c;参加了多期Datawhale的组队学习。 这篇图文是他在线下组队学习时&#xff0c;为大家分享自己学习“知识图谱”过程中的笔记。 希望参与我们线下组…

linux命令行3d,Linux命令行快捷键

总结一下&#xff1a;1.移动光标&#xff1a;1.1 行首 ctrla1.2 行末 ctrle1.3 前移一字符 ctrlb(注&#xff1a;因为左边的内容先于右边输入 &#xff0c;故向左为向前&#xff0c;向右为向后)1.4 后移一字符 ctrlf1.5 前移一词 altb1.6 后移一词 altf2.删除2.1 删除至行首 ct…

Linux系统配置VI或VIM的技巧

Linux系统配置VI或VIM的技巧作者&#xff1a;IT专家网论坛出处&#xff1a;IT专家网论坛2008-10-28 11:08配置VI和VIM的颜色显示&#xff0c;使它能够高亮度显示一些特别的单词&#xff0c;这对编写程序很有用⋯⋯  1、VI或VIM的配置文件的路径  发现/usr/share/vim/vimrc和…

【组队学习】十一月微信图文索引

十一月微信图文索引 一、组队学习相关 周报&#xff1a; Datawhale组队学习周报&#xff08;第037周&#xff09;Datawhale组队学习周报&#xff08;第038周&#xff09;Datawhale组队学习周报&#xff08;第039周&#xff09;Datawhale组队学习周报&#xff08;第040周&…

僵尸(bot)程序缓解

2019独角兽企业重金招聘Python工程师标准>>> 与浮在表面而广受关注的间谍软件、广告软件、垃圾邮件不同&#xff0c;僵尸程序往往不受注意。它们是散发间谍软件、广告软件、垃圾邮件的罪魁祸首&#xff0c;已经被列为对个人用户及企业 威胁不断增加的一种安全危害。…

Linux火狐解压完运行不了,在Ubuntu系统下firefox账号无法登录的解决

在Ubuntu 16.04系统下默认自带有firefox浏览器&#xff0c;但是使用这个firefox浏览器会发现账号无法登录&#xff0c;原来是在windows系统下的数据没有办法同步&#xff0c;书签也同步不了。经过查询资料后得知&#xff0c;Ubuntu系统下自带的firefox浏览器是国际版本&#xf…

[亿能测试_www.gdtesting.com]测试技术资料网盘共享

[亿能测试_www.gdtesting.com]测试技术资料网盘共享: http://pan.baidu.com/share/home?uk974090852 转载于:https://www.cnblogs.com/preftest/p/3249341.html

【NCEPU】吴丹飞:新闻文章点击预测

吴丹飞是华北电力大学数理系大三的学生&#xff0c;LSGO软件技术团队&#xff08;Dreamtech算法组&#xff09;成员&#xff0c;参加了多期Datawhale的组队学习&#xff0c;荣获多期优秀队长的称号。 这篇图文是她在线下组队学习时&#xff0c;为大家分享自己参与天池“新闻文…

centos中执行apt-get命令提示apt-get command not found

在centos下用yum install xxxyum和apt-get的区别一般来说著名的linux系统基本上分两大类&#xff1a; 1.RedHat系列&#xff1a;Redhat、Centos、Fedora等 2.Debian系列&#xff1a;Debian、Ubuntu等 RedHat 系列 1 常见的安装包格式 rpm包,安装rpm包的命令是“rpm -参数” 2 包…

在linux上装git教程,教你玩转Git-Linux 平台上安装

导读Git 是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件。Git 与常用的版本控制工具 CVS, Subversion 等不同&#xff0c;它采用了分布式版本库的方…