python executemany执行延迟_运维架构师-Python 自动化运维开发-031

*运维架构师-Python 自动化运维开发-031

十九、Python3 操作数据库

1、Python3 操作 MySQL

1、基本介绍

  • Python3 操作 MySQL 数据库 可以使用的模块是 pymysqlMySQLdb
  • 这个两个模块都是通过自己的 API 执行原生的 SQL 语句实现的。
  • MySQLdb 是最早出现的一个操作 MySQL 数据库的模块,核心由C语言编写,接口精炼,性能最棒,缺点是环境依赖较多,安装稍复杂,近两年已停止更新,且只支持Python2.x,不支持Python3.x。
  • pymysql 为替代 MySQLdb 而生,纯 Python 实现,API 的接口与 MySQLdb 完全兼容,安装方便,支持Python3。
  • 2020 已经离我们很近了,所以,我们这里只聊 pymysql

2、 安装包 pymysql

pymsql是Python中操作MySQL的模块(Linux 机器)

pip3 install pymysql

3、 基本操作

1、创建表

import pymysql 
创建连接
conn = pymysql.connect(host='172.16.153.10',port=3306,user='root',passwd='123', db='shark_db',charset='utf8mb4')
获取游标对象
cursor = conn.cursor()
定义 sql 语句
create_table_sql = """create table t1(id int auto_increment primary key, name varchar(10) not null, age int not null)"""
​
执行 sql 语句
cursor.execute(create_table_sql)提交
conn.commit()
​
关闭游标对象
cursor.close()
​
关闭连接对象
conn.close()

2、插入数据

一次插入一条数据

一次插入一条数据, 并且使用变量占位符
insert_data_sql = "insert into t1(name, age) values(%s, %s);"
row = cursor.execute(insert_data_sql, ('shark', 18))
​
conn.commit()
cursor.close()
conn.close()

一次插入多条数据

定义插入数据的语句
many_sql = "insert into t1 (name, age) values(%s, %s)"
​
一次插入多条数据
row = cursor.executemany(many_sql, [('shark1', 18),('xiguatian', 20),('qf', 8)])
​
conn.commit()
cursor.close()
conn.close()

3、查询数据

1、获取到的数据是元组类型

定义一个查询语句
query_sql = "select id,name,age from t1 where name=%s;"
​
执行查询语句,并且返回得到结果的行数
row_nums = cursor.execute(query_sql, ('shark2'))
​
"""
获取到数据结果集具有迭代器的特性:
1. 可以通过索引取值,可以切片
2. 结果集中的数据每次取出一条就少一条
"""
​
获取数据中的第一条 10元
one_data = cursor.fetchone()
​
获取数据中的指定数量的条目  20元
many_data = cursor.fetchmany(2)
​
获取数据中剩余的全部数据  70元
all_data = cursor.fetchall()
​
cursor.close()
conn.close()
print(row_nums)
print(one_data)
print(many_data)
print(all_data)

2、获取到的数据是字典类型的

游标设置为字典类型
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
​
query_sql = "select id,name,age from t1 where name=%s;"
​
row_nums = cursor.execute(query_sql, ('shark2'))
​
获取结果的操作和之前的一样
result = cursor.fetchone()
conn.commit()
cursor.close()
conn.close()
​
print(result)

4、应该加入异常处理

import pymysql# 创建连接
conn = pymysql.connect(host='172.16.153.10',port=3306,user='root',passwd='123', db='shark_db')
​
# 创建游标
cursor = conn.cursor()try:cursor.executemany("INSERT INTO para5(name,age) VALUES(%s,%s);", [('次牛444', '12'), ("次牛2", '11'), ('次牛3', '10')])conn.commit()
except Exception as e:# 如果执行sql语句出现问题,则执行回滚操作conn.rollback()print(e)
finally:# 不论try中的代码是否抛出异常,# 这里都会执行关闭游标和数据库连接cursor.close()conn.close()

5、 获取新增数据的自增 ID

# 先连接
cursor = conn.cursor()
cursor.executemany("insert into student(name,age, phone)values(%s,%s, %s)",[ ("superman5110",18, '13295686769')]   )
conn.commit()
cursor.close()
conn.close()# 获取最新自增ID
new_id = cursor.lastrowid

6、操作存储过程(扩展)

无参数存储过程

cursor.callproc('p1')  #等价于cursor.execute("call p1()")

有参存储过程

cursor.callproc('p2', args=(1, 22, 3, 4))
​
#获取执行完存储的参数,参数@开头
cursor.execute("select @p2,@_p2_1,@_p2_2,@_p2_3")  #{'@_p2_1': 22, '@p2': None, '@_p2_2': 103, '@_p2_3': 24}
​
​
row_1 = cursor.fetchone()

2、Python3 操作 Redis

1、简单介绍

redis是一个key-value存储系统,和Memcached类似。它支持存储的value类型相对更多,包括string(字符串)、list(链表、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。

这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。

与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

1. 使用Redis有哪些好处?
(1) 速度快,因为数据存在内存中,类似于HashMap,HashMap的优势就是查找和操作的时间复杂度都是O(1)
(2) 支持丰富数据类型,支持string,list,set,sorted set,hash
(3) 支持事务,操作都是原子性,所谓的原子性就是对数据的更改要么全部执行,要么全部不执行
(4) 丰富的特性:可用于缓存,消息,按key设置过期时间,过期后将会自动删除

2、安装 redis 软件

yum install redis      #需要epel源
systemctl start redis

命令列表

redis-server                # Redis 服务器
redis-cli                   # Redis 自带的客户端
redis-benchmark             # Redis 性能测试工具
redis-check-aof             # AOF 文件修复工具

Redis 默认监听 6379 端口

3、Redis 命令

Redis 命令用于在 redis 服务上执行操作。

要在 redis 服务上执行命令需要一个 redis 客户端。Redis 客户端在我们之前下载的的 redis 的安装包中。

语法

Redis 客户端的基本语法为:

$ redis-cli

以下实例讲解了如何启动 redis 客户端:

启动 redis 客户端,打开终端并输入命令 redis-cli。该命令会连接本地的 redis 服务。

$redis-cli
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PINGPONG

在以上实例中我们连接到本地的 redis 服务并执行 PING 命令,该命令用于检测 redis 服务是否启动。

在远程服务上执行命令

如果需要在远程 redis 服务上执行命令,同样我们使用的也是 redis-cli 命令。

语法

$ redis-cli -h host -p port -a password

以下实例演示了如何连接到主机为 127.0.0.1,端口为 6379 ,密码为 mypass 的 redis 服务上。

$redis-cli -h 127.0.0.1 -p 6379 -a "mypass"
redis 127.0.0.1:6379>
redis 127.0.0.1:6379> PINGPONG

4、Redis 数据类型

Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

1、String(字符串)

string 是 redis 最基本的类型,你可以理解成与 Memcached 一模一样的类型,一个 key 对应一个 value。

string 类型是二进制安全的。意思是 redis 的 string 可以包含任何数据。比如jpg图片或者序列化的对象。

string 类型是 Redis 最基本的数据类型,string 类型的值最大能存储 512MB。

redis 127.0.0.1:6379> SET name "ganfan"
OK
redis 127.0.0.1:6379> GET name
"ganfan"

在以上实例中我们使用了 Redis 的 SETGET 命令。键为 name,对应的值为 qianfeng

注意:一个键最大能存储512MB。

2、Hash(哈希)

Redis hash 是一个键值(key=>value)对集合。

Redis hash 是一个 string 类型的 field 和 value 的映射表,hash 特别适合用于存储对象。

DEL qianfeng 用于删除前面测试用过的 key,不然会报错:(error) WRONGTYPE Operation against a key holding the wrong kind of value

redis 127.0.0.1:6379> DEL qianfeng
redis 127.0.0.1:6379> HMSET myhash field1 "Hello" field2 "World"
"OK"
redis 127.0.0.1:6379> HGET myhash field1
"Hello"
redis 127.0.0.1:6379> HGET myhash field2
"World"

实例中我们使用了 Redis HMSET, HGET 命令,HMSET 设置了两个 field=>value 对, HGET 获取对应 field 对应的 value

每个 hash 可以存储 2**32-1 键值对(40多亿)。

3、List(列表)

Redis 列表是简单的字符串列表,按照插入顺序排序。你可以添加一个元素到列表的头部(左边)或者尾部(右边)。

redis 127.0.0.1:6379> lpush qianfeng redis
(integer) 1
redis 127.0.0.1:6379> lpush qianfeng mongodb
(integer) 2
redis 127.0.0.1:6379> lpush qianfeng rabitmq
(integer) 3
redis 127.0.0.1:6379> lrange qianfeng 0 10
1) "rabitmq"
2) "mongodb"
3) "redis"
redis 127.0.0.1:6379>

在以上实例中我们使用了 LPUSH 将三个值插入了名为 qianfeng 的列表当中。

列表最多可存储 232 - 1 元素 (4294967295, 每个列表可存储40多亿)。

4、Set(集合)

Redis的Set是string类型的无序集合。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是0(1)。

1、sadd 命令

添加一个 string 元素到 key 对应的 set 集合中,成功返回1,如果元素已经在集合中返回 0,如果 key 对应的 set 不存在则返回错误。

sadd key memberredis 127.0.0.1:6379> sadd qianfeng1 redis
(integer) 1
redis 127.0.0.1:6379> sadd qianfeng1 mongodb
(integer) 1
redis 127.0.0.1:6379> sadd qianfeng1 rabitmq
(integer) 1
redis 127.0.0.1:6379> sadd qianfeng1 rabitmq
(integer) 0
redis 127.0.0.1:6379> smembers qianfeng11) "redis"
2) "rabitmq"
3) "mongodb"

注意:以上实例中 rabitmq 添加了两次,但根据集合内元素的唯一性,第二次插入的元素将被忽略。

集合中最大的成员数为 2**32 - 1(4294967295, 每个集合可存储40多亿个成员)。

5、zset(sorted set:有序集合)

Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。

不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。

有序集合的成员是唯一的,但分数(score)却可以重复。

集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。。

double 和 float 的区别是 double精度高,有效数字16位,float精度7位。但double消耗内存是float的两倍,double的运算速度比float慢得多

1、zadd 命令

添加元素到集合,元素在集合中存在则更新对应score

zadd key score member redis 127.0.0.1:6379> ZADD qianfengkey 1 redis
(integer) 1
redis 127.0.0.1:6379> ZADD qianfengkey 2 mongodb
(integer) 1
redis 127.0.0.1:6379> ZADD qianfengkey 3 mysql
(integer) 1
redis 127.0.0.1:6379> ZADD qianfengkey 3 mysql
(integer) 0
redis 127.0.0.1:6379> ZADD qianfengkey 4 mysql
(integer) 0
redis 127.0.0.1:6379> ZRANGE qianfengkey 0 10 WITHSCORES
​
1) "redis"
2) "1"
3) "mongodb"
4) "2"
5) "mysql"
6) "4"

在以上实例中我们通过命令 ZADD 向 redis 的有序集合中添加了三个值并关联上分数。

5、Python 操作 Redis

所见即所得的东西,讲一部分,其他按照笔记看。不要求都掌握。

1、安装包

pip3 install redis

2、连接

In [1]: import redis
​
In [2]: r = redis.Redis(host='10.18.42.174', port=6379)
​
In [3]: r.set("QF", "www.qfedu.com")
Out[3]: TrueIn [4]: r.get("QF")
Out[4]: b'www.qfedu.com'
​
In [5]: ret = r.get("QF")In [6]: ret.decode()
Out[6]: 'www.qfedu.com'

3、连接池

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。

默认,每个Redis实例都会维护一个自己的连接池。

可以直接建立一个连接池,然后作为参数传给Redis,这样就可以实现多个 Redis 实例共享一个连接池

In [12]: pool = redis.ConnectionPool(host='172.16.153.134', port=6379)
​
In [13]: rs = redis.Redis(connection_pool=pool)
​
In [14]: rs.set("foo", "bar")
Out[14]: True
​
In [15]: rs.get("foo")
Out[15]: b'bar'

4、基本操作

  • String 操作
    redis中的 String 在内存中按照一个name对应一个value来存储
set(name, value, ex=None, px=None, nx=False, xx=False)
​
set() """在 Redis 中设置值,默认,不存在则创建,存在则修改参数:ex,过期时间(秒)px,过期时间(毫秒)nx,假如设置为True,则只有 name 不存在时,当前 set 操作才执行xx,假如设置为True,则只有 name 存在时,当前 set 操作才执行"""setnx(name, value)
​# 设置值,只有name不存在时,执行设置操作(添加)setex(name, value, time)
​
"""设置值参数:time,过期时间(数字秒)
"""
​
psetex(name, time_ms, value)
​
"""设置值参数:time_ms,过期时间(数字毫秒)
"""
​
mset(*args, **kwargs)
​
"""
批量设置值:mset(QF='www.qfedu.com', yangge='杨哥')或mget({'k1': 'v1', 'k2': 'v2'})
"""
​
get(name)
​# 获取值mget(keys, *args)
"""
批量获取:mget('QF', 'foo')或mget(['QF', 'foo'])
"""
​
​
getset(name, value)
​
# 设置新值并获取原来的值
​
getrange(key, start, end)
​
# 以字节的方式获取一部分值(一个汉字等于三个字节)
​
setrange(name, offset, value)
"""
修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加)
参数:offset  字符串的索引,字节方式
"""
​
incr(self, name, amount=1)
​
"""自增 name对应的值,当name不存在时,则创建 name=amount,否则,则自增。参数:name,Redis的nameamount,自增数(必须是整数)
"""
​
decr(self, name, amount=1)
# 自减
​
append(key, value)
​
# 在redis name对应的值后面追加内容
  • Hash 操作

d0e01abb06958edd2496fdefcf9a0474.png

3482e602699fc29178aaedcb195fde29.png
hset(name, key, value)
#*************************
In [20]: rs.hset("hs1","k1", "v1")
Out[20]: 0
​
#*************************
​
"""name 对应的 hash 中设置一个键值对(不存在,则创建;否则,修改)参数:name,redis hash的namekey,name对应的hash中的keyvalue,name对应的hash中的value注意:# hsetnx(name, key, value),当name对应的hash中不存在当前key时则创建(相当于添加)
"""
​
hmset(name, mapping)
#*************************
In [6]: rs.hmset('hs1', {'k1':'v1', 'k2': 'v2'})
Out[6]: True
#*************************
​
"""
在name对应的hash中批量设置键值对,没有的 key 就创建,已存在的 key 修改参数:mapping,字典,栗子:{'k1':'v1', 'k2': 'v2'}
"""hget(name,key)
#*************************
In [8]: rs.hget('hs1','k1')
Out[8]: b'v1'
#*************************
​
# 在name对应的hash中获取根据key获取value
​
hmget(name, keys, *args)
"""在name对应的hash中获取多个key的值参数:name,reids对应的namekeys,要获取key集合,栗子:['k1', 'k2', 'k3']*args,要获取的key,栗子:k1,k2,k3栗子:r.mget('xx', ['k1', 'k2'])或r.hmget('xx', 'k1', 'k2')
"""################### 下面的自己搞 ########################
hgetall(name)
# 获取name对应hash的所有键值
​
hlen(name)
# 获取name对应的hash中键值对的个数
​
hkeys(name)
# 获取name对应的hash中所有的key的值
​
hvals(name)
# 获取name对应的hash中所有的value的值
​
hexists(name, key)
# 检查name对应的hash是否存在当前传入的key
​
hdel(name,*keys)
# 将name对应的hash中指定key的键值对删除
​
hincrby(name, key, amount=1)
"""自增name对应的hash中的指定key的值,不存在则创建key=amount参数:name,redis中的namekey, hash对应的keyamount,自增数(整数)
"""
​
hincrbyfloat(name, key, amount=1.0)
"""自增name对应的hash中的指定key的值,不存在则创建key=amount参数:name,redis中的namekey, hash对应的keyamount,自增数(浮点数)
"""
​# 更多 http://redisdoc.com/key/scan.html#scan
  • List 操作
lpush(name,values)
"""在name对应的list中添加元素,每个新的元素都添加到列表的最左边栗子:r.lpush('oo', 11,22,33)保存顺序为: 33,22,11扩展:rpush(name, values) 表示从右向左操作
"""
​
lpushx(name,value)
"""在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边更多:rpushx(name, value) 表示从右向左操作
"""
​
llen(name)
# name对应的list元素的个数
​
linsert(name, where, refvalue, value))
"""在name对应的列表的某一个值前或后插入一个新值参数:name,redis的namewhere,BEFORE或AFTERrefvalue,标杆值,即:在它前后插入数据value,要插入的数据
"""
​
r.lset(name, index, value)
"""对name对应的list中的某一个索引位置重新赋值参数:name,redis的nameindex,list的索引位置value,要设置的值
"""
​
r.lrem(name, value, num)
"""在name对应的list中删除指定的值参数:name,redis的namevalue,要删除的值num,  num=0,删除列表中所有的指定值;num=2,从前到后,删除2个;num=-2,从后向前,删除2个
"""
​
lpop(name)
"""在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素扩展:# rpop(name) 表示从右向左操作
"""
​
lindex(name, index)
"""
在name对应的列表中根据索引获取列表元素
lrange(name, start, end)
​在name对应的列表分片获取数据参数:name,redis的namestart,索引的起始位置end,索引结束位置
"""
​
ltrim(name, start, end)
"""在name对应的列表中移除没有在start-end索引之间的值参数:name,redis的namestart,索引的起始位置end,索引结束位置
"""
​
rpoplpush(src, dst)
"""从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边参数:src,要取数据的列表的namedst,要添加数据的列表的name
"""
​
blpop(keys, timeout)
"""将多个列表排列,按照从左到右去pop对应列表的元素参数:keys,redis的name的集合timeout,超时时间,当元素所有列表的元素获取完之后,阻塞等待列表内有数据的时间(秒), 0 表示永远阻塞扩展:r.brpop(keys, timeout),从右向左获取数据
"""
​
brpoplpush(src, dst, timeout=0)
"""从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧参数:src,取出并要移除元素的列表对应的namedst,要插入元素的列表对应的nametimeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
"""
​
​
#########   自定义增量迭代 ######### 
"""由于redis类库中没有提供对列表元素的增量迭代,假如想要循环name对应的列表的所有元素,那么就需要:1、获取name对应的所有列表2、循环列表但是,假如列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
"""
​def list_iter(name):"""自定义redis列表增量迭代:param name: redis中的name:return: yield 返回 列表元素"""list_count = r.llen(name)for index in xrange(list_count):yield r.lindex(name, index)# 使用
for item in list_iter('pp'):print(item)
  • Set 操作
    也是列表形式,但是其内的元素不允许重复
sadd(name,values)
# name对应的集合中添加元素
​
scard(name)
# 获取name对应的集合中元素个数
​
sdiff(keys, *args)
# 差集,在第一个name对应的集合中且不在其他name对应的集合的元素集合
​
sdiffstore(dest, keys, *args)
# 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
​
sinter(keys, *args)
# 获取一个name对应集合的交集
​
sinterstore(dest, keys, *args)
# 获取多一个name对应集合的并集,再讲其加入到dest对应的集合中
​
sismember(name, value)
# 检查value是不是name对应的集合的成员
​
smembers(name)
# 获取name对应的集合的所有成员
​
smove(src, dst, value)
# 将某个成员从一个集合中移动到另外一个集合
​
spop(name)
# 从集合的右侧(尾部)移除一个成员,并将其返回
​
srandmember(name, numbers)
# 从name对应的集合中随机获取 numbers 个元素
​
srem(name, values)
# 在name对应的集合中删除某些值
​
sunion(keys, *args)
# 获取多一个name对应的集合的并集
​
sunionstore(dest,keys, *args)
# 获取多一个name对应的集合的并集,并将结果保存到dest对应的集合中
  • Sort Set 操作
    有序集合,在集合的基础上,为每元素排序;元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。
    zadd(name, *args, **kwargs)
    """
    在 name 对应的有序集合中添加元素
    例如:
    zadd('something', 'n1', 1, 'n2', 2)

    zadd('something', n1=11, n2=22)
    """

    zcard(name)
    # 获取name对应的有序集合元素的数量

    zcount(name, min, max)
    # 获取name对应的有序集合中分数 在 [min,max] 之间的个数

    zincrby(name, value, amount)
    # 自增name对应的有序集合的 name 对应的分数

    r.zrange( name, start, end, desc=False, withscores=False, score_cast_func=float)
    """
    按照索引范围获取name对应的有序集合的元素
    参数:
    name,redis的name
    start,有序集合索引起始位置(非分数)
    end,有序集合索引结束位置(非分数)
    desc,排序规则,默认按照分数从小到大排序
    withscores,是否获取元素的分数,默认只获取元素的值
    score_cast_func,对分数进行数据转换的函数
    更多:
    从大到小排序
    zrevrange(name, start, end, withscores=False, score_cast_func=float)
    按照分数范围获取name对应的有序集合的元素
    zrangebyscore(name, min, max, start=None, num=None, withscores=False, score_cast_func=float)
    从大到小排序
    zrevrangebyscore(name, max, min, start=None, num=None, withscores=False, score_cast_func=float)
    """

    zrank(name, value)
    """
    获取某个值在 name对应的有序集合中的排行(从 0 开始)
    更多:
    zrevrank(name, value),从大到小排序
    """

    zrangebylex(name, min, max, start=None, num=None)
    """
    当有序集合的所有成员都具有相同的分值时,有序集合的元素会根据成员的 值 (lexicographical ordering)来进行排序,而这个命令则可以返回给定的有序集合键 key 中, 元素的值介于 min 和 max 之间的成员
    对集合中的每个成员进行逐个字节的对比(byte-by-byte compare), 并按照从低到高的顺序, 返回排序后的集合成员。 如果两个字符串有一部分内容是相同的话, 那么命令会认为较长的字符串比较短的字符串要大
    参数:
    name,redis的name
    min,左区间(值)。 + 表示正无限; - 表示负无限; ( 表示开区间; [ 则表示闭区间
    min,右区间(值)
    start,对结果进行分片处理,索引位置
    num,对结果进行分片处理,索引后面的num个元素
    例子:
    ZADD myzset 0 aa 0 ba 0 ca 0 da 0 ea 0 fa 0 ga
    r.zrangebylex('myzset', "-", "[ca") 结果为:['aa', 'ba', 'ca']
    扩展:
    从大到小排序
    zrevrangebylex(name, max, min, start=None, num=None)
    """

    zrem(name, values)
    # 删除name对应的有序集合中值是values的成员
    # 如:zrem('zz', ['s1', 's2'])

    zremrangebyrank(name, min, max)
    # 根据排行范围删除

    zremrangebyscore(name, min, max)
    # 根据分数范围删除

    zremrangebylex(name, min, max)
    # 根据值返回删除

    zscore(name, value)
    # 获取name对应有序集合中 value 对应的分数

    zinterstore(dest, keys, aggregate=None)
    # 获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
    # aggregate的值为: SUM MIN MAX

    zunionstore(dest, keys, aggregate=None)
    # 获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
    # aggregate的值为: SUM MIN MAX

6、发布和订阅

1、发布者

import redis
pool = redis.ConnectionPool(host='172.16.153.136',port=6379,max_connections=10)
conn = redis.Redis(connection_pool=pool)
conn.publish('fm101', '我要上头条')

2、订阅者

import redis
pool = redis.ConnectionPool(host='172.16.153.136',port=6379,max_connections=10)
conn = redis.Redis(connection_pool=pool)
pub = conn.pubsub()
pub.subscribe('fm101')
while True:data = pub.parse_response()print(data)

7、python链接redis操作(作业练习)

redis-py提供两个类Redis和StrictRedis用于实现Redis的命令,StrictRedis用于实现大部分官方的命令,并使用官方的语法和命令,Redis是StrictRedis的子类,用于向后兼容旧版本的redis-py。import redis
#创建redis链接对象
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
#存储键值对
r.set('site','www.qi.cn')
#获取值
print(r.get('site'))
#指定decode_responses为True,表示输出为字符串
red = redis.StrictRedis(host='127.0.0.1',port=6379,decode_responses=True)
​
#默认redis入库编码是utf-8,如果要修改的话,需要指明 charset 和 decode_responsers 为True
#test = redis.StrictRedis(host='localhost', port=6379, db=0, password=None, socket_timeout=None, connection_pool=None, charset='utf-8', errors='strict', decode_responses=False, unix_socket_path=None)
red.lpush('list1','mongdb','redis','mysql')
print(r.lrange('list1',0,-1))
print(r.llen('list1'))
​
#output:
www.qi.cn
['mysql', 'redis', 'mongdb']
3

连接池:

redis-py使用connection pool来管理对一个redis server的所有连接,避免每次建立、释放连接的开销。默认,每个Redis实例都会维护一个自己的连接池。可以直接建立一个连接池,然后作为参数Redis,这样就可以实现多个Redis实例共享一个连接池。

import redis
#创建连接池
pool = redis.ConnectionPool(host='127.0.0.1',port=6379,decode_responses=True)
#创建链接对象
r=redis.Redis(connection_pool=pool)
#设置集合
r.sadd('set1','v1','v2','v3')
r.sadd('set1','v2')
#显示集合的值
print(r.smembers('set1'))
​
#使用strictRedis连接池
rs = redis.StrictRedis(connection_pool=pool)
r.lpush('l1','python','memcache','redis','mongodb')
print(r.lrange('l1',0,-1))
​
​
#output:
{'v3', 'v1', 'v2'}
['mongodb', 'redis', 'memcache', 'python']

(1)数据string操作

redis中的String在在内存中按照一个name对应一个value来存储的。

set key value EX seconds [NX|XX]

参数:

ex,过期时间(秒)
px,过期时间(毫秒)
nx,如果设置为``True``,则只有name不存在时,当前``set``操作才执行
xx,如果设置为``True``,则只有name存在时,岗前``set``操作才执行import redis
#创建连接池
pool = redis.ConnectionPool(host='127.0.0.1',port=6379,decode_responses=True)
#创建链接对象
r=redis.Redis(connection_pool=pool)
r.set('test','dddddddddddd',ex=3,nx=True)
print(r.get('test'))

setnx(name,value):设置值,只有在name不存在是才执行操作

setex(name,value,time):设置值过期时间,单位为秒

psetex(name,time_ms,value):设置值,过期时间为毫秒

mset(*args,**kwargs):批量设置多个值

get(name):获取值

getrange(key,start,end):获取子序列,根据字节获取

setrange(name,oofset,value):修改字符串内容,从指定字符串索引开始向后替换

import redis
#创建连接池
pool = redis.ConnectionPool(host='127.0.0.1',port=6379,decode_responses=True)
#创建链接对象
r=redis.Redis(connection_pool=pool)
r.set('test','12345',nx=True)
r.setrange('test',0,'8888')
print(r.get('test'))

setbit(name,offset,value):对name对应值的二进制表示的位进行操作

getbit(name,offset):获取name对应的二进制位表示的值,只能是0或1

import redis
r=redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.set('name','p')
print(r.get('name'))
#打印p,q对应的ascii码
print(ord('p'),ord('q'))
#打印ascii码对应的二进制
print(bin(ord('p')),bin(ord('q')))
print('修改前7位的值:',r.getbit('name','7'))
#设置二进制位的第7位为1,相当于移动ascii码位112为113对应的字符为q
r.setbit('name','7','1')
print('修改后7位的值:',r.getbit('name','7'))
print(r.get('name'))
​
#output:
p
112 113
0b1110000 0b1110001
修改前7位的值: 0
修改后7位的值: 1
q

strlen(name):返回name对应值的字节长度,一个汉字3个字节

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.set('name','python')
print(r.strlen('name'))  #输出6个字节

incr(self,name,amount=1):自增name对应的值,当name不存在时,则创建name=amount,否则自增

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
#r.set('name','python')
r.set('age','1')
print(r.incr('age','3')) #结果为4

decr(self,name,amount=1):自减 name对应的值,当name不存在时,则创建name=amount,否则,则自减

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
​
r.set('age','10')
print(r.decr('age','3'))  #输出为7

append(key,value):在name对应的值后面追加内容

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.set('age','10')
print(r.get('age'))
print(r.append('age','11'))
print(r.get('age'))
​
#output:
10
4
1011

(2)hash操作

hset(name,key,value):在name对应的hash中设置一个键值对,不存在则创建否则修改

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hset('haset','python','3.5')
print(r.hget('haset','python'))
r.hset('haset','redis','1.8')
print(r.hgetall('haset'))
​
#output:
3.5
{'python': '3.5', 'redis': '1.8'}

hmset(name,mapping):在name对应的hash中批量设置键值对

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'v1','k2':'v2','k3':'v3'})
print(r.hmget('hashmore','k1','k2','k3'))
print(r.hgetall('hashmore'))

hget(name,key):获取hash中的value

hmget(name,keys,*args):获取过个hash的key的值

hgetall(name):获取hash的所有键值对

hlen(name):获取hash中键值对的个数

hkeys(name):获取hash中所有keys的值

hvals(name):获取hash中所有value的值

hexists(name,key):检查hash中是否存在key

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'v1','k2':'v2','k3':'v3'})
print(r.hmget('hashmore','k1','k2','k3'))
print(r.hgetall('hashmore'))
print(r.hexists('hashmore','k2'))
print(r.hexists('hashmore','k4'))
​
#output:
['v1', 'v2', 'v3']
{'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}
True
False

hdel(name,*key):删除hash中的key

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'v1','k2':'v2','k3':'v3'})
print(r.hgetall('hashmore'))
print(r.hdel('hashmore','k3'))
print(r.hgetall('hashmore'))
​
#output:
{'k3': 'v3', 'k2': 'v2', 'k1': 'v1'}
1
{'k2': 'v2', 'k1': 'v1'}

hincrby(name,key,amount=1):自增hash中指定的key的值,不存在则创建key=amount

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'1','k2':'2','k3':'3'})
print(r.hgetall('hashmore'))
r.hincrby('hashmore','k1','2')
print(r.hgetall('hashmore'))

hincrbyfloat(name,key,amount=1.0):自增hash中指定的key的值,同上针对浮点数

hscan(name,cursor=0,match=None,count=None):增量迭代获取hash中数据,cursor游标,match匹配key默认所有,count获取的个数。

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'1','k2':'2','k3':'3','k4':'4'})
print(r.hgetall('hashmore'))
print(r.hscan('hashmore',cursor=2,match='k2',count=1))
print(r.hscan('hashmore',count=4))
​
#output:

{'k1': '1', 'k3': '3', 'k2': '2', 'k4': '4'}(0, {'k2': '2'})(0, {'k1': '1', 'k3': '3', 'k2': '2', 'k4': '4'})

hscan_iter(name,match=None,count=None):利用yield封装hscan创建生成器,实现分批获取数据

import redis
r= redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.hmset('hashmore',{'k1':'1','k2':'2','k3':'3','k4':'4','k5':'5','k6':'6','k7':'7','k8':'8'})
oo = r.hscan_iter('hashmore')
print(next(oo))
print(next(oo))
print(next(oo))
print(next(oo))
​
#output:
('k2', '2')
('k7', '7')
('k8', '8')
('k5', '5')

(3)list操作

lpush(name,values):在列表中添加元素,每个新元素都从左边开始添加

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.lpush('l3',1,2)
print(r.lrange('l3',0,-1))
r.lpush('l3','88')
print(r.lrange('l3',0,-1))
​
#output:
['2', '1']
['88', '2', '1']

lpushx(name,value):在列表中添加元素,只有在name存在时才添加

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.lpushx('l4',1)
print(r.lrange('l4',0,-1))
r.lpush('l4',2)
r.lpushx('l4',1)
print(r.lrange('l4',0,-1))
​
#output:
[]
['1', '2']

llen(name):name对应的list元素的长度

linsert(name,where,refvalue,value):在name对应的列表的某个值前或后插入一个新值,where指定前或后(befor/after),refvalue参考值即指定的元素,value要插入的值

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.lpush('num','1','2')
r.linsert('num','after','2','python')#在2后面添加python元素值
r.linsert('num','before','1','redis') #在1之前插入redis
print(r.lrange('num',0,-1))
​
#output:
['2', 'python', 'redis', '1']

lset(name,index,value):对列表中的某个索引位的值修改

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
print(r.lrange('num',0,-1))
r.lset('num','0','hello')
print(r.lrange('num',0,-1))
​
#output:
['2', 'python', 'redis', '1']
['hello', 'python', 'redis', '1']

lrem(name,value,num):在name对应的list中删除指定的值

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
print(r.lrange('num',0,-1))
r.lrem('num','1','2')   #2为num指定的值的个数,可以指定-2从后往前删除
print(r.lrange('num',0,-1))
​
#output:
['1', 'hello', 'python', 'redis', '1']
['hello', 'python', 'redis']

lpop(name):在name对应的列表的左侧获取第一个元素并删除,并返回参数的元素

lindex(name,index):在name对应的列表中根据索引获取列表元素

ltrim(name,start,end):在name对应的列表中移除start到end之间的值

lrange(name,start,end):列表分片获取数据

rpoplush(src,dst):获取源列表最后一个元素的值,并将它添加到目标列表中的最左边

blpop(keys,timeout):将多个列表排列,按照从左到右去pop对应列表的元素

brpoplpush(src,dst,timeout=0):从一个列表的右侧移除一个元素并将其添加到另一个列表的左侧

(4)set操作

sadd(name,values):添加元素到集合

scard(name):获取集合中元素的个数

sdiff(keys,*args):在第一个集合中的元素且不在其他集合的元素的集合

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.sadd('s1',1,2,3)
r.sadd('s2',4,5,2)
r.sadd('s3',7,8,1)
print(r.sdiff('s1','s2','s3'))
​
#output:
{'3'}

sdiffstore(dest,keys,*args):在第一个keys中的集合元素且不在其他集合中的元素添加到dest新集合中

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
# r.sadd('s1',1,2,3)
# r.sadd('s2',4,5,2)
# r.sadd('s3',7,8,1)
print(r.sdiffstore('s4','s1','s2','s3'))
print(r.smembers('s4'))

sinter(keys,*args):获取多个集合的并集

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)r.sadd('s1',1,2,3)r.sadd('s2',4,5,2)
print(r.sinter('s1','s2'))
​
#output:
{'2'}

sinterstore(dest,keys,*args):获取多个集合的并集并将结果加入到dest集合中

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.sadd('sex1',1,2,3,4)
r.sadd('sex2',4,5,2,7)
r.sadd('sex3',7,8,1,4,2)
r.sinterstore('sex4','sex1','sex2','sex3')
print(r.smembers('sex4'))
​
#output:
{'4', '2'}

sismember(name,value):检查value是否在集合中

import redis
r = redis.Redis(host='127.0.0.1',port=6379,decode_responses=True)
r.sadd('sex3',7,8,1,4,2)
print(r.sismember('sex3','8'))
​
#output:
True

smembers(name):获取集合的所有成员

smove(src,dst,value):将源集合中的某个成员移动到目标集合中

spop(name):从集合的右侧(尾部)移除一个成员,并将其返回

srandmember(name,numbers):从name对应的集合中随机获取 numbers 个元素

srem(name,values):在name对应的集合中删除某些值

sunion(keys,*args):并集显示多个集合元素

sunionstore(dest,keys,*args):获取多一个name对应的集合的并集,并将结果保存到dest对应的集合中

sscan(name,cursor=0,match=None,count=None):同字符串的操作,用于增量迭代分批获取元素,避免内存消耗太大

sscan_iter(name,match=None,count=None):同字符串的操作,用于增量迭代分批获取元素,避免内存消耗太大

(5)有序集合操作

在集合的基础上,为每个元素排序,元素的排序需要根据另外一个值来进行比较,所以,对于有序集合,每一个元素有两个值,即:值和分数,分数专门用来做排序。

  • zadd(name,*args,**kwargs):在name对应的有序集合中添加元素
  • zcard(name):获取name对应的有序集合元素的数量
  • zcount(name,min,max):获取name对应的有序集合中分数 在 [min,max] 之间的个数
  • zincrby(name,value,amount):自增name对应的有序集合的 name 对应的分数
  • r.zrange(name, start, end, desc=False, withscores=Flase, score_cast_func=float):按照索引范围获取name对应的有序集合的元素
  • zrank(name, value):获取某个值在 name对应的有序集合中的排行(从 0 开始)
  • zrangebylex(name, min, max, start=None, num=None):当有序集合的所有成员都具有相同的分值时,有序集合的元素会根据成员的 值
  • zrem(name, values):删除name对应的有序集合中值是values的成员
  • zremrangebyrank(name, min, max): 根据排行范围删除
  • zremrangebyscore(name, min, max):根据分数范围删除
  • zremrangebylex(name, min, max):根据值返回删除
  • zscore(name, values):获取name对应有序集合中 value 对应的分数
  • zinterstore(dest, keys, aggregate=None):获取两个有序集合的交集,如果遇到相同值不同分数,则按照aggregate进行操作
  • zunionstore(dest, keys, aggregate=None):获取两个有序集合的并集,如果遇到相同值不同分数,则按照aggregate进行操作
  • zscan(name, cursor=0, match=None, count=None, score_cast_func=float):同字符串相似,相较于字符串新增score_cast_func,用来对分数进行操作
  • zscan_iter(name, match=None, count=None,score_cast_func=float):同字符串相似,相较于字符串新增score_cast_func,用来对分数进行操作

(6)其他操作

  • delete(*name):根据删除redis中的任意数据类型
  • exists(name):检测redis的name是否存在
  • keys(pattern='*'):根据模型获取redis的name
  • expire(name,time):为某个redis的某个name设置超时时间
  • rename(src, dst):对redis的name重命名为
  • move(name,db):将redis的某个值移动到指定的db下
  • randomkey():随机获取一个redis的name(不删除)
  • type(name):获取name对应值的类型
  • scan(cursor=0,match=None,count=None):同字符串操作,用于增量迭代获取key
  • scan_iter(match=None,count=None):同字符串操作,用于增量迭代获取key

8、python对redis管道操作

redis默认在执行每次请求都会创建(连接池申请链接)和断开(归还连接池)一次连接操作,如果想要再一次请求中指定多个命令,则可以使用pipline实现一次请求指定多个命令,并且默认情况下一次pipline是原子性操作。

import redispool = redis.ConnectionPool(host='0.0.0.0', port=6379)r = redis.Redis(connection_pool=pool)# pipe = r.pipeline(transaction=False)
pipe = r.pipeline(transaction=True)r.set('name', 'python')
r.set('age', '18')pipe.execute()

9、python对redis发布与订阅

demo:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import redis
class RedisHelper:'''类'''def __init__(self):#链接self.__conn = redis.Redis(host='0.0.0.0')self.chan_sub = 'fm104.5'#创建频道self.chan_pub = 'fm104.5'def public(self,info):'''公共的'''self.__conn.publish(self.chan_pub,info)'''将内容发布到频道'''return Truedef subscribe(self):pub = self.__conn.pubsub()pub.subscribe(self.chan_sub)pub.parse_response()return pub

发布者:

#!/usr/bin/env python
# -*- coding:utf-8 -*- 
#导入模块
from redis_demo.demo import RedisHelper
#实例化
obj = RedisHelper()
#把内容发布到频道
obj.public('python')

订阅者:

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from redis_demo.demo import RedisHelperobj = RedisHelper()
redis_sub = obj.subscribe()while True:msg= redis_sub.parse_response()print (msg)print(type(msg))

运行方式:

    先启动demo, 启动订阅者,启动发布者,订阅者接受消息。

欢迎访问磊哥B站主页:千锋云计算磊哥

喜欢文章的话,欢迎点赞收藏评论互动~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489445.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

bilibili 解析_用 Python 抓取 bilibili 弹幕并分析!

时隔一年,嵩哥带来他的新作《雨幕》。他依旧认真创作,追求高品质,作品在发表之前已听了五百遍以上。如此高品质的音乐,大家如何评价呢?通过哔哩哔哩上的视频弹幕,感受一下。01 实现思路首先,利用…

2019中国科学院、中国工程院院士增选名单正式发布

来源:医谷医学讯 今日,“两院”院士2019年增选名单正式公布。中国科学院选举产生了64名中国科学院院士和20名中国科学院外籍院士。中国工程院共选举产生75位院士和29位外籍院士。2019年新当选中国科学院院士名单(共64人,分学部按姓…

微信 小程序 canvas

测试手机为IPHONE6,开发者工具版本0.10.102800。开发者工具0.11.112301版本也一样 微信小程序里的canvas 非 h5 canvas有很多不一样的地方,以下把微信小程序的canvas叫做wxcanvas 下面全是我一点点测试出的干货,耐心看: 1.wxcanvas,不像h5can…

Android App赞赏功能,微信公众号赞赏功能升级:作者可直接收到赞赏, iOS安卓均可用...

DoNews6月6日消息 (记者 费倩文)微信公众平台发布消息称,公众号赞赏功能升级为“喜欢作者”,开启了赞赏的文章在原创文章底部有“喜欢作者”的入口,作者可以直接收到读者赞赏,在 iOS 版和 Android 版微信上都可以使用。据了解&…

hashcode是什么意思_什么才是 Java 的基础知识?

作者:晓风轻链接:zhuanlan.zhihu.com/p/28615617近日里,很多人邀请我回答各种j2ee开发的初级问题,我无一都强调java初学者要先扎实自己的基础知识,那什么才是java的基础知识?又怎么样才算掌握了java的基础知…

BZOJ 1305 二分+网络流

思路: 建图我根本没有想到啊……. (我是不会告诉你我借鉴了一下题解的思路) 把每个人拆成喜欢的和不喜欢的点 男 喜欢 向 男 不喜欢 连 边权为k的边 如果男喜欢女 那么 男喜欢向 女喜欢 连 1 如果男 不喜欢女 那么 男不喜欢 向 女不喜欢 连1…

迄今最详细宇宙模型建成

来源:科技日报一个国际科研团队最近创建了迄今最详细的大尺度宇宙模型TNG50。这一虚拟宇宙“芳龄”约138亿岁、宽约2.3亿光年,包含数万个正处于演化中的星系,星系的细节程度与单星系模型中的相当。该模型跟踪了200多亿个代表暗物质、气体、恒…

线程操作函数

线程的挂起和恢复 DWORD SuspendThread ( HANDLE hThread ); //挂起线程 DWORD ResumeThread ( HANDLE hThread ); //恢复线程 SuspendThread 和 ResumeThread 都返回之前的挂起计数。 一个线程最多可以挂起MAXIMUM_SUSPEND_COUNT (WinNT.h中定义为127次)。 进程的挂起和恢…

先进激光三维成像雷达技术的研究进展与趋势分析

本文内容转载自《激光杂志》2019年第5期,版权归《激光杂志》编辑部所有。杨兴雨,李晨,郝丽婷,王元庆,古丽孜热∙艾尼外南京大学,伊犁师范学院摘要:激光雷达具有体积小、质量轻、探测距离远、高分…

Android Binder 系统学习笔记(一)Binder系统的基本使用方法

1.什么是RPC(远程过程调用) Binder系统的目的是实现远程过程调用(RPC),即进程A去调用进程B的某个函数,它是在进程间通信(IPC)的基础上实现的。RPC的一个应用场景如下: A进…

mongodb 监听不到端口_干货|MongoDB简单操作和通过python进行操作

点击上方“AI遇见机器学习”,选择“星标”公众号重磅干货,第一时间送达这次我们主要来简单的讨论一下在MongoDB中如何更新数据(修改数据),删除数据,以及如何通过Python调用MongoDB。一、简单使用MongoDB操作数据| a.更新数据| i.数…

人工智能+脑机接口:让我们距离“增强人类”越来越近

来源:资本实验室前段时间,一则新闻引发了广泛争议:国内一所小学利用头环来监控孩子的脑电波,以判断孩子上课是否走神。暂且不论该事件是否是一场打着高科技幌子的闹剧,头环本身所代表的脑机接口技术正在受到越来越多的…

哲学的未来

来源:哲学园作者:约翰R塞尔译者:GTY约翰塞尔生于1932年,当代著名哲学家,现为美国加州大学伯克利分校Slusser哲学教授,在语言哲学、心灵哲学和社会哲学领域贡献巨大,是目前在世的最著名的分析哲学…

怎么知道wx.config执行成功没_作为一个减肥40斤,且10年没反弹的普通人,这份瘦身经验分享给你...

“减肥”是女生老生常谈的话题,但是“减肥失败”、“越减越肥”也是很多女生面临的常态。所以做为成功减肥40斤且10多年没有反弹的人,我想来给大家一些自己的经验。很多姑娘知道减肥的关键因素是“热量差”,无论是增加运动,还是减…

html代码type,HTML中type是什么意思

在HTML中,type是类型的意思,是一个标签属性,主要用于定义标签元素的类型或文档(脚本)的MIME类型;例在input标签中type属性可以规定input元素的类型,在script标签中type属性可以规定脚本的MIME类型。推荐:ht…

bzoj1085骑士精神(搜索)

1085: [SCOI2005]骑士精神 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1893 Solved: 1051Description 在一个55的棋盘上有12个白色的骑士和12个黑色的骑士, 且有一个空位。在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1&am…

中国2项上榜:《时代周刊》2019年度100大最佳发明榜单发布!

来源:Time导读:《时代周刊》最新评选出2019年度100大最佳发明!这100项突破性的发明改变了我们的生活、工作、娱乐和思考方式,它们让世界变得更美好,更智能,或更有趣。今天分享其中的20个极具未来感的产品。…

html异形轮播,异形滚动

异形滚动效果图.gif1、原理的揭示前言:图片大小处理问题的解决,当我们只改变盒子大小,图片会溢出,无法充满这个盒子。设置图片的宽高为 100%异形滚动.box {width: 100px;height: 100px;}img { //让图片充满整个盒子width: 100%;he…

【周末阅读】工业互联网的发展历程及实现路径

来源:青岛智能产业技术研究院【导读】目前,我国工业互联网发展迅猛,从国家层面、部委层面、地方层面都在积极推动,国际上对工业互联网发展也比较关注。我主要介绍工业互联网的三个方面内容:工业互联网的基本认识、国内…

三菱fx5u编程手册_FX5U系列PLC控制伺服3种方式

FX5U系列PLC为三菱目前最新的小型PLC,机身小巧却功能强大,不仅保留了三菱小型PLC已有的优点,还吸收了大型PLC的开发理念,在整体性能上得到了很大的提高。本文以FX5U在控制伺服的性能上做个总结,归纳下FX5U控制伺服的3种…