SegmentFault 寸土币争最新的文章
2020-07-30T21:53:46+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
ETH短期介入的最佳位置在哪里?逢低做多继续看涨!
https://segmentfault.com/a/1190000023442024
2020-07-30T21:53:46+08:00
2020-07-30T21:53:46+08:00
寸土币争
https://segmentfault.com/u/liaogx
0
<p><img src="/img/bVbKwvi" alt="image.png" title="image.png"><br><strong>一、分析指标</strong> <br>1. 斐波那契回测 <br>将本轮上涨的 7月21日15点 最低价作为起始点,7月28日06点 最高价作为高点(北京时间)做斐波那契回测。0.382分位是296.83美金,与7月26日01点大增量上行后的收盘价一致;0.5分位是285.56美金,与7月25日04:00点至23:00的阻力位一致; <br>2. 成交量分布图(VP) <br>调出VPVR指标(固定范围7月21日 - 现在),0.382分位下方的295至296美金也是筹码密集群,有支撑作用; <br>3. Vagas通道,EMA12牵引 <br>使用Vagas通道,EMA12作为牵引线,目前1h已经跌破上方通道并逐渐远离,本轮上涨一直没有像样的回调,现在是时候了;4h的Vagas通道上方在继续上行,目前价格为294美金左右,过段时间正好能与短期第一支撑位(斐波那契回测的0.382分位)重合,一个完美的买入点! <br>4. K线形态 <br>切换到4h级别,7月28日04:00收了一根完美的十字星,后面2根下跌阴线,短期的见顶形态值得注意。 </p><p><strong>二、分析的周期包括</strong> <br>1. 1h(短期) 4h(短期) </p><p><strong>三、结论</strong> <br>1. 未来会回调再上涨,逢低做多为主 <br>2. 短期第一支撑位297美金,不要全部梭哈,分批买入 <br>3. 下方第二强力支撑位285.5美金,依然逢低做多。这里要注意止损! </p><p><strong>【交易建议】</strong> <br><strong>心理方面</strong> <br>1. 尽量在心情舒畅,状态好的时候交易,情绪失控时绝对不能操盘 <br>2. 长期的盈利是胜多败少的结果,要承认和接受失败的交易,切忌盲目扛单 <br>3. 在剧烈的砸盘和暴拉过程中不要头脑发热参与交易,火中取栗是无策略无计划的韭菜行为 </p><p><strong>策略方面</strong> <br>1. 盈亏比小的交易,把握不大的轻仓;盈亏比大的交易,很有把握的重仓,看情况用小倍杠杆 <br>2. 每一笔交易都要设置好止盈和止损,即便无法通过分析确定,也要凭心理预期设置 </p><p><strong>投资交流</strong> <br>【个人微信:2820020192】请注明“SF”,交流群免费加入 <br>【微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code>】策略第一时间公众号发布<br><img src="https://segmentfault.com/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"><br>【申明】炒币高风险,所有言论不构成任何投资建议!</p>
做多 没有“踏空”一说,耐心等待回调,减半后牛市才刚刚开始!
https://segmentfault.com/a/1190000023442013
2020-07-30T21:51:25+08:00
2020-07-30T21:51:25+08:00
寸土币争
https://segmentfault.com/u/liaogx
0
<p><img src="/img/bVbKwuW" alt="image.png" title="image.png"><br><strong>一、分析指标</strong> <br>1. 牛熊趋势线 <br>7月26日的增量上行,一举突破了2017年12月17日高点与2019年6月26日高点形成的<strong>下降趋势线</strong>,并成功站稳继续上行!又突破了<strong>减半前(2020年2月13日的高点)10500美金</strong>; <br>2. 成交量分布图(VP) <br>调出VPVR指标(可视范围)不难看出,在7月27日的高点11394.86美金以上,都只有非常稀少的交易筹码(11850美金处有一定的交易量),大趋势上价格如果向上突破,将很快创下<strong>历史新高</strong>; <br>3. Vagas通道,EMA12牵引 <br>使用Vagas通道,EMA12作为牵引线,目前1h刚刚跌破上方通道,有<strong>回调需求</strong>;4h的Vagas通道上方在继续上行,目前价格为10150美金左右; <br>4. 斐波那契回测 <br>将本轮上涨的 7月21日15点 最低价作为起始点,7月28日06点 最高价作为高点(北京时间)做斐波那契回测。0.5分位是10294.14美金,结合交易的筹码密集区,短期回调的支撑位在10350美金。 </p><p><strong>二、分析的周期包括</strong> <br>1. 1h(短期) 4h(短期) <br>2. 1D(中期) <br>3. 1W(长期) </p><p><strong>三、结论</strong> <br>1. 未来会回调再上涨,逢低做多为主 <br>2. 短期宽幅震荡范围是<strong>10350至11850</strong>,越低越买 </p><p><strong>【交易建议】</strong> <br><strong>心理方面</strong> <br>1. 尽量在心情舒畅,状态好的时候交易,情绪失控时绝对不能操盘 <br>2. 长期的盈利是胜多败少的结果,要承认和接受失败的交易,切忌盲目扛单 <br>3. 在剧烈的砸盘和暴拉过程中不要头脑发热参与交易,火中取栗是无策略无计划的韭菜行为 </p><p><strong>策略方面</strong> <br>1. 盈亏比小的交易,把握不大的轻仓;盈亏比大的交易,很有把握的重仓,看情况用小倍杠杆 <br>2. 每一笔交易都要设置好止盈和止损,即便无法通过分析确定,也要凭心理预期设置 </p><p><strong>投资交流</strong> <br>【个人微信:2820020192】请注明“SF”,交流群免费加入 <br>【微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code>】策略第一时间公众号发布<br><img src="https://segmentfault.com/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"><br>【申明】炒币高风险,所有言论不构成任何投资建议!</p>
四种常见链表的实现及时间复杂度分析(Python3版)
https://segmentfault.com/a/1190000020755979
2019-10-21T17:35:37+08:00
2019-10-21T17:35:37+08:00
寸土币争
https://segmentfault.com/u/liaogx
0
<p>四种常见的链表包括:单向链表,单向循环链表,双向链表,双向循环链表。<br><strong>要实现的链表操作包括</strong></p>
<ul>
<li>
<code>is_empty()</code> 判断链表是否为空</li>
<li>
<code>length()</code> 求链表长度</li>
<li>
<code>traversing()</code> 遍历所有节点元素</li>
<li>
<code>add()</code> 头部添加节点</li>
<li>
<code>append()</code> 尾部添加节点</li>
<li>
<code>insert(pos, item)</code> 某个位置插入节点</li>
<li>
<code>remove(item)</code> 删除一个节点</li>
<li>
<code>search(item)</code> 查找某个节点是否存在</li>
</ul>
<p>先初始化节点</p>
<pre><code class="python">class Node(object):
"""单节点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class DoubleNode(Node):
"""双节点"""
def __init__(self, elem):
super(DoubleNode, self).__init__(elem)
self.prev = None</code></pre>
<p>四种链表的实现中,每一个类都继承自<code>object</code>, <code>self.__head</code>是私有变量,不能被子类或外部调用。</p>
<pre><code>class SingleLinkList(object):
"""单向链表"""
def __init__(self, node=None):
self.head = node
def is_empty(self) -> bool:
"""链表是否为空 O(1)"""
return self.head is None
def length(self) -> int:
"""链表长度 O(n)"""
count, cur = 0, self.head
while cur is not None:
cur = cur.next # 不要写错cur = self.head.next, self.__next不是活动指针
count += 1
return count
def traversing(self) -> '':
"""遍历所有节点 O(n)"""
cur = self.head # 不是 self._head
while cur is not None:
print(cur.elem, end=' ')
cur = cur.next
return ''
def add(self, item) -> None:
"""头部添加节点 O(1)"""
node = Node(item)
node.next = self.head
self.head = node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = Node(item)
cur = self.head
if self.is_empty():
self.head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
pre, cur = None, self.head
while cur is not None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
break # 只remove第一个元素
pre.next = cur.next
break
pre = cur
cur = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
cur = self.head
while cur is not None:
if cur.elem == item:
return True
cur = cur.next
return False</code></pre>
<pre><code>class SingleCycleLinkList(object):
"""单向循环链表"""
def __init__(self, node=None):
self.__head = node
if node:
node.next = node
def is_empty(self) -> bool:
"""链表是否为空 O(1)"""
return self.__head is None
def length(self) -> int:
"""链表长度 O(n)"""
if self.is_empty():
return 0
count, cur = 1, self.__head
while cur.next != self.__head:
cur = cur.next # 不要写错cur = self.__head.next, self.__next不是活动指针
count += 1
return count
def transverse(self) -> '':
"""遍历所有节点 O(n)"""
if not self.is_empty():
cur = self.__head # 不是 self._head
while cur.next != self.__head:
print(cur.elem, end=' ')
cur = cur.next
print(cur.elem, end=' ')
return ''
def add(self, item) -> None:
"""头部添加节点 O(n)"""
node = Node(item)
if self.is_empty():
self.__head = node
node.next = node
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
# 退出while循环之后cur指向尾结点
node.next = self.__head
self.__head = node
cur.next = self.__head
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = Node(item)
if self.is_empty():
self.__head = node
node.next = node
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
cur.next = node
node.next = self.__head
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.__head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
if self.is_empty():
return
pre, cur = None, self.__head
while cur.next != self.__head:
if cur.elem == item:
# 移除头结点
if cur == self.__head:
rear = self.__head
while rear.next != self.__head:
rear = rear.next
self.__head = cur.next
rear.next = self.__head
# 移除中间节点
else:
pre.next = cur.next
return # 结束。只remove第一个元素
pre = cur
cur = cur.next
# 移除尾结点
if cur.elem == item:
if cur == self.__head:
self.__head = None
else:
pre.next = self.__head # 或者 pre.next = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
if self.is_empty():
return False
else:
cur = self.__head
while cur.next != self.__head:
if cur.elem == item:
return True
cur = cur.next
return cur.elem == item</code></pre>
<pre><code>class DoubleLinkList(object):
"""双向链表"""
def __init__(self, node=None):
self.__head = node
def is_empty(self) -> bool:
"""链表是否为空 O(1)"""
return self.__head is None
def length(self) -> int:
"""链表长度 O(n)"""
count, cur = 0, self.__head
while cur is not None:
cur = cur.next # 不要写错cur = self.__head.next, self.__next不是活动指针
count += 1
return count
def transverse(self) -> '':
"""遍历所有节点 O(n)"""
cur = self.__head # 不是 self._head
while cur is not None:
print(cur.elem, end=' ')
cur = cur.next
return ''
def add(self, item) -> None:
"""头部添加节点 O(1)"""
node = DoubleNode(item)
node.next = self.__head
self.__head = node
if node.next: # 当原链表为空时
node.next.prev = node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = DoubleNode(item)
cur = self.__head
if self.is_empty():
self.__head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
node.prev = cur
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.__head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.prev = node
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
cur = self.__head
while cur is not None:
if cur.elem == item:
if cur == self.__head:
self.__head = cur.next
if self.__head: # 只有一个节点的特殊情况
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next:
cur.next.prev = cur.prev
break # 只remove第一个元素
cur = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
cur = self.__head
while cur is not None:
if cur.elem == item:
return True
cur = cur.next
return False</code></pre>
<pre><code>class DoubleCycleLinkList(object):
"""双向循环链表"""
def __init__(self, node=None):
self.__head = node
if node:
node.next = node
node.prev = node
def is_empty(self) -> bool:
"""链表是否为空 O(1)"""
return self.__head is None
def length(self) -> int:
"""链表长度 O(n)"""
if self.is_empty():
return 0
count, cur = 1, self.__head
while cur.next != self.__head:
cur = cur.next # 不要写错cur = self.__head.next, self.__next不是活动指针
count += 1
return count
def transverse(self) -> '':
"""遍历所有节点 O(n)"""
if not self.is_empty():
cur = self.__head # 不是 self._head
while cur.next != self.__head:
print(cur.elem, end=' ')
cur = cur.next
print(cur.elem, end=' ')
return ''
def add(self, item) -> None:
"""头部添加节点 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.__head = node
node.next = node
node.prev = node
else:
cur = self.__head
while cur.next != self.__head:
cur = cur.next
# 退出while循环之后cur指向尾结点,双向循环链表需要改动5个指针
node.next = self.__head # 1.node.next指向原来的头结点
node.prev = cur # 2.node.prev指向尾结点,当前cur指向的节点
cur.next.prev = node # 3.原来头结点的prev指向要插入的node
self.__head = node # 4.self.__head指向要插入的node
cur.next = node # 5.尾结点的next指向要插入的node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.__head = node
node.next = node
node.prev = node
else:
cur = self.__head
# 退出while循环之后cur指向尾结点,双向循环链表需要改动4个指针
while cur.next != self.__head:
cur = cur.next
cur.next.prev = node # 1.原来头结点的.prev指向要插入的node
cur.next = node # 2.原来尾结点.next指向要插入的node
node.prev = cur # 3.node.prev指向原来的尾节点
node.next = self.__head # 4.node.next指向头结点
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.__head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.pre = node
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
if self.is_empty():
return
cur = self.__head
while cur.next != self.__head:
if cur.elem == item:
# 移除头结点
if cur == self.__head:
cur.prev.next = cur.next
cur.next.prev = cur.prev
self.__head = cur.next
# 移除中间节点
else:
cur.prev.next = cur.next
cur.next.prev = cur.prev
return # 结束。只remove第一个元素
cur = cur.next
# 移除尾结点
if cur.elem == item:
if cur == self.__head: # 当链表只有一个节点时
self.__head = None
else:
cur.next.prev = cur.prev
cur.prev.next = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
if self.is_empty():
return False
else:
cur = self.__head
while cur.next != self.__head:
if cur.elem == item:
return True
cur = cur.next
return cur.elem == item</code></pre>
<p>在以上四种链表的实现中,可以发现有的类方法代码是重复的,具体重复的方法如下:</p>
<ul>
<li>所有的<code>is_empty()</code>方法都一样</li>
<li>双向链表的<code>length()</code>, <code>traversing()</code>, <code>search(item)</code>实现与单向链表</li>
<li>双向循环链表的<code>length()</code>, <code>traversing()</code>, <code>search(item)</code>实现与单向循环链表一样</li>
</ul>
<p>因此,我们可以使用Python中类的特性:<strong>继承和多态</strong> 来简化代码,使用了继承之后把<code>self.__head</code>改成<code>self.head</code>。</p>
<pre><code class="python">#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# __author__ = 'zhao zi yang'
class Node(object):
"""单节点"""
def __init__(self, elem):
self.elem = elem
self.next = None
class DoubleNode(Node):
"""双节点"""
def __init__(self, elem):
super(DoubleNode, self).__init__(elem)
self.prev = None
class SingleLinkList(object):
"""单链表"""
def __init__(self, node=None):
self.head = node
def is_empty(self) -> bool:
"""链表是否为空 O(1)"""
return self.head is None
def length(self) -> int:
"""链表长度 O(n)"""
count, cur = 0, self.head
while cur is not None:
cur = cur.next # 不要写错cur = self.head.next, self.__next不是活动指针
count += 1
return count
def traversing(self) -> '':
"""遍历所有节点 O(n)"""
cur = self.head # 不是 self._head
while cur is not None:
print(cur.elem, end=' ')
cur = cur.next
return ''
def add(self, item) -> None:
"""头部添加节点 O(1)"""
node = Node(item)
node.next = self.head
self.head = node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = Node(item)
cur = self.head
if self.is_empty():
self.head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
pre, cur = None, self.head
while cur is not None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
break # 只remove第一个元素
pre.next = cur.next
break
pre = cur
cur = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
cur = self.head
while cur is not None:
if cur.elem == item:
return True
cur = cur.next
return False
class SingleCycleLinkList(SingleLinkList):
"""单向循环链表"""
def __init__(self, node=None):
if node:
node.next = node
super(SingleCycleLinkList, self).__init__(node=node)
def length(self) -> int:
"""链表长度 O(n)"""
if self.is_empty():
return 0
count, cur = 1, self.head
while cur.next != self.head:
cur = cur.next # 不要写错cur = self.head.next, self.__next不是活动指针
count += 1
return count
def traversing(self) -> '':
"""遍历所有节点 O(n)"""
if not self.is_empty():
cur = self.head # 不是 self._head
while cur.next != self.head:
print(cur.elem, end=' ')
cur = cur.next
print(cur.elem, end=' ')
return ''
def add(self, item) -> None:
"""头部添加节点 O(n)"""
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
# 退出while循环之后cur指向尾结点
node.next = self.head
self.head = node
cur.next = self.head
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = Node(item)
if self.is_empty():
self.head = node
node.next = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
cur.next = node
node.next = self.head
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = Node(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
if self.is_empty():
return
pre, cur = None, self.head
while cur.next != self.head:
if cur.elem == item:
# 移除头结点
if cur == self.head:
rear = self.head
while rear.next != self.head:
rear = rear.next
self.head = cur.next
rear.next = self.head
# 移除中间节点
else:
pre.next = cur.next
return # 结束。只remove第一个元素
pre = cur
cur = cur.next
# 移除尾结点
if cur.elem == item:
if cur == self.head:
self.head = None
else:
pre.next = self.head # 或者 pre.next = cur.next
def search(self, item) -> bool:
"""查找节点是否存在 O(n)"""
if self.is_empty():
return False
else:
cur = self.head
while cur.next != self.head:
if cur.elem == item:
return True
cur = cur.next
return cur.elem == item
class DoubleLinkList(SingleLinkList):
"""双链表"""
def add(self, item) -> None:
"""头部添加节点 O(1)"""
node = DoubleNode(item)
node.next = self.head
self.head = node
if node.next: # 当原链表为空时
node.next.prev = node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = DoubleNode(item)
cur = self.head
if self.is_empty():
self.head = node
else:
while cur.next is not None:
cur = cur.next
cur.next = node
node.prev = cur
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.prev = node
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
cur = self.head
while cur is not None:
if cur.elem == item:
if cur == self.head:
self.head = cur.next
if self.head: # 只有一个节点的特殊情况
cur.next.prev = None
else:
cur.prev.next = cur.next
if cur.next:
cur.next.prev = cur.prev
break # 只remove第一个元素
cur = cur.next
class DoubleCycleLinkList(SingleCycleLinkList):
"""双向循环链表"""
def __init__(self, node=None):
if node:
node.next = node
node.prev = node
super(DoubleCycleLinkList, self).__init__(node=node)
def add(self, item) -> None:
"""头部添加节点 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.head = node
node.next = node
node.prev = node
else:
cur = self.head
while cur.next != self.head:
cur = cur.next
# 退出while循环之后cur指向尾结点,双向循环链表需要改动5个指针
node.next = self.head # 1.node.next指向原来的头结点
node.prev = cur # 2.node.prev指向尾结点,当前cur指向的节点
cur.next.prev = node # 3.原来头结点的prev指向要插入的node
self.head = node # 4.self.head指向要插入的node
cur.next = node # 5.尾结点的next指向要插入的node
def append(self, item) -> None:
"""尾部添加节点 O(n)"""
node = DoubleNode(item)
if self.is_empty():
self.head = node
node.next = node
node.prev = node
else:
cur = self.head
# 退出while循环之后cur指向尾结点,双向循环链表需要改动4个指针
while cur.next != self.head:
cur = cur.next
cur.next.prev = node # 1.原来头结点的.prev指向要插入的node
cur.next = node # 2.原来尾结点.next指向要插入的node
node.prev = cur # 3.node.prev指向原来的尾节点
node.next = self.head # 4.node.next指向头结点
def insert(self, position: int, item) -> None:
"""
节点插入到某个位置 O(n)
:param position: 0表示第1个位置
:param item:
:return: None
"""
if position <= 0:
self.add(item)
elif position >= self.length():
self.append(item)
else:
node = DoubleNode(item)
count, cur = 1, self.head
while count < position:
cur = cur.next
count += 1
node.next = cur.next
node.prev = cur
cur.next.pre = node
cur.next = node
def remove(self, item) -> None:
"""删除链表中的一个节点 O(n)"""
if self.is_empty():
return
cur = self.head
while cur.next != self.head:
if cur.elem == item:
# 移除头结点
if cur == self.head:
cur.prev.next = cur.next
cur.next.prev = cur.prev
self.head = cur.next
# 移除中间节点
else:
cur.prev.next = cur.next
cur.next.prev = cur.prev
return # 结束。只remove第一个元素
cur = cur.next
# 移除尾结点
if cur.elem == item:
if cur == self.head: # 当链表只有一个节点时
self.head = None
else:
cur.next.prev = cur.prev
cur.prev.next = cur.next
if __name__ == '__main__':
print("----single_link_list-----")
single_link_list = SingleLinkList()
single_link_list.remove('test')
print(single_link_list.is_empty(), single_link_list.length())
single_link_list.insert(-1, 'zhao')
print(single_link_list.is_empty(), single_link_list.length())
single_link_list.insert(3, 'zi')
print(single_link_list.length())
single_link_list.append('yang')
single_link_list.add("head")
single_link_list.insert(4, "tail")
print(single_link_list.traversing())
single_link_list.remove(1)
print(single_link_list.traversing())
single_link_list.remove("head")
print(single_link_list.traversing())
single_link_list.remove("tail")
print(single_link_list.traversing())
single_link_list.remove('zi')
print(single_link_list.traversing())
print("\n----single_cycle_link_list-----")
single_cycle_link_list = SingleCycleLinkList()
single_cycle_link_list.remove('test')
print(single_cycle_link_list.is_empty(), single_cycle_link_list.length())
single_cycle_link_list.insert(-1, 'zhao')
print(single_cycle_link_list.is_empty(), single_cycle_link_list.length())
single_cycle_link_list.insert(3, 'zi')
print(single_cycle_link_list.length())
single_cycle_link_list.append('yang')
single_cycle_link_list.add("head")
single_cycle_link_list.insert(4, "tail")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove(1)
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove("head")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove("tail")
print(single_cycle_link_list.traversing())
single_cycle_link_list.remove('zi')
print(single_cycle_link_list.traversing())
print("\n----double_link_list-----")
double_link_list = DoubleLinkList()
double_link_list.remove('test')
print(double_link_list.is_empty(), double_link_list.length())
double_link_list.insert(-1, 'zhao')
print(double_link_list.is_empty(), double_link_list.length())
double_link_list.insert(3, 'zi')
print(double_link_list.length())
double_link_list.append('yang')
double_link_list.add("head")
double_link_list.insert(4, "tail")
print(double_link_list.traversing())
double_link_list.remove(1)
print(double_link_list.traversing())
double_link_list.remove("head")
print(double_link_list.traversing())
double_link_list.remove("tail")
print(double_link_list.traversing())
double_link_list.remove('zi')
print(double_link_list.traversing())
print("\n----double_cycle_link_list-----")
double_cycle_link_list = DoubleCycleLinkList()
double_cycle_link_list.remove('test')
print(double_cycle_link_list.is_empty(), double_cycle_link_list.length())
double_cycle_link_list.insert(-1, 'zhao')
print(double_cycle_link_list.is_empty(), double_cycle_link_list.length())
double_cycle_link_list.insert(3, 'zi')
print(double_cycle_link_list.length())
double_cycle_link_list.append('yang')
double_cycle_link_list.add("head")
double_cycle_link_list.insert(4, "tail")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove(1)
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove("head")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove("tail")
print(double_cycle_link_list.traversing())
double_cycle_link_list.remove('zi')
print(double_cycle_link_list.traversing())</code></pre>
<p>结果运行如下:</p>
<pre><code>----single_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----single_cycle_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----double_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang
----double_cycle_link_list-----
True 0
False 1
2
head zhao zi yang tail
head zhao zi yang tail
zhao zi yang tail
zhao zi yang
zhao yang </code></pre>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
调研的六个开源DevOps平台
https://segmentfault.com/a/1190000018477767
2019-03-12T17:37:22+08:00
2019-03-12T17:37:22+08:00
寸土币争
https://segmentfault.com/u/liaogx
1
<table>
<thead><tr>
<th>项目名称</th>
<th>开发语言</th>
<th>活跃度</th>
<th>文档说明</th>
<th>功能描述</th>
</tr></thead>
<tbody>
<tr>
<td><a href="https://link.segmentfault.com/?enc=GFo36YXDPnIcbN3Y51TMHw%3D%3D.KnHx%2B1n50zDatB2TS5bnHJSD%2FqEpJrq49SMpn3wErl5blxplTey7Lqb9%2Fx5qqhtC" rel="nofollow">Walle 瓦力</a></td>
<td>Python</td>
<td>活跃、更新及时</td>
<td>文档较完善,有<a href="https://link.segmentfault.com/?enc=HD01vurGkKjsUjvUeUq%2F8Q%3D%3D.MpfRzYY07b1Fg8rS7Ypa8r7TptCdEmEgMmJzPhRbFqA%3D" rel="nofollow">官网</a>
</td>
<td>DevOps代码部署平台:空间管理、服务器管理、项目管理、环境管理、用户管理、部署管理</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=n%2B%2BSQm29qRHkSKdGQ3YRoQ%3D%3D.IzKhRmv1lqxdWPlJiHysQup8gjwo1a5CzxRQKYEwgUqUNzkYCifsGlfwl5LPVS3U" rel="nofollow">gaia</a></td>
<td>Golang</td>
<td>活跃、更新及时</td>
<td>文档较完善,有<a href="https://link.segmentfault.com/?enc=bgVPntaR1WtHKnkp6gTJdQ%3D%3D.6uGGQy7%2B42I5cwsVcOnm7NOusrfSHVXceFhqKCdJmpw%3D" rel="nofollow">官网</a>
</td>
<td>CI/CD:创建主流开发语言的Pipline,包括Golang、Python、Java、C++、Ruby</td>
</tr>
<tr>
<td>蓝鲸智云配置平台(<a href="https://link.segmentfault.com/?enc=eot6EBJwMyKKbxkxpikicw%3D%3D.vk4WbOLo%2FVkqCLW9D8omj5DPkC42m5xPxOYx8DU20gbWo1RuGkDIgeXAfzknm2PU" rel="nofollow">BlueKing CMDB</a>)</td>
<td>Golang</td>
<td>活跃、更新及时</td>
<td>文档很完善,有<a href="https://link.segmentfault.com/?enc=9f17kjTxLnskGFJPSem%2BLw%3D%3D.f15M2sPKIBX4HDIbjeJ3zyXCGAXdOrzL1S5wrPfd%2B94%3D" rel="nofollow">官网</a>,有视频教程</td>
<td>云CMDB:拓扑化的主机管理、组织架构管理、模型管理、进程管理、事件注册与推送、通用权限管理、操作审计</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=%2BMUoZ3VSQZ9VADa4F2MX3Q%3D%3D.4e%2B9rq8%2BlViSe6%2FOny1uEOOfLXBBprGNoOtrvevclkM%3D" rel="nofollow">cds</a></td>
<td>Golang</td>
<td>活跃、更新及时</td>
<td>有英文文档和<a>官网</a>
</td>
<td>CD & DevOps自动化:Self-Service、Horizontal Scalability、High Availability、Pipeline Reutilisability、REST API、Customizable</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=ziZhZ%2FuKzMiHw2YO24PnyQ%3D%3D.ek5eT%2FqRflzKMgpYrvLW6LyqNJ9V%2BV%2B1LnMwOSpl6WvzkfzIW1R1%2BvKoTHvZ7AIG" rel="nofollow">cloudunit</a></td>
<td>Java</td>
<td>不活跃,基本停止更新</td>
<td>有部分安装和使用文档</td>
<td>DevOps平台:CI/CD with Gitlab or Jenkins2、EKL Stack for monitoring users containers、Prometheus for monitoring platform、Sonar to analyse and reports in the future、Mattermost chat</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=ID3OxjEu3oQ7pcxy1sWzeQ%3D%3D.Fvb2anauLZAsf%2FiFBonfR9jHDO2t%2FjJv3lOFiWP%2BVCwMBiiIpOD5yO2Ad%2Bo2Mi4I" rel="nofollow">Hygieia</a></td>
<td>Java</td>
<td>活跃、更新及时</td>
<td>
<a href="https://link.segmentfault.com/?enc=mNEboUUl6kNV9f1XrQsqjQ%3D%3D.Nelio8K0tLFZXCB%2FPH%2F2W6oYkZVajFCPlfsIOvYzE%2FiwATXk9YCiQ0IL7REKRmlqarsyc9w4aiKjd3FOg%2FdNeg%3D%3D" rel="nofollow">文档</a>较完善,有<a href="https://link.segmentfault.com/?enc=eCijRbxpmzcIgnpuxFTMBA%3D%3D.wlTFg6efGKjnFtJBty8DFfTY8b%2FDJxcxZ2wQiHogbqjn3qOpcJZBFrTKhtPSAcao" rel="nofollow">视频</a>
</td>
<td>一站式DevOps平台:CI/CD、交付管道、数据可视化、看板</td>
</tr>
</tbody>
</table>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python中的描述符
https://segmentfault.com/a/1190000017368787
2018-12-13T18:10:06+08:00
2018-12-13T18:10:06+08:00
寸土币争
https://segmentfault.com/u/liaogx
0
<p>解答三个问题,描述是什么?如何实现?使用场景?</p>
<h3>一、什么是描述符</h3>
<p>描述符就是一个具有绑定行为的对象属性,其属性访问将由描述符协议中的方法覆盖。这些方法为 <code>__get__</code>、<code>__set__</code> 和 <code>__delete__</code>。如果这些方法中的任何一个针对某个对象定义,那么它就被认为是一个描述符。</p>
<p><code>__get__</code> 用于访问属性。它返回属性的值,或者在所请求的属性不存在的情况下出现 <code>AttributeError</code> 异常</p>
<p><code>__set__</code> 将在属性分配操作中调用。不会返回任何内容</p>
<p><code>__delete__</code> 控制删除操作。不会返回内容</p>
<h3>二、描述符的实现方式</h3>
<h4>2.1 基于类创建</h4>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
class Descriptor(object):
""""""
def __init__(self):
self._name = ''
def __get__(self, instance, owner):
print("__get__")
return self._name
def __set__(self, instance, value):
print("__set__")
self._name = value
def __delete__(self, instance):
print("__delete__")
del self._name
class Person(object):
name = Descriptor()
p = Person()
print(p.name)
p.name = 'liao gao xiang'
del p.name
# print(p.name)</code></pre>
<h4>2.2 使用propety()函数</h4>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
class Person(object):
def __init__(self):
self._name = ''
def fget(self):
print("Getting: %s" % self._name)
return self._name
def fset(self, value):
print("Setting: %s" % value)
self._name = value.title()
def fdel(self):
print("Deleting: %s" % self._name)
del self._name
name = property(fget, fset, fdel, "I'm the property.")
p = Person()
print(p.name)
p.name = 'liao gao xiang'
del p.name
# print(p.name)</code></pre>
<h4>2.3 使用@property装饰器</h4>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
class Person(object):
""""""
def __init__(self, name):
self._name = name
@property
def name(self):
print("get_name")
return self._name
@name.setter
def name(self, value):
print("set_name")
self._name = value
@name.deleter
def name(self):
print("del_name")
del self._name
p = Person()
print(p.name)
p.name = 'liao gao xiang'
del p.name
# print(p.name)</code></pre>
<h3>三、描述符的使用场景</h3>
<ol>
<li>通过结合使用描述符,可以实现优雅的编程,允许创建 <em>Setters</em> 和 <em>Getters</em> 以及只读属性</li>
<li>根据值或类型请求进行属性验证</li>
<li>大量用于各种框架中,比如Django的models</li>
</ol>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python生成器实现数据处理管道
https://segmentfault.com/a/1190000017211331
2018-11-30T17:56:57+08:00
2018-11-30T17:56:57+08:00
寸土币争
https://segmentfault.com/u/liaogx
0
<p><strong>假设现在有如下业务场景</strong></p>
<p>某生产系统的日志文件如下,并且在持续增加...</p>
<pre><code class="bash">[ncms@UPZZGAP02 logs]$ pwd
/home/ncms/ncms/logs
[ncms@UPZZGAP02 logs]$ ll
总用量 797020
-rw-rw-r-- 1 ncms ncms 495465795 11月 30 17:10 ansible.log
-rw-rw-r-- 1 ncms ncms 2251937 11月 30 17:10 celery_beat.log
-rw-rw-r-- 1 ncms ncms 16003 11月 15 10:26 celery_flower.log
-rw-rw-r-- 1 ncms ncms 7042114 11月 30 17:10 celery_worker.log
-rw-r--r-- 1 ncms ncms 24665873 11月 30 17:10 db_error.log
-rw-r--r-- 1 ncms ncms 52428571 11月 28 18:46 db_error.log.1
-rw-r--r-- 1 ncms ncms 52428691 11月 24 06:43 db_error.log.2
-rw-r--r-- 1 ncms ncms 22410652 11月 19 15:16 db_error.log.3
-rw-r--r-- 1 ncms ncms 28064985 11月 30 17:10 db_info.log
-rw-r--r-- 1 ncms ncms 52426630 11月 28 13:29 db_info.log.1
-rw-r--r-- 1 ncms ncms 52427357 11月 24 03:48 db_info.log.2
-rw-r--r-- 1 ncms ncms 24276767 11月 19 15:16 db_info.log.3
-rw-rw-r-- 1 ncms ncms 42490 11月 30 13:06 ncms_access.log
-rw-rw-r-- 1 ncms ncms 24072 10月 30 15:33 ncms_error.log
-rw-rw-r-- 1 ncms ncms 1350318 11月 30 16:38 nginx_access.log
-rw-rw-r-- 1 ncms ncms 1685 11月 7 18:15 nginx_error.log
-rw-rw-r-- 1 ncms ncms 24001 11月 15 10:27 supervisord.log
-rw-rw-r-- 1 ncms ncms 645742 11月 30 16:38 uwsgi.log
[ncms@UPZZGAP02 logs]$ du -sh *
473M ansible.log
2.2M celery_beat.log
16K celery_flower.log
6.8M celery_worker.log
24M db_error.log
51M db_error.log.1
51M db_error.log.2
22M db_error.log.3
27M db_info.log
51M db_info.log.1
51M db_info.log.2
24M db_info.log.3
44K ncms_access.log
24K ncms_error.log
1.3M nginx_access.log
4.0K nginx_error.log
24K supervisord.log
632K uwsgi.log
[ncms@UPZZGAP02 logs]$</code></pre>
<p>其中有应用、数据库、Celery、Nginx、uwsgi、supervisord、Ansible的日志,Ansible.log有473M,未来很定会更大。现在需要使用某些关键字对日志进行查找分析,应该如何做?</p>
<p>最简单粗暴的方式就是使用<code>grep</code>之类的命令,递归查找所有的.log文件,但这样会耗费大量内存,影响机器性能。</p>
<p>可以考虑使用数据管道 (类似 Unix 管道) 的方式迭代处理数据。使用Python生成器函数是一个实现管道机制</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
import os
import fnmatch
import gzip
import bz2
import re
# 问题,你想以数据管道 (类似 Unix 管道) 的方式迭代处理数据。比如,你有个大量的数据
# 需要处理,但是不能将它们一次性放入内存中。可以使用生成器实现数据处理管道
""" 文件格式如下
foo/
access-log-012007.gz
access-log-022007.gz
access-log-032007.gz
...
access-log-012008
bar/
access-log-092007.bz2
...
access-log-022008
"""
def gen_find(filepat, top):
"""
查找符合Shell正则匹配的目录树下的所有文件名
:param filepat: shell正则
:param top: 目录路径
:return: 文件绝对路径生成器
"""
for path, _, filenames in os.walk(top):
for file in fnmatch.filter(filenames, filepat):
yield os.path.join(path, file)
def gen_opener(filenames):
"""
每打开一个文件生成就生成一个文件对象,调用下一个迭代前关闭文件
:param filenames: 多个文件绝对路径组成的可迭代对象
:return: 文件对象生成器
"""
for filename in filenames:
if filename.endswith('.gz'):
f = gzip.open(filename, 'r', encoding='utf-8')
elif filename.endswith('.bz2'):
f = bz2.open(filename, 'r', encoding='utf-8')
else:
f = open(filename, 'r', encoding='utf-8')
yield f
f.close()
def gen_concatenate(iterators):
"""
将输入序列拼接成一个很长的行序列。
:param iterators:
:return: 返回生成器所产生的所有值
"""
for it in iterators:
yield from it
def gen_grep(pattern, lines):
"""
使用正则匹配行
:param pattern: 正则匹配
:param lines: 多行
:return: 结果生成器
"""
pat = re.compile(pattern)
for n, line in enumerate(lines, start=1):
if pat.search(line):
yield n, line
if __name__ == "__main__":
filenames = gen_find('*.log', '/home/ncms/ncms/logs')
files = gen_opener(filenames)
lines = gen_concatenate(files)
user_action = gen_grep('(?i)liaogaoxiang_kd', lines)
for n, line in user_action:
print(line)</code></pre>
<p>查询包含用户 <em>liaogaoxiang_kd</em> 的所有记录,数据结果如下:</p>
<pre><code class="bash">[views:post]:2018-11-07 18:13:09.841490 -users- liaogaoxiang_kd登录成功!
[views:get]:2018-11-07 18:16:04.681519 -users- liaogaoxiang_kd访问了用户信息列表
[views:post]:2018-11-07 18:16:23.866700 -users- liaogaoxiang_kd编辑了用户的信息
[views:get]:2018-11-07 18:16:23.878949 -users- liaogaoxiang_kd访问了用户信息列表
[views:get]:2018-11-07 18:16:25.641090 -users- liaogaoxiang_kd访问了用户信息列表
[views:post]:2018-11-07 18:16:42.671377 -users- liaogaoxiang_kd编辑了用户的信息
[views:get]:2018-11-07 18:16:42.719873 -users- liaogaoxiang_kd访问了用户信息列表
[views:post]:2018-11-08 11:17:42.627693 -users- liaogaoxiang_kd登录成功!</code></pre>
<p>如需查询其它错误信息,只需替换<code>gen_grep('(?i)liaogaoxiang_kd', lines)</code>中的关键字即可!以管道方式处理数据可以用来解决各类其他问题,包括解析,读取实时数据,定时 轮询等。 </p>
<p>为了理解上述代码,重点是要明白 <code>yield</code> 语句作为数据的生产者而 for 循环语句 作为数据的消费者。当这些生成器被连在一起后,每个 yield 会将一个单独的数据元 素传递给迭代处理管道的下一阶段。这种方式一个非常好的特点是每个生成器函数很小并且都是独立的。这样的话就 很容易编写和维护。很多时候,这些函数如果比较通用的话可以在其他场景重复使用。并且最终将这些组件组合起来的代码看上去非常简单,也很容易理解。</p>
<p>使用这种方式的内存效率很高。上述代码即便是在一个超大型文件目录中 也能工作的很好。事实上,由于使用了迭代方式处理,代码运行过程中只需要很小很小的内存。 在调用 gen_concatenate() 函数的时候你可能会有些不太明白。这个函数的目的是将输入序列拼接成一个很长的行序列。 itertools.chain() 函数同样有类似的功能, 但是它需要将所有可迭代对象最为参数传入。在上面这个例子中,你可能会写类似这样 的语句 lines = itertools.chain(*files) ,这将导致 gen_opener() 生成器被提前全部消费掉。但由于 gen_opener() 生成器每次生成一个打开过的文件,等到下一个迭 代步骤时文件就关闭了,因此 chain() 在这里不能这样使用。上面的方案可以避免这 种情况。</p>
<p>gen_concatenate() 函数中出现过 yield from 语句,它将 yield 操作代理到父 生成器上去。语句 yield from it 简单的返回生成器 it 所产生的所有值。</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python中collections模块的使用
https://segmentfault.com/a/1190000017209726
2018-11-30T16:28:48+08:00
2018-11-30T16:28:48+08:00
寸土币争
https://segmentfault.com/u/liaogx
3
<blockquote>本文将详细讲解collections模块中的所有类,和每个类中的方法,从源码和性能的角度剖析。</blockquote>
<p>一个模块主要用来干嘛,有哪些类可以使用,看<code>__init__.py</code>就知道</p>
<pre><code class="python">'''This module implements specialized container datatypes providing
alternatives to Python's general purpose built-in containers, dict,
list, set, and tuple.
* namedtuple factory function for creating tuple subclasses with named fields
* deque list-like container with fast appends and pops on either end
* ChainMap dict-like class for creating a single view of multiple mappings
* Counter dict subclass for counting hashable objects
* OrderedDict dict subclass that remembers the order entries were added
* defaultdict dict subclass that calls a factory function to supply missing values
* UserDict wrapper around dictionary objects for easier dict subclassing
* UserList wrapper around list objects for easier list subclassing
* UserString wrapper around string objects for easier string subclassing
'''
__all__ = ['deque', 'defaultdict', 'namedtuple', 'UserDict', 'UserList',
'UserString', 'Counter', 'OrderedDict', 'ChainMap']</code></pre>
<p>collections模块实现一些特定的数据类型,可以替代Python中常用的内置数据类型如dict, list, set, tuple,简单说就是对基本数据类型做了更上一层的处理。</p>
<h2>一、deque</h2>
<blockquote>用途:双端队列,头部和尾部都能以O(1)时间复杂度插入和删除元素。类似于列表的容器</blockquote>
<p>所谓<code>双端队列</code>,就是两端都能操作,与Python内置的list区别在于:<strong>头部插入与删除的时间复杂度为O(1)</strong>,来个栗子感受一下:</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
"""
保留最后n个元素
"""
from collections import deque
def search(file, pattern, history=5):
previous_lines = deque(maxlen=history)
for l in file:
if pattern in l:
yield l, previous_lines # 使用yield表达式的生成器函数,将搜索过程的代码和搜索结果的代码解耦
previous_lines.append(l)
with open(b'file.txt', mode='r', encoding='utf-8') as f:
for line, prevlines in search(f, 'Python', 5):
for pline in prevlines:
print(pline, end='')
print(line, end='')
d = deque()
d.append(1)
d.append("2")
print(len(d))
print(d[0], d[1])
d.extendleft([0])
print(d)
d.extend([6, 7, 8])
print(d)
d2 = deque('12345')
print(len(d2))
d2.popleft()
print(d2)
d2.pop()
print(d2)
# 在队列两端插入或删除元素时间复杂度都是 O(1) ,区别于列表,在列表的开头插入或删除元素的时间复杂度为 O(N)
d3 = deque(maxlen=2)
d3.append(1)
d3.append(2)
print(d3)
d3.append(3)
print(d3)</code></pre>
<p>输出结果如下</p>
<pre><code class="python">人生苦短
我用Python
2
1 2
deque([0, 1, '2'])
deque([0, 1, '2', 6, 7, 8])
5
deque(['2', '3', '4', '5'])
deque(['2', '3', '4'])
deque([1, 2], maxlen=2)
deque([2, 3], maxlen=2)</code></pre>
<p>因此,如果你遇到经常操作列表头的场景,使用deque最好。deque类的所有方法,自行操作一遍就知道了。</p>
<pre><code class="python">class deque(object):
"""
deque([iterable[, maxlen]]) --> deque object
A list-like sequence optimized for data accesses near its endpoints.
"""
def append(self, *args, **kwargs): # real signature unknown
""" Add an element to the right side of the deque. """
pass
def appendleft(self, *args, **kwargs): # real signature unknown
""" Add an element to the left side of the deque. """
pass
def clear(self, *args, **kwargs): # real signature unknown
""" Remove all elements from the deque. """
pass
def copy(self, *args, **kwargs): # real signature unknown
""" Return a shallow copy of a deque. """
pass
def count(self, value): # real signature unknown; restored from __doc__
""" D.count(value) -> integer -- return number of occurrences of value """
return 0
def extend(self, *args, **kwargs): # real signature unknown
""" Extend the right side of the deque with elements from the iterable """
pass
def extendleft(self, *args, **kwargs): # real signature unknown
""" Extend the left side of the deque with elements from the iterable """
pass
def index(self, value, start=None, stop=None): # real signature unknown; restored from __doc__
"""
D.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
"""
return 0
def insert(self, index, p_object): # real signature unknown; restored from __doc__
""" D.insert(index, object) -- insert object before index """
pass
def pop(self, *args, **kwargs): # real signature unknown
""" Remove and return the rightmost element. """
pass
def popleft(self, *args, **kwargs): # real signature unknown
""" Remove and return the leftmost element. """
pass
def remove(self, value): # real signature unknown; restored from __doc__
""" D.remove(value) -- remove first occurrence of value. """
pass
def reverse(self): # real signature unknown; restored from __doc__
""" D.reverse() -- reverse *IN PLACE* """
pass
def rotate(self, *args, **kwargs): # real signature unknown
""" Rotate the deque n steps to the right (default n=1). If n is negative, rotates left. """
pass</code></pre>
<p>这里提示一下,有些函数对队列进行操作,但返回值是None,比如<code>reverse()</code>反转队列,<code>rotate(1)</code>将队列中元素向右移1位,尾部的元素移到头部。</p>
<h2>二、defaultdict</h2>
<blockquote>用途:带有默认值的字典。父类为Python内置的dict</blockquote>
<p>字典带默认值有啥好处?举个栗子,一般来讲,创建一个多值映射字典是很简单的。但是,如果你选择自己实现的话, 那么对于值的初始化可能会有点麻烦,你可能会像下面这样来实现:</p>
<pre><code class="python">d = {}
for key, value in pairs:
if key not in d:
d[key] = []
d[key].append(value)</code></pre>
<p>如果使用 defaultdict 的话代码就更加简洁了:</p>
<pre><code class="python">d = defaultdict(list)
for key, value in pairs:
d[key].append(value)</code></pre>
<p>defaultdict 的一个特征是它会自动初始化每个 key 刚开始对应的值,所以你只需要 关注添加元素操作了。比如:</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
# 字典中的键映射多个值
from collections import defaultdict
d = defaultdict(list)
print(d)
d['a'].append([1, 2, 3])
d['b'].append(2)
d['c'].append(3)
print(d)
d = defaultdict(set)
print(d)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)
print(d)</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">defaultdict(<class 'list'>, {})
defaultdict(<class 'list'>, {'a': [[1, 2, 3]], 'b': [2], 'c': [3]})
defaultdict(<class 'set'>, {})
defaultdict(<class 'set'>, {'a': {1, 2}, 'b': {4}})</code></pre>
<h2>三、namedtuple()</h2>
<blockquote>用途:创建命名字段的元组。工厂函数</blockquote>
<p>namedtuple主要用来产生可以使用名称来访问元素的数据对象,通常用来增强代码的可读性, 在访问一些tuple类型的数据时尤其好用。</p>
<p>比如我们用户拥有一个这样的数据结构,每一个对象是拥有三个元素的tuple。使用namedtuple方法就可以方便的通过tuple来生成可读性更高也更好用的数据结构。</p>
<pre><code class="python">from collections import namedtuple
websites = [
('Sohu', 'http://www.sohu.com/', u'张朝阳'),
('Sina', 'http://www.sina.com.cn/', u'王志东'),
('163', 'http://www.163.com/', u'丁磊')
]
Website = namedtuple('Website', ['name', 'url', 'founder'])
for website in websites:
website = Website._make(website)
print website
# 输出结果:
Website(name='Sohu', url='http://www.sohu.com/', founder=u'\u5f20\u671d\u9633')
Website(name='Sina', url='http://www.sina.com.cn/', founder=u'\u738b\u5fd7\u4e1c')
Website(name='163', url='http://www.163.com/', founder=u'\u4e01\u78ca')</code></pre>
<p>注意,namedtuple是函数,不是类。</p>
<h2>四、Counter</h2>
<blockquote>用途:统计可哈希的对象。父类为Python内置的dict</blockquote>
<p>寻找序列中出现次数最多的元素。假设你有一个单词列表并且想找出哪个单词出现频率最高:</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
from collections import Counter
words = [
'look', 'into', 'my', 'eyes', 'look', 'into', 'my', 'eyes',
'the', 'eyes', 'the', 'eyes', 'the', 'eyes', 'not', 'around', 'the',
'eyes', "don't", 'look', 'around', 'the', 'eyes', 'look', 'into',
'my', 'eyes', "you're", 'under'
]
word_counts = Counter(words)
# 出现频率最高的三个单词
top_three = word_counts.most_common(3)
print(top_three)
# Outputs [('eyes', 8), ('the', 5), ('look', 4)]
print(word_counts['eyes'])
morewords = ['why', 'are', 'you', 'not', 'looking', 'in', 'my', 'eyes']
# 如果你想手动增加计数,可以简单的用加法:
for word in morewords:
print(word)
word_counts[word] += 1
print(word_counts['eyes'])</code></pre>
<p>结果如下:</p>
<pre><code class="python">[('eyes', 8), ('the', 5), ('look', 4)]
8
why
are
you
not
looking
in
my
eyes
9</code></pre>
<p>因为Counter继承自dict,所有dict有的方法它都有(defaultdict和OrderedDict也是的),Counter自己实现或重写了6个方法:</p>
<ul>
<li>
<code>most_common(self, n=None)</code>,</li>
<li><code>elements(self)</code></li>
<li><code>fromkeys(cls, iterable, v=None)</code></li>
<li><code>update(*args, **kwds)</code></li>
<li><code>subtract(*args, **kwds)</code></li>
<li><code>copy(self)</code></li>
</ul>
<h2>五、OrderedDict</h2>
<blockquote>用途:排序的字段。父类为Python内置的dict</blockquote>
<p>OrderedDict在迭代操作的时候会保持元素被插入时的顺序,OrderedDict内部维护着一个根据键插入顺序排序的<strong>双向链表</strong>。每次当一个新的元素插入进来的时候,它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。</p>
<p>需要注意的是,一个OrderedDict的大小是一个普通字典的两倍,因为它内部维护着另外一个链表。 所以如果你要构建一个需要大量OrderedDict 实例的数据结构的时候(比如读取100,000行CSV数据到一个 OrderedDict 列表中去),那么你就得仔细权衡一下是否使用 OrderedDict带来的好处要大过额外内存消耗的影响。</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
from collections import OrderedDict
d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['grok'] = 4
# d['bar'] = 22 #对于一个已经存在的键,重复赋值不会改变键的顺序
for key in d:
print(key, d[key])
print(d)
import json
print(json.dumps(d))</code></pre>
<p>结果如下:</p>
<pre><code class="python">foo 1
bar 2
spam 3
grok 4
OrderedDict([('foo', 1), ('bar', 2), ('spam', 3), ('grok', 4)])
{"foo": 1, "bar": 2, "spam": 3, "grok": 4}</code></pre>
<p>OrderDict实现或重写了如下方法。都是干嘛的?这个留给大家当课后作业了^_^</p>
<ul>
<li><code>clear(self)</code></li>
<li><code>popitem(self, last=True)</code></li>
<li><code>move_to_end(self, key, last=True)</code></li>
<li><code>keys(self)</code></li>
<li><code>items(self)</code></li>
<li><code>values(self)</code></li>
<li><code>pop(self, key, default=__marker)</code></li>
<li><code>setdefault(self, key, default=None)</code></li>
<li><code>copy(self)</code></li>
<li><code>fromkeys(cls, iterable, value=None)</code></li>
</ul>
<h2>六、ChainMap</h2>
<blockquote>用途:创建多个可迭代对象的集合。类字典类型</blockquote>
<p>很简单,如下:</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
from collections import ChainMap
from itertools import chain
# 不同集合上元素的迭代
a = [1, 2, 3, 4]
b = ('x', 'y', 'z')
c = {1, 'a'}
# 方法一,使用chain
for i in chain(a, b, c):
print(i)
print('--------------')
# 方法二,使用chainmap
for j in ChainMap(a, b, c):
print(j)
# 这两种均为节省内存,效率更高的迭代方式</code></pre>
<p>一个 ChainMap 接受多个字典并将它们在逻辑上变为一个字典。然后,这些字典并不是真的合并在一起了,ChainMap 类只是在内部创建了一个容纳这些字典的列表并重新定义了一些常见的字典操作来遍历这个列表。大部分字典操作都是可以正常使用的,比如:</p>
<pre><code class="python">#!/usr/bin/env python
# -*- coding:utf-8 -*-
# __author__ = 'liao gao xiang'
# 合并多个字典和映射
a = {'x': 1, 'z': 3}
b = {'y': 2, 'z': 4}
# 现在假设你必须在两个字典中执行查找操作
# (比如先从 a 中找,如果找不到再在 b 中找)。
# 一个非常简单的解决方案就是使用collections模块中的ChainMap类
from collections import ChainMap
c = ChainMap(a, b)
print(c)
a['x'] = 11 # 使用ChainMap时,原字典做了更新,这种更新会合并到新的字典中去
print(c) # 按顺序合并两个字典
print(c['x'])
print(c['y'])
print(c['z'])
# 对于字典的更新或删除操作影响的总是列中的第一个字典。
c['z'] = 10
c['w'] = 40
del c['x']
print(a)
# del c['y']将出现报错
# ChainMap对于编程语言中的作用范围变量(比如globals,locals等)
# 是非常有用的。事实上,有一些方法可以使它变得简单:
values = ChainMap() # 默认会创建一个空字典
print('\t', values)
values['x'] = 1
values = values.new_child() # 添加一个空字典
values['x'] = 2
values = values.new_child()
values['x'] = 30
# values = values.new_child()
print(values, values['x']) # values['x']输出最后一次添加的值
values = values.parents # 删除上一次添加的字典
print(values['x'])
values = values.parents
print(values)
a = {'x': 1, 'y': 2}
b = {'y': 2, 'z': 3}
merge = dict(b)
merge.update(a)
print(merge['x'], merge['y'], merge['z'])
a['x'] = 11
print(merge['x'])</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">ChainMap({'x': 1, 'z': 3}, {'y': 2, 'z': 4})
ChainMap({'x': 11, 'z': 3}, {'y': 2, 'z': 4})
11
2
3
{'z': 10, 'w': 40}
ChainMap({})
ChainMap({'x': 30}, {'x': 2}, {'x': 1}) 30
2
ChainMap({'x': 1})
1 2 3
1</code></pre>
<p>作为ChainMap的替代,你可能会考虑使用 update() 方法将两个字典合并。这样也能行得通,但是它需要你创建一个完全不同的字典对象(或者是破坏现有字典结构)。同时,如果原字典做了更新,这种改变不会反应到新的合并字典中去。</p>
<p>ChainMap实现或重写了如下方法:</p>
<ul>
<li><code>get(self, key, default=None)</code></li>
<li><code>fromkeys(cls, iterable, *args)</code></li>
<li><code>copy(self)</code></li>
<li><code>new_child(self, m=None)</code></li>
<li><code> parents(self)</code></li>
<li><code>popitem(self)</code></li>
<li><code>pop(self, key, *args)</code></li>
<li><code>clear(self)</code></li>
</ul>
<h2>七、UserDict、UserList、UserString</h2>
<p>这三个类是分别对 dict、list、str 三种数据类型的包装,其主要是为方便用户实现自己的数据类型。在 Python2 之前,这三个类分别位于 UserDict、UserList、UserString 三个模块中,需要用类似于 <code>from UserDict import UserDict</code> 的方式导入。在 Python3 之后则被挪到了 collections 模块中。这三个类都是基类,如果用户要扩展这三种类型,只需继承这三个类即可。</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python中fnmatch模块的使用
https://segmentfault.com/a/1190000017198824
2018-11-29T23:12:06+08:00
2018-11-29T23:12:06+08:00
寸土币争
https://segmentfault.com/u/liaogx
3
<p>fnmatch()函数匹配能力介于简单的字符串方法和强大的正则表达式之间,如果在数据处理操作中只需要简单的通配符就能完成的时候,这通常是一个比较合理的方案。此模块的主要作用是文件名称的匹配,并且匹配的模式使用的Unix shell风格。源码很简单:</p>
<pre><code class="python">"""Filename matching with shell patterns.
fnmatch(FILENAME, PATTERN) matches according to the local convention.
fnmatchcase(FILENAME, PATTERN) always takes case in account.
The functions operate by translating the pattern into a regular
expression. They cache the compiled regular expressions for speed.
The function translate(PATTERN) returns a regular expression
corresponding to PATTERN. (It does not compile it.)
"""
import os
import posixpath
import re
import functools
__all__ = ["filter", "fnmatch", "fnmatchcase", "translate"]
def fnmatch(name, pat):
"""Test whether FILENAME matches PATTERN.
Patterns are Unix shell style:
* matches everything
? matches any single character
[seq] matches any character in seq
[!seq] matches any char not in seq
An initial period in FILENAME is not special.
Both FILENAME and PATTERN are first case-normalized
if the operating system requires it.
If you don't want this, use fnmatchcase(FILENAME, PATTERN).
"""
name = os.path.normcase(name)
pat = os.path.normcase(pat)
return fnmatchcase(name, pat)
@functools.lru_cache(maxsize=256, typed=True)
def _compile_pattern(pat):
if isinstance(pat, bytes):
pat_str = str(pat, 'ISO-8859-1')
res_str = translate(pat_str)
res = bytes(res_str, 'ISO-8859-1')
else:
res = translate(pat)
return re.compile(res).match
def filter(names, pat):
"""Return the subset of the list NAMES that match PAT."""
result = []
pat = os.path.normcase(pat)
match = _compile_pattern(pat)
if os.path is posixpath:
# normcase on posix is NOP. Optimize it away from the loop.
for name in names:
if match(name):
result.append(name)
else:
for name in names:
if match(os.path.normcase(name)):
result.append(name)
return result
def fnmatchcase(name, pat):
"""Test whether FILENAME matches PATTERN, including case.
This is a version of fnmatch() which doesn't case-normalize
its arguments.
"""
match = _compile_pattern(pat)
return match(name) is not None
def translate(pat):
"""Translate a shell PATTERN to a regular expression.
There is no way to quote meta-characters.
"""
i, n = 0, len(pat)
res = ''
while i < n:
c = pat[i]
i = i+1
if c == '*':
res = res + '.*'
elif c == '?':
res = res + '.'
elif c == '[':
j = i
if j < n and pat[j] == '!':
j = j+1
if j < n and pat[j] == ']':
j = j+1
while j < n and pat[j] != ']':
j = j+1
if j >= n:
res = res + '\\['
else:
stuff = pat[i:j].replace('\\','\\\\')
i = j+1
if stuff[0] == '!':
stuff = '^' + stuff[1:]
elif stuff[0] == '^':
stuff = '\\' + stuff
res = '%s[%s]' % (res, stuff)
else:
res = res + re.escape(c)
return r'(?s:%s)\Z' % res</code></pre>
<p><code>fnmatch</code>的中的5个函数<code>["filter", "fnmatch", "fnmatchcase", "translate"]</code></p>
<ul><li>filter 返回列表形式的结果</li></ul>
<pre><code class="python">def gen_find(filepat, top):
"""
查找符合Shell正则匹配的目录树下的所有文件名
:param filepat: shell正则
:param top: 目录路径
:return: 文件绝对路径生成器
"""
for path, _, filenames in os.walk(top):
for file in fnmatch.filter(filenames, filepat):
yield os.path.join(path, file)</code></pre>
<ul><li>fnmatch</li></ul>
<pre><code class="python"># 列出元组中所有的python文件
pyfiles = [py for py in ('restart.py', 'index.php', 'file.txt') if fnmatch(py, '*.py')]
# 字符串的 startswith() 和 endswith() 方法对于过滤一个目录的内容也是很有用的</code></pre>
<ul><li>fnmatchcase 区分大小写的文件匹配</li></ul>
<pre><code class="python"># 这两个函数通常会被忽略的一个特性是在处理非文件名的字符串时候它们也是很有用的。 比如,假设你有一个街道地址的列表数据
address = [
'5412 N CLARK ST',
'1060 W ADDISON ST',
'1039 W GRANVILLE AVE',
'2122 N CLARK ST',
'4802 N BROADWAY',
]
print([addr for addr in address if fnmatchcase(addr, '* ST')])</code></pre>
<ul><li>translate 这个似乎很少有人用到,前面说了fnmatch是Unix shell匹配风格,可以使用translate将其转换为正则表达式,举个栗子</li></ul>
<pre><code class="python">shell_match = 'Celery_?*.py'
print(translate(shell_match))
# 输出结果:(?s:Celery_..*\.py)\Z</code></pre>
<p><code>Celery_..*\.py</code>就是正则表达式的写法。</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python操作Redis大全
https://segmentfault.com/a/1190000016696863
2018-10-16T10:21:19+08:00
2018-10-16T10:21:19+08:00
寸土币争
https://segmentfault.com/u/liaogx
35
<h2>一、字符串 strings</h2>
<p>Python操作Redis的redis模块对字符串(string)的主要操作函数包括:SET、GET、GETSET、SETEX、SETNX、MSET、MSETNX、INCR(INCRBY,DECR,DECRBY在python中庸同一个函数incr实现)、APPEND、SETRANGE、STRLEN。函数说明如下:</p>
<ol>
<li>
<strong>SET</strong>: 为指定的键(key)设置值(value), set(self, name, value, **kwargs)。</li>
<li>
<strong>GET</strong>:获取指定键(key)绑定的值(value),get(self, name)。</li>
<li>
<strong>GETSET</strong>:为指定的键(key)设置新的值(value),并返回旧的值(old Value),getset(self, name, value)</li>
<li>
<strong>SETEX</strong>:为指定的键(key)设置过期以秒(second)计的过期时间,setex(self, name, value, time)</li>
<li>
<strong>SETNX</strong>:键(key)不存在时,为键(key)指定值(value),setnx(self, name, value)</li>
<li>
<strong>MSET</strong>:一次性设置多个键-值(key-value)对,函数设置的键-值对(即mapping所指内容)数据要以Python字典数据类型传入,mset(self, mapping)</li>
<li>
<strong>MSETNX</strong>:键-值(key-value)对不存在时,设置键-值(key-value)对,msetnx(self, mapping),mapping值参考6</li>
<li>
<strong>INCR</strong>:自增函数,默认步长为1,通过对步长(amount)大小以及字符的控制实现了INCRBY(amount>=1)、DECR(amount=-1)、DECRBY(amount<=-1)等函数功能,incr(self, name, amount=1)</li>
<li>
<strong>APPEND</strong>:为指定的字符串追加值,若不存在则直接创建,append(self, key, value)</li>
<li>
<strong>SETRANGE</strong>:用 value 参数覆写给定 key 所储存的字符串值,从偏移量 offset 开始,setrange(self, name, offset, value)</li>
<li>
<strong>STRLEN</strong>:返回字符串的长度,当name不存在时返回0,strlen(self, name)</li>
</ol>
<p>示例代码如下:</p>
<pre><code class="python">#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall() # 清空Redis
r.setex('name', value='liaogx', time=2) # 设置新值,过期时间为3s
r.mset(k1 = 'v1', k2 = 'v2', k3 = 'v3') # 批量设置新值
print(r.mget('k1', 'k2', 'k3', 'k4')) # 批量获取新值
print(r.getset('name', 'liaogaoxiang')) # 设置新值并获取原来的值
print(r.getrange('name', 0, 1)) # 获取子序列 0 <= x <= 1
r.setrange('name', 0, 'LIAO') # 修改字符串内容,从指定字符串索引开始向后替换(新值太长时,则向后添加),返回值的长度
i = 0
while i < 4:
print(r.get('name'))
time.sleep(1)
i += 1
source = 'foo'
r.set('n1', source)
r.setbit('n1', 7, 1)
'''
注:如果在Redis中有一个对应: n1 = "foo",
那么字符串foo的二进制表示为:01100110 01101111 01101111
所以,如果执行 setbit('n1', 7, 1),则就会将第7位设置为1,
那么最终二进制则变成 01100111 01101111 01101111,即:"goo"
'''
print(r.get('n1'))
print(r.getbit('n1', 7)) # 获取n1对应的值的二进制表示中的某位的值 (0或1)
r.set('n2', '廖高祥')
print(r.strlen('n2')) # 返回对应的字节长度(一个汉字3个字节)
r.set('num', 1)
r.incr('num', amount=10)
r.decr('num', amount=1)
print(r.get('num')) # 自增num对应的值,当name不存在时,则创建name=amount,否则,则自增。
r.append('num', 111)
print(r.get('num')) # 在redis num对应的值后面追加内容</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">[b'v1', b'v2', b'v3', None]
b'liaogx'
b'li'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'LIAOgaoxiang'
b'goo'
1
9
b'10'
b'10111'</code></pre>
<h2>二、列表 lists</h2>
<p>Python操作Redis主要利用了redis模块来实现,list表操作函数主要模拟了Redis操作命令LPUSH,LRANGE,LINDEX,BLPOP,BRPOP。函数说明如下:</p>
<ol>
<li>
<strong>lpush</strong>函数实现了从向指定redis列表头部压入数据功能,<code>lpush key value</code>
</li>
<li>
<strong>lrange</strong>获取列表指定范围的函数,<code>lrange key start end</code>
</li>
<li>
<strong>lindex</strong>根据列表下标量获取列表元素值, <code>lindex key index</code>
</li>
<li>
<strong>blpop</strong>从列表头部取出第一个元素,返回该元素值并从列表删除(l代表left,左边)</li>
<li>
<strong>brpop</strong>从列表尾部取出第一个元素,返回该元素值并从列表删除(l代表right,右边)</li>
<li>
<strong>LPUSHX、RPUSHX</strong>以及其他一些Redis列表(List)函数目前版本无法实现,如有可实现方法博客代码事例将会得到更新。</li>
</ol>
<p>示例代码如下:</p>
<pre><code class="python">#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall() # 清空Redis
r.lpush('oo', 11) # 保存顺序为: 33,22,11
r.lpushx('oo', 00) # 在name对应的list中添加元素,只有name已经存在时,值添加到列表的最左边
print(r.llen('oo')) # name对应的list元素的个数
r.linsert('oo', 'before', 11, 99) # 在11之前插入值99
r.lset('oo', 1, 88) # 对name对应的list中的某一个索引位置重新赋值
print(r.lrange('oo', 0, -1)) # 在name对应的列表分片获取数据
r.lrem('oo', 88, num=1) # 在name对应的list中删除指定的值.num=0,删除列表中所有的指定值;num=2,从前到后,删除2个;num=-2,从后向前,删除2个
print(r.lrange('oo', 0, -1))
print(r.lpop('oo')) # 在name对应的列表的左侧获取第一个元素并在列表中移除,返回值则是第一个元素
print(r.lindex('oo', 0)) # 在name对应的列表中根据索引获取列表元素
r.lpush('l1', 11) # index为0
r.rpush('l1', 22)
r.rpush('l1', 33)
r.rpush('l1', 44)
r.rpush('l1', 55) # index为4
r.ltrim('l1', 1, 3) # 在name对应的列表中移除没有在[start-end]索引之间的值
print(r.lrange('l1', 0, -1))
r.rpoplpush('l1', 'l1') # 从一个列表取出最右边的元素,同时将其添加至另一个列表的最左边;src要取数据的列表的name, dst要添加数据的列表的name
print(r.lrange('l1', 0, -1))
r.brpoplpush('l1', 'l1', timeout=3) # # timeout,当src对应的列表中没有数据时,阻塞等待其有数据的超时时间(秒),0 表示永远阻塞
print(r.lrange('l1', 0, -1))
print(r.blpop('l1', 3)) # 从列表头部取出第一个元素,返回该元素值并从列表删除(l代表left,左边)
print(r.lrange('l1', 0, -1))
'''
# 由于redis类库中没有提供对列表元素的增量迭代,如果想要循环name对应的列表的所有元素,那么就需要:
# 1、获取name对应的所有列表
# 2、循环列表
# 但是,如果列表非常大,那么就有可能在第一步时就将程序的内容撑爆,所有有必要自定义一个增量迭代的功能:
'''
print('自定义增量迭代:')
r.flushall()
r.lpush('l1', 11) # index为0
r.rpush('l1', 22)
r.rpush('l1', 33)
r.rpush('l1', 44)
r.rpush('l1', 55) # index为4
def list_iter(name):
list_count = r.llen(name)
for index in range(list_count):
yield r.lindex(name, index)
for item in list_iter('l1'):
print(item)</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">2
[b'0', b'88', b'11']
[b'0', b'11']
b'0'
b'11'
[b'22', b'33', b'44']
[b'44', b'22', b'33']
[b'33', b'44', b'22']
(b'l1', b'33')
[b'44', b'22']
自定义增量迭代:
b'11'
b'22'
b'33'
b'44'
b'55'</code></pre>
<h2>三、集合 sets</h2>
<p>Redis 数据库集合对象(set object)是由string类型的无重复元素的无需集合,底层编码可以是intset或者hashtable。intset编码的集合对象用整数集合最为底层实现,所有对象元素保存在整数集合中。Python的redis模块实现了 SADD、SCARD 、SDIFF 、SDIFFSTORE、SINTER 、SINTERSTORE、SISMEMBER 、SMEMBERS 、SMOVE、SPOP、SRANDMEMBER、SREM、SUNION、SUNIONSTORE操作命令的基本用法。函数说明如下:</p>
<ol>
<li>
<strong>SADD</strong>:向集合对象添加成员,sadd(self, name, value)</li>
<li>
<strong>SCARD</strong>:获取集合元素个数,scard(self, name)</li>
<li>
<strong>SDIFF</strong>:返回给定多个集合对象的差集(set key1-set key2..-set keyn),从左到右计算集合差集,sdiff(self, keys, *args)</li>
<li>
<strong>SDIFFSTORE</strong>:返回给定给定多个集合对象的差集并存储在目标(dest)集合中,sdiffstore(self, dest, keys, *args)</li>
<li>
<strong>SINTER</strong>:返回给定所有集合(keys, <em>args)的交集, sinter(self, keys, </em>args)</li>
<li>
<strong>SINTERSTORE</strong>:返回给定所有集合(keys, <em>args)的交集并存储在 集合(dest) 中, sinterstore(self, dest, keys, </em>args)</li>
<li>
<strong>SISMEMBER</strong>:判断 value元素是否是集合 name 的成员,返回布尔逻辑值True或者False,sismember(self, name, value)</li>
<li>
<strong>SMEMBERS</strong>:返回集合中所元素值的Python集合类型数据,smembers(self, name)</li>
<li>
<strong>SMOVE</strong>:将元素value从集合src移动到 集合 dest。若元素value在集合src中不存在,则集合dest中不会添加元素value, smove(self, src, dest, value)</li>
<li>
<strong>SPOP</strong>:移除并返回集合中的一个随机元素, spop(self, name)</li>
<li>
<strong>SRANDMEMBER</strong>:返回集合中一个随机数,但是不做移除操作, srandmember(self, name)。从Redis 2.6 版本开始, 在命令行下Srandmember 命令接受可选返回元素数量的参数 redis>SRANDMEMBER name count</li>
<li>
<strong>SREM</strong>:移除集合中一个元素,srem(self, name, value),redis模块任然沿用Redis 2.4 版本以前的只接受单个元素的用法。</li>
<li>
<strong>SUNION</strong>:返回所有给定集合的并集中所有元素,sunion(self, keys, *args)</li>
<li>
<strong>SUNIONSTORE</strong>:所有给定集合的并集存储在集合dest 中, sunionstore(self, dest, keys, *args)</li>
<li>
<strong>SSCAN</strong>:迭代集合中的元素,sscan(self, name, cursor=0, match=None, count=None)</li>
</ol>
<p>示例代码如下:</p>
<pre><code class="python">#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall() # 清空Redis
r.sadd('s1', 'v1', 'v1', 'v2', 'v3') # name对应的集合中添加元素
r.sadd('s2', 'v2', 'v4') # name对应的集合中添加元素
print(r.scard('s1')) # 获取name对应的集合中元素个数
print(r.sdiff('s1', 's2')) #在第一个name对应的集合中且不在其他name对应的集合的元素集合
r.sdiffstore('s3', 's1', 's2') # 获取第一个name对应的集合中且不在其他name对应的集合,再将其新加入到dest对应的集合中
print(r.smembers('s3')) # 获取s3对应的集合的所有成员
print(r.sinter('s1', 's2')) # 获取s1, s2对应集合的交集
r.sinterstore('s4', 's1', 's2') # 获取s1, s2对应集合的交集,并将其存放到集合是s4中
print(r.smembers('s4'))
print(r.sunion('s1', 's2')) # 获取s1, s2对应集合的并集
r.sunionstore('s5', 's1', 's2') # 获取s1, s2对应集合的交集,并将其存放到集合是s5中
print(r.smembers('s5'))
print(r.sismember('s4', 'v4')) # 检查value是否是name对应的集合的成员
r.smove('s2', 's1', 'v4') # 将集合s2中成员v4移至集合s1中
print(r.smembers('s1'))
r.srem('s1', 'v1') # 在name对应的集合中删除某些值
print(r.spop('s1')) # 从集合的右侧(尾部)移除一个成员,并将其返回 注意:集合是无序的,故结果随机!
print(r.srandmember('s1')) # 从name对应的集合中随机获取 numbers 个元素(Redis 2.6+)</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">3
{b'v3', b'v1'}
{b'v3', b'v1'}
{b'v2'}
{b'v2'}
{b'v3', b'v2', b'v4', b'v1'}
{b'v3', b'v2', b'v4', b'v1'}
False
{b'v3', b'v2', b'v4', b'v1'}
b'v2'
b'v3'</code></pre>
<h2>四、有序集合 sorted sets</h2>
<table>
<thead><tr>
<th>命令</th>
<th>描述</th>
</tr></thead>
<tbody>
<tr>
<td><a href="https://link.segmentfault.com/?enc=lNwOjaJcXE%2FC1ewYQhL2%2FA%3D%3D.PSr%2BN6Y%2Fo%2FiPACYP6VWwqh5F4Twpt1AxcUyVI606dA59dPMLsjsetMXFWVg%2BT4JZ" rel="nofollow">Redis Zadd 命令</a></td>
<td>向有序集合添加一个或多个成员,或者更新已存在成员的分数</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=rJcpZT4juX1qUKjCjiqPGw%3D%3D.A7Z0wEwPE5rGbv9gIUf5JTbaLn2JC%2By4oargHjOfaseX2N%2BtEtI%2BtvcLJMzGEQEE" rel="nofollow">Redis Zcard 命令</a></td>
<td>获取有序集合的成员数</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=Cgm%2F6PcfKIuSfpgW%2Fsp18w%3D%3D.8xvzf3iUwBlcBmOFFqUnW8D5JwRoHV799MnGE5kntFUY57nKjR0fX4X11H3T6Jea" rel="nofollow">Redis Zcount 命令</a></td>
<td>计算在有序集合中指定区间分数的成员数</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=OBDsSUp3EOliPbChtPJv1Q%3D%3D.eUnGrsyBJkcn5FnVcAMlBOLrP5Q5q8aHCZpecIcAZ19lxPX88TpF8%2BMtekNRXaKv" rel="nofollow">Redis Zincrby 命令</a></td>
<td>有序集合中对指定成员的分数加上增量 increment</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=Bm%2FjHvdbTkPNDpQhGrbRSQ%3D%3D.%2FQjzoxgLKr0IvfyCLHi5TFNKiFcTNW6ZoD90Iw783anLxRYDbbbaOW3yWtaJHJar" rel="nofollow">Redis Zinterstore 命令</a></td>
<td>计算给定的一个或多个有序集的交集并将结果集存储在新的有序集合 key 中</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=%2Bke5yKz2y1vn%2F6teQDD6%2Fg%3D%3D.DX8fh3SrHdGGepzks8a%2BcWrkw6U%2FI6Xq9DcazSoRF5DN5dDAWeu9DzcG2EwzxnhV" rel="nofollow">Redis Zlexcount 命令</a></td>
<td>在有序集合中计算指定字典区间内成员数量</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=Jef0r3LPn2vyO4RPjUPZYw%3D%3D.QtnjoVQ5vmdLsYk7wHvVd2sECTFGRBvrmNRNbwqDb6qmY5Kg4rSQt%2FUYmtwsYBns" rel="nofollow">Redis Zrange 命令</a></td>
<td>通过索引区间返回有序集合成指定区间内的成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=1RFr9x9qZ40iVAuts4W7vw%3D%3D.x%2FHlEbow6vD9VUJj6UnRxEV5O4KHyhjiF0Ogfj0OmMUTQmIM34PpAcmdEAqw9qeB" rel="nofollow">Redis Zrangebylex 命令</a></td>
<td>通过字典区间返回有序集合的成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=KrLH9sCk5e2upvPGvjt5hQ%3D%3D.bQ58HTFQduOns38r8Z%2FVahjDAaBFF%2BVA69jG5QmpnGJKgJH6h%2BCdeKhI6vHxoXUP" rel="nofollow">Redis Zrangebyscore 命令</a></td>
<td>通过分数返回有序集合指定区间内的成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=OagGZs8robAkDtsOHQGcuA%3D%3D.PhWiMPj%2B%2FRO382G6WwWetSX5LwKYE1pRs7ncBPDHhV1RoTqr%2FajIrs%2BVn9mznUnm" rel="nofollow">Redis Zrank 命令</a></td>
<td>返回有序集合中指定成员的索引</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=T%2B3CXArUQ0XwyKzrB857Pw%3D%3D.XmvRBx1GtFAg5fZ3%2FTHtwLtZultJPngPSFgOYQQXBK1%2BrsLEH6F82XAIfydzWd3k" rel="nofollow">Redis Zrem 命令</a></td>
<td>移除有序集合中的一个或多个成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=KhdgvwqZK8xeKwh5IHDFww%3D%3D.XqbZ%2FH8%2FGY2s67PfMrJ%2FY86xpu3f6LHwVpygjqrM3RcPcHRrSUHQplZX4SVlDssL" rel="nofollow">Redis Zremrangebylex 命令</a></td>
<td>移除有序集合中给定的字典区间的所有成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=6N%2BQtB%2FmnjACV1IWtIgDdg%3D%3D.s%2F%2BT33nDUPDPttLSb8mrcAhG5JMWBrKJCjWHR%2FtYXmb%2FStbR8VJzbKQq1heTt3Gj" rel="nofollow">Redis Zremrangebyrank 命令</a></td>
<td>移除有序集合中给定的排名区间的所有成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=Z1TQwax9xXU0TO6umTyAqA%3D%3D.389zN07CK7ixrd4gLf2tQCUK9NZ%2BH%2FyqN6tJ6hAEtOKDOcF7utNkTqOzkHP2fS3w" rel="nofollow">Redis Zremrangebyscore 命令</a></td>
<td>移除有序集合中给定的分数区间的所有成员</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=%2FLnTj7Nw5vNT6IlRJIBp7g%3D%3D.EiRcOnNmowhT%2Bzo4PIAvIoWMIbXeupDtxNLx%2Fz2dnFo8o21pXdMoHZzR%2FxSpnnkq" rel="nofollow">Redis Zrevrange 命令</a></td>
<td>返回有序集中指定区间内的成员,通过索引,分数从高到底</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=W9htbs2Zp7tlvEzC8atDdQ%3D%3D.ByTlQAuMSa%2FJC1spRXtNcKV%2BVV754xso7ZFaAqiJDwztHc%2BS63CRlEMRJ%2F15JcMK" rel="nofollow">Redis Zrevrangebyscore 命令</a></td>
<td>返回有序集中指定分数区间内的成员,分数从高到低排序</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=Kmq7axwpMJIrwsRsqsw38w%3D%3D.t6M1bn1Oae7NIT6647MtWSv8DkBB1%2FB9Bo7y%2ByHCFlNyy0i7jaxPf0hgQQSxHn1D" rel="nofollow">Redis Zrevrank 命令</a></td>
<td>返回有序集合中指定成员的排名,有序集成员按分数值递减(从大到小)排序</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=ngms7mafefA0ALBK3qSbJA%3D%3D.E3ZFWuKxhf7DxBPu4OHzY4hF7bSLaTX%2Bg2aHzdFYB3AoNaoDe2DIfDvm4biLmZs9" rel="nofollow">Redis Zscore 命令</a></td>
<td>返回有序集中,成员的分数值</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=n6FBMpMcvpiqKHo9i%2F%2FjSw%3D%3D.aK5c%2BAA0mbPB9oY5pJUreiLabMCk%2BgEkiMKgsFvaNKwxszsBsK8384pPSk%2FV8Ct0" rel="nofollow">Redis Zunionstore 命令</a></td>
<td>计算给定的一个或多个有序集的并集,并存储在新的 key 中</td>
</tr>
<tr>
<td><a href="https://link.segmentfault.com/?enc=zh%2BtIoSHxnc%2FH75HcccQPg%3D%3D.WR8R2j%2FJhEItytBtI1%2FDMfprZ2rnR4J9ju0nPHJU51V34VeD%2BhpDK%2BfidMIf3F52" rel="nofollow">Redis Zscan 命令</a></td>
<td>迭代有序集合中的元素(包括元素成员和元素分值)</td>
</tr>
</tbody>
</table>
<p>示例代码如下:</p>
<pre><code class="python">#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall() # 清空Redis
r.zadd('z1', '11', 1, '22', 2, '33', 3, '44', 4, '55', 5, '66', 6, '66', 7) # 在name对应的有序集合中添加元素
print(r.zcard('z1')) # 获取name对应的有序集合元素的数量
print(r.zcount('z1', 1, 2)) # 获取name对应的有序集合中分数 在 [min,max] 之间的个数
r.zincrby('z1', '11', amount=5) # 自增name对应的有序集合的 name 对应的分数
print(r.zrange('z1', 0, -1, desc=False, withscores=True)) # 值11被排序到最后;此处表示按元素的值升序排列
print(r.zrank('z1', 33)) # 获取某个值在 name对应的有序集合中的排行(从 0 开始)
r.zrem('z1', '66') # 删除name对应的有序集合中值是values的成员
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
r.zremrangebyrank('z1', 0, 1) # 根据排行范围删除
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
r.zremrangebyscore('z1', 4.5, 5.5) # 根据分数范围删除
print(r.zrange('z1', 0, -1, desc=False, withscores=True))
print(r.zscore('z1', 11)) # 获取name对应有序集合中 value 对应的分数
r.zadd("zset_name", "a1", 6, "a2", 2, "a3", 5)
r.zadd('zset_name1', a1=7, b1=10, b2=5)
'''
获取两个有序集合的交集并放入dest集合,如果遇到相同值不同分数,则按照aggregate进行操作
aggregate的值为: SUM MIN MAX
'''
r.zinterstore('zset_name2', ('zset_name', 'zset_name1'), aggregate='Sum')
print(r.zrange('zset_name2', 0, -1, desc=False, withscores=True))</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">6
2
[(b'22', 2.0), (b'33', 3.0), (b'44', 4.0), (b'55', 5.0), (b'11', 6.0), (b'66', 6.0)]
1
[(b'22', 2.0), (b'33', 3.0), (b'44', 4.0), (b'55', 5.0), (b'11', 6.0)]
[(b'44', 4.0), (b'55', 5.0), (b'11', 6.0)]
[(b'44', 4.0), (b'11', 6.0)]
6.0
[(b'a1', 13.0)]</code></pre>
<h2>五、哈希 hashes</h2>
<p>Redis 数据库hash数据类型是一个string类型的key和value的映射表,适用于存储对象。redis 中每个hash可以存储键值对多达40亿。Python的redis模块实现了Redis哈希(Hash)命令行操作的几乎全部命令,包括HDEL、HEXISTS、HGET、HGETALL、HINCRBY、HKEYS、HLEN 、HMGET 、HMSET 、HSET 、HSETNX 、HVALS 、HINCRBYFLOAT等命令。函数说明如下:</p>
<ol>
<li>
<strong>HDEL</strong>:删除对应哈希(Hash)表的指定键(key)的字段,hdel(self, name, key)</li>
<li>
<strong>HEXISTS</strong>:检测哈希(Hash)表对应键(key)字段是否存在,返回布尔逻辑,hexists(self, name, key)</li>
<li>
<strong>HGET</strong>:获取哈希(Hash)指定键(key)对应的值,hget(self, name, key)</li>
<li>
<strong>HGETALL</strong>:获取哈希(Hash)表的键-值对(key-value pairs),返回python字典类型数据,hgetall(self, name)</li>
<li>
<strong>HINCRBY</strong>:为哈希表(Hash)指定键(key)对应的值(key)加上指定的整数数值(int,可为负值)hincrby(self>, name, key, amount=1),Redis 中本操作的值被限制在 64 位(bit)有符号数字。</li>
<li>
<strong>HKEYS</strong>:返回哈希表(Hash)对应键(key)的数组(Python称之为列表List),hkeys(self, name)</li>
<li>
<strong>HLEN</strong>: 获取哈希表(Hash)中键-值对(key-value pairs)个数,hlen(self, name)</li>
<li>
<strong>HMGET</strong>:获取哈希表(Hash)中一个或多个给点字段的值,不存在返回nil(Redis命令行)/None(Python),hmget(self, name, keys),其中keys可以为列表(list)</li>
<li>
<strong>HMSET</strong>:设置对个键-值对(key-value pairs)到哈希表(Hash)中,python输入值(mapping)为字典(dictionary)类型,hmset(self, name, mapping)</li>
<li>
<strong>HSET</strong>:为哈希表(Hash)赋值,若键(key)存在值(value)则覆盖,不存在则创建,hset(self, name, key, value)</li>
<li>
<strong>HSETNX</strong>:为哈希表(Hash)不存值(value)的键(key)赋值,存在操作无效,对应值(value)无变化,hsetnx(self, name, key, value)</li>
<li>
<strong>HVALS</strong>:返回哈希表(Hash)对应值(value)的列表,hvals(self, name)</li>
<li>
<strong>HINCRBYFLOAT</strong>:为哈希表 key 中的指定字段的浮点数值加上增量 increment ,hincrbyfloat(self, name, key, amount=1.0)</li>
</ol>
<p>示例代码如下:</p>
<pre><code class="python">#!/usr/bin/python
# -*- coding:utf-8 -*-
# __author__ = 'Jack'
pool = redis.ConnectionPool(host='127.0.0.1', port=6379)
r = redis.Redis(connection_pool=pool)
r.flushall() # 清空Redis
r.hset('n1', 'k1', 'v1') # hset(name, key, value),name对应的hash中设置一个键值对(不存在,则创建;否则,修改)
print(r.hget('n1', 'k1'))
r.hmset('n2', {'k1': 'v1', 'k2': 'v2', 'k3': 'v3'}) # hmset(name, mapping),在name对应的hash中批量设置键值对
print(r.hmget('n2', 'k2'))
print(r.hgetall('n2')) # 获取name对应hash的所有键值
print(r.hlen('n2')) # 获取name对应的hash中键值对的个数
print(r.hkeys('n2')) # 获取name对应的hash中所有的key的值
print(r.hvals('n2')) # 获取name对应的hash中所有的value的值
print(r.hexists('n2', 'k4')) # 检查name对应的hash是否存在当前传入的key
r.hdel('n2', 'k3') # 将name对应的hash中指定key的键值对删除
r.hset('n3', 'k1', 1)
r.hincrby('n3', 'k1', amount=1) # hincrby(name, key, amount=1),自增name对应的hash中的指定key的value的值,不存在则创建key=amount
print(r.hgetall('n3'))</code></pre>
<p>输出结果如下:</p>
<pre><code class="python">b'v1'
[b'v2']
{b'k1': b'v1', b'k2': b'v2', b'k3': b'v3'}
3
[b'k1', b'k2', b'k3']
[b'v1', b'v2', b'v3']
False
{b'k1': b'2'}</code></pre>
<blockquote>命令太多记不住可以参考<a href="https://link.segmentfault.com/?enc=3Tq9IG1H84Ch9QqZPNbHcw%3D%3D.23Ig9FV44LLaRnN7U%2BxBm6R8GUIkVpXKVcwb764D9s4%3D" rel="nofollow">Redis中文网</a>,强烈建议收藏</blockquote>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Redis入门教程
https://segmentfault.com/a/1190000016649276
2018-10-11T14:23:16+08:00
2018-10-11T14:23:16+08:00
寸土币争
https://segmentfault.com/u/liaogx
47
<h2>一、基础知识</h2>
<h3>1.1 数据库</h3>
<p>在Redis里,数据库简单的使用一个数字编号来进行辨认,默认数据库的数字编号是0。如果你想切换到一个不同的数据库,你可以使用select命令来实现。在命令行界面里键入select 1,Redis应该会回复一条OK的信息,然后命令行界面里的提示符会变成类似redis 127.0.0.1:6379[1]>这样。如果你想切换回默认数据库,只要在命令行界面键入<code>select 0</code>即可</p>
<h3>1.2 命令、关键字和值</h3>
<p>Redis不仅仅是一种简单的关键字-值型存储,从其核心概念来看,Redis的5种数据结构中的每一个都至少有一个关键字和一个值</p>
<p>关键字(Keys)是用来标识数据块,值(Values)是关联于关键字的实际值,可以是字符串、整数、序列化对象(使用JSON、XML或其他格式)</p>
<p>Redis命令的基本构成,如:<em>set users:leto "{name: leto, planet: dune, likes: [spice]}"</em></p>
<p>关键字和值的是Redis的基本概念,而get和set命令是对此最简单的使用</p>
<h3>1.3 Redis查询</h3>
<p>对于Redis而言,关键字就是一切,而值是没有任何意义。Redis不允许通过值来进行查询</p>
<h3>1.4 存储器和持久化</h3>
<p>Redis是一种持久化的存储器内存储(in-memory persistent store)默认情况下,Redis会根据已变更的关键字数量来进行判断,然后在磁盘里创建数据库的快照(snapshot)。你可以对此进行设置,如果X个关键字已变更,那么每隔Y秒存储数据库一次。默认情况下,如果1000个或更多的关键字已变更,Redis会每隔60秒存储数据库;而如果9个或更少的关键字已变更,Redis会每隔15分钟存储数据库</p>
<p>至于存储器,Redis会将所有数据都保留在存储器中。显而易见,运行Redis具有不低的成本:因为RAM仍然是最昂贵的服务器硬件部件</p>
<h3>1.5 小结</h3>
<p>关键字(Keys)是用于标识一段数据的一个字符串</p>
<p>值(Values)是一段任意的字节序列,Redis不会关注它们实质上是什么</p>
<p>Redis展示了(也实现了)5种专门的数据结构</p>
<p>上面的几点使得Redis快速而且容易使用,但要知道Redis并不适用于所有的应用场景</p>
<h2>二、Redis的数据结构</h2>
<p>关于key</p>
<ul>
<li>key不要太长,尽量不要超过1024字节,这不仅消耗内存,而且会降低查找的效率</li>
<li>key也不要太短,太短的话,key的可读性会降低</li>
<li>在一个项目中,key最好使用统一的命名模式,例如user:10000:passwd</li>
</ul>
<h3>2.1 字符串strings</h3>
<pre><code class="bash">127.0.0.1:6379> set mynum "2"
OK
127.0.0.1:6379> get mynum
"2"
127.0.0.1:6379> incr mynum
(integer) 3
127.0.0.1:6379> get mynum
"3"</code></pre>
<p>由于INCR等指令本身就具有原子操作的特性,所以我们完全可以利用redis的INCR、INCRBY、DECR、DECRBY等指令来实现原子计数的效果,假如,在某种场景下有3个客户端同时读取了mynum的值(值为2),然后对其同时进行了加1的操作,那么,最后mynum的值一定是5。不少网站都利用redis的这个特性来实现业务上的统计计数需求。</p>
<h3>2.2 列表lists</h3>
<p>lists的常用操作包括LPUSH、RPUSH、LRANGE等。我们可以用LPUSH在lists的左侧插入一个新元素,用RPUSH在lists的右侧插入一个新元素,用LRANGE命令从lists中指定一个范围来提取元素。</p>
<pre><code class="bash">//新建一个list叫做mylist,并在列表头部插入元素"1"
127.0.0.1:6379> lpush mylist "1"
//返回当前mylist中的元素个数
(integer) 1
//在mylist右侧插入元素"2"
127.0.0.1:6379> rpush mylist "2"
(integer) 2
//在mylist左侧插入元素"0"
127.0.0.1:6379> lpush mylist "0"
(integer) 3
//列出mylist中从编号0到编号1的元素
127.0.0.1:6379> lrange mylist 0 1
1) "0"
2) "1"
//列出mylist中从编号0到倒数第一个元素
127.0.0.1:6379> lrange mylist 0 -1
1) "0"
2) "1"
3) "2"</code></pre>
<p>lists的应用相当广泛,随便举几个例子:</p>
<ul>
<li>我们可以利用lists来实现一个消息队列,而且可以确保先后顺序,不必像MySQL那样还需要通过ORDER BY来进行排序。</li>
<li>利用LRANGE还可以很方便的实现分页的功能。</li>
<li>在博客系统中,每片博文的评论也可以存入一个单独的list中。</li>
</ul>
<h3>2.3 集合sets</h3>
<p>redis的集合,是一种无序的集合,集合中的元素没有先后顺序。集合相关的操作也很丰富,如添加新元素、删除已有元素、取交集、取并集、取差集等.</p>
<pre><code class="bash">//向集合myset中加入一个新元素"one"
127.0.0.1:6379> sadd myset "one"
(integer) 1
127.0.0.1:6379> sadd myset "two"
(integer) 1
//列出集合myset中的所有元素
127.0.0.1:6379> smembers myset
1) "one"
2) "two"
//判断元素1是否在集合myset中,返回1表示存在
127.0.0.1:6379> sismember myset "one"
(integer) 1
//判断元素3是否在集合myset中,返回0表示不存在
127.0.0.1:6379> sismember myset "three"
(integer) 0
//新建一个新的集合yourset
127.0.0.1:6379> sadd yourset "1"
(integer) 1
127.0.0.1:6379> sadd yourset "2"
(integer) 1
127.0.0.1:6379> smembers yourset
1) "1"
2) "2"
//对两个集合求并集
127.0.0.1:6379> sunion myset yourset
1) "1"
2) "one"
3) "2"
4) "two"</code></pre>
<p>对于集合的使用,也有一些常见的方式,比如,QQ有一个社交功能叫做“好友标签”。</p>
<h3>2.4 有序集合sorted sets</h3>
<p>redis还提供了有序集合(sorted sets)。有序集合中的每个元素都关联一个序号(score),这便是排序的依据。很多时候,我们都将redis中的有序集合叫做zsets,这是因为在redis中,有序集合相关的操作指令都是以z开头的,比如zrange、zadd、zrevrange、zrangebyscore等等</p>
<pre><code class="bash">//新增一个有序集合myzset,并加入一个元素baidu.com,给它赋予的序号是1:
127.0.0.1:6379> zadd myzset 1 baidu.com
(integer) 1
//向myzset中新增一个元素360.com,赋予它的序号是3
127.0.0.1:6379> zadd myzset 3 360.com
(integer) 1
//向myzset中新增一个元素google.com,赋予它的序号是2
127.0.0.1:6379> zadd myzset 2 google.com
(integer) 1
//列出myzset的所有元素,同时列出其序号,可以看出myzset已经是有序的了。
127.0.0.1:6379> zrange myzset 0 -1 withscores
1) "baidu.com"
2) "1"
3) "google.com"
4) "2"
5) "360.com"
6) "3"
//只列出myzset的元素
127.0.0.1:6379> zrange myzset 0 -1
1) "baidu.com"
2) "google.com"
3) "360.com"</code></pre>
<h3>2.5 哈希hashes</h3>
<p>hashes存的是字符串和字符串值之间的映射,比如一个用户要存储其全名、姓氏、年龄等等,就很适合使用哈希</p>
<pre><code class="bash">//建立哈希,并赋值
127.0.0.1:6379> HMSET user username antirez password P1pp0 age 34
OK
//列出哈希的内容
127.0.0.1:6379> HGETALL user
1) "username"
2) "antirez"
3) "password"
4) "P1pp0"
5) "age"
6) "34"
//更改哈希中的某一个值
127.0.0.1:6379> HSET user password 12345
(integer) 0
//再次列出哈希的内容
127.0.0.1:6379> HGETALL user
1) "username"
2) "antirez"
3) "password"
4) "12345"
5) "age"
6) "34"</code></pre>
<h2>三、Redis持久化-RDB和AOF</h2>
<p>持久化不属于入门范围,找了几篇比较好的文章,有兴趣欢迎阅读</p>
<ul>
<li><a href="https://link.segmentfault.com/?enc=2rF8v45OoIbP4RrX2fo09g%3D%3D.mPmQXD4TsvJfJk%2FT7DhiVJp9bI8OkS8ooap5nKZISqufCnq340nNCjQl44GypzUw" rel="nofollow">redis持久化RDB和AOF</a></li>
<li>
<a href="https://link.segmentfault.com/?enc=ZPfrkMcE8KZxgJRnmsJnbQ%3D%3D.RsiuCDpILVG5tz2E%2BDCGYBmhQhFo8sFHLHrf3NgPgVA%3D" rel="nofollow">[Redis持久化RDB和AOF相比较</a>]</li>
<li>
<a href="https://link.segmentfault.com/?enc=8UNeATn05V3k4TDM1ud64g%3D%3D.U6J29liJ%2BSxFhUHVkDeXbj7qdJ%2B6ntflpx3ssuuf%2BmQ5MhMjuiG8u%2B6QnvRP1ng1" rel="nofollow">[redis系列:RDB持久化与AOF持久化</a>]</li>
</ul>
<h2>四、redis.conf文件配置项</h2>
<p>redis.conf 配置项说明如下:</p>
<ol>
<li>Redis默认不是以守护进程的方式运行,可以通过该配置项修改,使用yes启用守护进程<br><code>daemonize no</code>
</li>
<li>当Redis以守护进程方式运行时,Redis默认会把pid写入<code>/var/run/redis.pid</code>文件,可以通过pidfile指定<br><code>pidfile /var/run/redis.pid</code>
</li>
<li>指定Redis监听端口,默认端口为<code>6379</code>,这里有个故事,因为6379在手机按键上MERZ对应的号码,而MERZ取自意大利歌女Alessia Merz的名字<br><code>port 6379</code>
</li>
<li>绑定的主机地址<br><code>bind 127.0.0.1</code>
</li>
<li>当客户端闲置多长时间后关闭连接,如果指定为0,表示关闭该功能<br><code>timeout 30</code>
</li>
<li>指定日志记录级别,Redis总共支持四个级别:debug、verbose、notice、warning,默认为verbose<br><code>loglevel verbose</code>
</li>
<li>日志记录方式,默认为标准输出,如果配置Redis为守护进程方式运行,而这里又配置为日志记录方式为标准输出,则日志将会发送给<code>/dev/null</code><br><code>logfile stdout</code>
</li>
<li>设置数据库的数量,默认数据库为0,可以使用SELECT <dbid>命令在连接上指定数据库id<br><code>databases 16</code>
</li>
<li>指定在多长时间内,有多少次更新操作,就将数据同步到数据文件,可以多个条件配合<br><code>save <seconds> <changes></code><br> Redis默认配置文件中提供了三个条件:<br> `save 900 1<br> save 300 10<br> save 60 10000`<br> 分别表示<strong>900秒(15分钟)内有1个更改,300秒(5分钟)内有10个更改以及60秒内有10000个更改</strong>。</li>
<li>指定存储至本地数据库时是否压缩数据,默认为yes,Redis采用LZF压缩,如果为了节省CPU时间,可以关闭该选项,但会导致数据库文件变的巨大<br><code>rdbcompression yes</code>
</li>
<li>指定本地数据库文件名,默认值为dump.rdb<br><code>dbfilename dump.rdb</code>
</li>
<li>
<p>指定本地数据库存放目录</p>
<pre><code>`dir ./`
</code></pre>
</li>
<li>
<p>设置当本机为slav服务时,设置master服务的IP地址及端口,在Redis启动时,它会自动从master进行数据同步</p>
<pre><code>`slaveof <masterip> <masterport>`
</code></pre>
</li>
<li>
<p>当master服务设置了密码保护时,slav服务连接master的密码</p>
<pre><code>`masterauth <master-password>`
</code></pre>
</li>
<li>
<p>设置Redis连接密码,如果配置了连接密码,客户端在连接Redis时需要通过AUTH <password>命令提供密码,默认关闭</p>
<pre><code>`requirepass foobared`
</code></pre>
</li>
<li>设置同一时间最大客户端连接数,默认无限制,Redis可以同时打开的客户端连接数为Redis进程可以打开的最大文件描述符数,如果设置 maxclients 0,表示不作限制。当客户端连接数到达限制时,Redis会关闭新的连接并向客户端返回<em>max number of clients reached</em>错误信息<br><code>maxclients 128</code>
</li>
<li>
<p>指定Redis最大内存限制,Redis在启动时会把数据加载到内存中,达到最大内存后,Redis会先尝试清除已到期或即将到期的Key,当此方法处理后,仍然到达最大内存设置,将无法再进行写入操作,但仍然可以进行读取操作。Redis新的vm机制,会把Key存放内存,Value会存放在swap区</p>
<pre><code>`maxmemory <bytes>`
</code></pre>
</li>
<li>指定是否在每次更新操作后进行日志记录,Redis在默认情况下是异步的把数据写入磁盘,如果不开启,可能会在断电时导致一段时间内的数据丢失。因为 redis本身同步数据文件是按上面save条件来同步的,所以有的数据会在一段时间内只存在于内存中。默认为no<br><code>appendonly no</code>
</li>
<li>指定更新日志文件名,默认为appendonly.aof<br><code>appendfilename appendonly.aof</code>
</li>
<li>
<p>指定更新日志条件,共有3个可选值:</p>
<blockquote>no:表示等操作系统进行数据缓存同步到磁盘(快) <br> always:表示每次更新操作后手动调用fsync()将数据写到磁盘(慢,安全) <br> everysec:表示每秒同步一次(折衷,默认值)<br> appendfsync everysec</blockquote>
</li>
<li>指定是否启用虚拟内存机制,默认值为no,简单的介绍一下,VM机制将数据分页存放,由Redis将访问量较少的页即冷数据swap到磁盘上,访问多的页面由磁盘自动换出到内存中<br><code>vm-enabled no</code>
</li>
<li>虚拟内存文件路径,默认值为/tmp/redis.swap,不可多个Redis实例共享<br><code>vm-swap-file /tmp/redis.swap</code>
</li>
<li>将所有大于vm-max-memory的数据存入虚拟内存,无论vm-max-memory设置多小,所有索引数据都是内存存储的(Redis的索引数据 就是keys),也就是说,当vm-max-memory设置为0的时候,其实是所有value都存在于磁盘。默认值为0<br><code>vm-max-memory 0</code>
</li>
<li>Redis swap文件分成了很多的page,一个对象可以保存在多个page上面,但一个page上不能被多个对象共享,vm-page-size是要根据存储的 数据大小来设定的,作者建议如果存储很多小对象,page大小最好设置为32或者64bytes;如果存储很大大对象,则可以使用更大的page,如果不 确定,就使用默认值<br><code>vm-page-size 32</code>
</li>
<li>设置swap文件中的page数量,由于页表(一种表示页面空闲或使用的bitmap)是在放在内存中的,,在磁盘上每8个pages将消耗1byte的内存。<br><code>vm-pages 134217728</code>
</li>
<li>设置访问swap文件的线程数,最好不要超过机器的核数,如果设置为0,那么所有对swap文件的操作都是串行的,可能会造成比较长时间的延迟。默认值为4<br><code>vm-max-threads 4</code>
</li>
<li>设置在向客户端应答时,是否把较小的包合并为一个包发送,默认为开启<br><code>glueoutputbuf yes</code>
</li>
<li>指定在超过一定的数量或者最大的元素超过某一临界值时,采用一种特殊的哈希算法<br> `hash-max-zipmap-entries 64<br> hash-max-zipmap-value 512`</li>
<li>指定是否激活重置哈希,默认为开启<br><code>activerehashing yes</code>
</li>
<li>指定包含其它的配置文件,可以在同一主机上多个Redis实例之间使用同一份配置文件,而同时各个实例又拥有自己的特定配置文件<p><code>include /path/to/local.conf</code></p>
</li>
</ol>
<ul><li>什么是守护进程?<br>守护进程(Daemon Process),也就是通常说的 Daemon 进程(精灵进程),是 Linux 中的后台服务进程。它是一个生存期较长的进程,通常独立于控制终端并且周期性地执行某种任务或等待处理某些发生的事件。守护进程是个特殊的孤儿进程,这种进程脱离终端,为什么要脱离终端呢?之所以脱离于终端是为了避免进程被任何终端所产生的信息所打断,其在执行过程中的信息也不在任何终端上显示。由于在 linux 中,每一个系统与用户进行交流的界面称为终端,每一个从此终端开始运行的进程都会依附于这个终端,这个终端就称为这些进程的控制终端,当控制终端被关闭时,相应的进程都会自动关闭。</li></ul>
<h2>五、 事务处理</h2>
<p>MULTI、EXEC、DISCARD、WATCH指令构成了redis事务处理的基础</p>
<p>MULTI用来组装一个事务;</p>
<p>EXEC用来执行一个事务;</p>
<p>DISCARD用来取消一个事务;</p>
<p>WATCH用来监视一些key,一旦这些key在事务执行之前被改变,则取消事务的执行。</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
CentOS 7如何重置root密码
https://segmentfault.com/a/1190000016452153
2018-09-19T11:29:03+08:00
2018-09-19T11:29:03+08:00
寸土币争
https://segmentfault.com/u/liaogx
13
<p>搬砖过程中杂七杂八的环境和配置问题,每次总能碰到不一样的错误。Google一下发现别人能解决的方法不一定适合你。这次我遇到问题的环境是:</p>
<blockquote>Windows 10 企业版 2016 LTS<p>VMware® Workstation 14 Pro 14.1.0 build-7370693</p>
<p>CentOS Linux release 7.5.1804 (Core)</p>
</blockquote>
<p>VMWare中安装的CentOS 7 root密码忘记了,于是只能重置</p>
<h3>一、启动客户机</h3>
<p><img src="/img/remote/1460000016452156" alt="1536998450313" title="1536998450313"></p>
<p>进入如上界面之后按<code>e</code>,然后进入如下界面</p>
<p><img src="/img/remote/1460000016452157" alt="1536998520012" title="1536998520012"></p>
<h3>二、修改启动文件</h3>
<p>光标往下,找到<code>Linux16</code>,<code>ro</code>的位置</p>
<p><img src="/img/remote/1460000016452158" alt="1536998611783" title="1536998611783"></p>
<p>将<code>ro</code>改成<code>rw init=/sysroot/bin/sh</code>,按<code>Ctrl + x</code>重新启动。</p>
<p>这里说明一下,有的教程说改成<code>rw init=/bin/sh</code>,反正我是没成功!改成<code>rw init=/bin/sh</code>之后重启客户机报错如下</p>
<p><img src="/img/remote/1460000016452159" alt="1536998965521" title="1536998965521"></p>
<p>说我BIOS使hw-PMU资源奔溃,<em>客户机操作系统已禁用CPU。请关闭或重置虚拟机。</em>于是按照这个报错去Google了好久,说是Windows系统没有开启CPU虚拟化,于是重启笔记本进入BIOS</p>
<p><img src="/img/remote/1460000016452160" alt="1537001221085" title="1537001221085"></p>
<p>发现<code>Intel virtualization Technology</code>是开启,问题越扯越离谱,还是改成<code>rw init=/sysroot/bin/sh</code>吧!</p>
<h3>三、重新启动</h3>
<p>重启客户机后进入如下界面,执行<code>chroot /sysroot</code></p>
<p><img src="/img/remote/1460000016452161" alt="1536999477417" title="1536999477417"></p>
<p>执行<code>passwd root</code>更改root用户密码</p>
<pre><code class="bash">:/# passwd root
Changing password for user root
New password:
Retype new password:
passwd: Authentication token manipulation error</code></pre>
<h3>四、更新/etc/shadow</h3>
<p>如果有报错提示<code>Authentication token manipulation error</code>,表示root密码更改失败,<a href="https://link.segmentfault.com/?enc=cj49BT1w0Qo5BqQOohCRZA%3D%3D.mwqurHvbXLyjan1tXCrDLaUHFct6Mk8jof948AukTmB3fPoFfjyJsjNhhwIIRCM%2B3JYBi%2BPx9NHTynmxOVHI9Lfih2Se6Moi5XXC7uvadZSGb8G4gztmq%2F4bksJHx6AjD%2F5IQ1S9OFemgZwngoVYnSyda6CYbVMC0qlEw5xJrNY%3D" rel="nofollow">正确答案在这里</a>。因为没有<code>/etc/shadow</code>文件,如图</p>
<p><img src="/img/remote/1460000016452162" alt="1537000183239" title="1537000183239"></p>
<p>只有<code>gshadow</code>和<code>gshadow-</code>。通过<code>pwconv</code>重新生成<code>shadow</code>文件,并设置权限为<code>-rw-r-----</code></p>
<p><img src="/img/remote/1460000016452163" alt="1537000366423" title="1537000366423"></p>
<h3>五、重新挂载root分区</h3>
<blockquote>mount -o remount,rw /</blockquote>
<p>此时再更改root密码,发现可以了</p>
<pre><code class="bash">:/# passwd root
Changing password for user root
New password:
Retype new password:
passwd: all authentication tokens updated successfully</code></pre>
<p><img src="/img/remote/1460000016452164" alt="1537000929084" title="1537000929084"></p>
<p>重启客户机登录成功!</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
CentOS 7更新YUM源步骤
https://segmentfault.com/a/1190000016397359
2018-09-14T11:35:34+08:00
2018-09-14T11:35:34+08:00
寸土币争
https://segmentfault.com/u/liaogx
11
<p>国内小伙伴推荐使用<a href="https://link.segmentfault.com/?enc=IH6N9Ui5Be3rLG5Hhku5qA%3D%3D.7T0yeBNZER%2Bjz2%2BToz17L%2FNZlEJnKxTWOxz2stWd0oI%3D" rel="nofollow">阿里云的源</a></p>
<h3>Step1 找到需要的源</h3>
<p><a href="https://link.segmentfault.com/?enc=GoWVHxcpA1CSy%2Fq13zPqxA%3D%3D.CqcL%2Fj8RtC0AQIfBPxRA7L6uAFLwlQZ67gxcshUTbjs%3D" rel="nofollow">阿里巴巴开源镜像站</a>各种源应有尽有,老域名是<a href="https://link.segmentfault.com/?enc=DJRvQjYFy0pY84gL7aOw6w%3D%3D.e%2FpJTaIxJx7GRKlVib187zVQlhQIos%2F5i41baHvMM9s%3D" rel="nofollow">https://mirrors.aliyun.com/</a></p>
<p><img src="/img/remote/1460000016397362" alt="" title=""></p>
<h3>Step2 编辑CentOS7.repo文件</h3>
<p>进入<code>/etc/yum.repos.d</code>,发现我的源还是<em>7.4.1708</em></p>
<pre><code class="bash">[base]
name=CentOS-$releasever - Base - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7.4.1708/os/x86_64/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
#released updates
[updates]
name=CentOS-$releasever - Updates - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7.4.1708/updates/x86_64/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=updates
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7.4.1708/extras/x86_64/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=extras
gpgcheck=1
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7.4.1708/centosplus/x86_64/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=centosplus
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7
#contrib - packages by Centos Users
[contrib]
name=CentOS-$releasever - Contrib - mirrors.aliyun.com
failovermethod=priority
baseurl=http://mirrors.aliyun.com/centos/7.4.1708/contrib/x86_64/
#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=contrib
gpgcheck=1
enabled=0
gpgkey=http://mirrors.aliyun.com/centos/RPM-GPG-KEY-CentOS-7</code></pre>
<p>这个版本的源已经迁移到<em>7.5.1804</em>了,→<a href="https://link.segmentfault.com/?enc=u98PEfAbs%2FmqOiIx48z4zQ%3D%3D.VixNJ%2FLyerplqnHQf4ybCRdZLVWNBJiFmqlXzk3ajlzytvb8Yl0qwCSRhrOioZy0VLtWf6wBQoBNxxhlNjNJvg%3D%3D" rel="nofollow">地址</a>,使用VIM将其替换</p>
<pre><code class="bash">:%s/7.4.1708/7.7.1908/g</code></pre>
<h3>Step3 修复冲突报错</h3>
<p>然后更新系统试试<code>yum -y update</code></p>
<pre><code class="bash">[root@liaogx ~]# yum -y update
Plugin "product-id" can't be imported
Plugin "search-disabled-repos" can't be imported
Loaded plugins: fastestmirror
Loading mirror speeds from cached hostfile
* base: mirrors.aliyun.com
* epel: mirrors.tuna.tsinghua.edu.cn
* extras: mirrors.aliyun.com
* updates: mirrors.aliyun.com
Resolving Dependencies
--> Running transaction check
---> Package ModemManager.x86_64 0:1.6.0-2.el7 will be updated
......此处略......
---> Package yum-rhn-plugin.noarch 0:2.0.1-10.el7 will be installed
--> Running transaction check
---> Package libbytesize.x86_64 0:1.2-1.el7 will be installed
---> Package python2-pytoml.noarch 0:0.1.18-1.el7 will be installed
---> Package volume_key-libs.x86_64 0:0.3.9-8.el7 will be installed
--> Processing Conflict: initscripts-9.49.41-1.el7_5.1.x86_64 conflicts redhat-release < 7.5-0.11
--> Finished Dependency Resolution
Error: initscripts conflicts with redhat-release-server-7.4-18.el7.x86_64
You could try using --skip-broken to work around the problem
** Found 2 pre-existing rpmdb problem(s), 'yum check' output follows:
PackageKit-1.1.5-1.el7.centos.x86_64 has missing requires of PackageKit-backend
rhn-check-2.0.2-17.el7.noarch has missing requires of yum-rhn-plugin >= ('0', '1.6.4', '1')
[root@liaogx ~]#</code></pre>
<p>如果报如下错误</p>
<blockquote>Error: initscripts conflicts with redhat-release-server-7.4-18.el7.x86_64</blockquote>
<p>这是更新软件包是与原版本冲突造成的,有两种解决办法</p>
<ul>
<li>通过关键字initscritps排除冲突:<code>yum update --exclude=kernel* --exclude=centos-release* --exclude=initscripts*</code>
</li>
<li>删除冲突包:<code>rpm -e redhat-release-server-7.4-18.el7.x86_64 --nodeps</code>
</li>
</ul>
<p>这里使用第二种方法,把冲突的包干掉</p>
<pre><code class="bash">[root@liaogx ~]# rpm -e redhat-release-server-7.4-18.el7.x86_64 --nodeps
warning: file /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release: remove failed: No such file or directory
warning: file /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-rhx: remove failed: No such file or directory
warning: file /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-release: remove failed: No such file or directory
warning: file /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-legacy-former: remove failed: No such file or directory
warning: file /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-beta: remove failed: No such file or directory
[root@liaogx ~]#</code></pre>
<h3>Step4 更新系统</h3>
<p>小白从入门到跑路必会,<code>sudo yum -y update</code>,老鸟都懂。</p>
<pre><code class="bash">[root@liaogx ~]# yum -y update
......此处省略10分钟......
Complete!
[root@liaogx ~]#</code></pre>
<p>更新成功 ^_^</p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
【连载】Django入门到实战(一)
https://segmentfault.com/a/1190000016373934
2018-09-12T18:00:42+08:00
2018-09-12T18:00:42+08:00
寸土币争
https://segmentfault.com/u/liaogx
27
<h2>一、项目目录结构介绍</h2>
<p><img src="/img/remote/1460000016373937" alt="" title=""></p>
<p><code>manager.py</code> 与项目进行交互的命令行工具集的入口(项目管理器)</p>
<p><code>MyDjango</code> 目录:项目容器,包含项目的基本配置,目录名称不建议修改</p>
<p><code>__init__.py</code> Python中声明模块的文件,内容默认为空</p>
<p><code>settings.py</code> 项目的总配置文件,包含数据库、Web应用、时间等各种配置</p>
<p><code>urls.py</code> URL配置文件,Django项目中所有地址(页面)都需要我们自己去配置其URL</p>
<p><code>wsgi.py</code> WSGI(Python Web Server Gateway Interface)Python服务器网关接口,Python应用与Web服务器之间的接口</p>
<p><code>mytest</code>目录:开发者创建的应用</p>
<p>命令行:<code>python manage.py startapp mytest</code>(使用命令行创建应用时需要手动将应用名添加到settings.py中的<code>INSTALLED_APPS</code>里,应用名不能与Python中模块名相同)</p>
<p>Django服务器启动命令:<code>python manage.py runserver [端口号]</code></p>
<h2>二、应用目录结构介绍</h2>
<p><img src="/img/remote/1460000016373938" alt="" title=""></p>
<p><code>migrations</code> 数据移植(迁移)模块</p>
<p><code>__init__.py</code> Python中声明模块的文件,内容默认为空</p>
<p><code>admin.py</code> 应用的后台管理系统的配置</p>
<p><code>apps.py</code> 应用的一些配置,Django-1.9以后自动生成</p>
<p><code>models.py</code> 数据模型,使用ORM框架,类似于MVC结构中的Models(模型)</p>
<p><code>tests.py</code> 自动化测试模块,Django提供了自动化测试功能,在这里编写测试脚本(语句)</p>
<p><code>views.py</code> 执行响应代码和逻辑处理的主要模块,包含项目中的大部分代码</p>
<h2>三、响应页面示例</h2>
<p>编辑<code>views.py</code><br><img src="/img/remote/1460000016373939" alt="" title=""></p>
<p>每个响应对应一个函数,函数必须返回一个响应,函数必须存在一个参数,一般约定为request,每一个响应(函数)对应一个URL</p>
<p>编辑<code>urls.py</code><br><img src="/img/remote/1460000016373940" alt="" title=""></p>
<p>每个URL都以url的形式写出来,url函数放在urlpatterns列表中,url函数三个参数:URL(正则)、对应的方法、名称</p>
<h2>四、URL配置</h2>
<p>在根<code>urls.py</code>中引入include;在APP目录下创建<code>urls.py</code>文件,格式与<code>urls.py</code>相同;根<code>urls.py</code>中url函数第二个参数改为<code>include('blog.urls')</code></p>
<p>注意事项:根<code>urls.py</code>针对APP配置的URL名称,是该APP所有URL的总路径; 配置URL时注意正则表达式结尾符<code>$和/</code><br><img src="/img/remote/1460000016373941" alt="" title=""></p>
<h2>五、Templates介绍</h2>
<p>定义:使用了Django模板语言(<code>Django Template Language, DTL</code>)的HTML文件,也可以使用第三方模板(如<code>Jinja2</code>)</p>
<h3>5.1 使用步骤</h3>
<ul>
<li>在APP的根目录下创建名叫<code>Templates</code>的目录</li>
<li>在该目录下创建HTML文件</li>
<li>在<code>views.py</code>中返回<code>render()</code>
</li>
</ul>
<h3>5.2 DTL初步使用</h3>
<p><code>render()</code>函数中支持一个dict类型参数,该字典是后台传递到模板的参数,键为参数名,在模板中使用<strong>{{ 参数名 }}</strong>来直接使用</p>
<h3>5.3 Django查找Templates</h3>
<p>Django按照INSTALLED_APPS中的添加顺序查找Templates,不同APP下Templates目录中的同名.html文件会造成冲突</p>
<p>解决Templates冲突方案:在APP的<code>Templates</code>目录下创建以APP名为名称的目录,将html文件放入新创建的目录下</p>
<h2>六、Models介绍</h2>
<p>Django中的Models通常是一个Model对应数据库的一张数据表,Django中的Models以类的形式表现,它包含了一些基本字段以及数据的一些行为</p>
<p>ORM(<code>Object-Relational Mapping</code>, 对象关系映射):实现了对象和数据库之间的映射,隐藏了数据访问的细节,不需要编写SQL语句</p>
<h3>6.1 编写Models步骤</h3>
<ul>
<li>在APP根目录下创建<code>models.py</code>,并引入models模块</li>
<li>创建类,继承<code>models.Model</code>,该类即是一张数据表</li>
<li>在类中创建字段,字段即类里面的属性(变量)</li>
</ul>
<p><code>attr = models.CharField(max_length = 64)</code> <a href="https://link.segmentfault.com/?enc=b7%2B2an7XC4Lj1g%2FJccw8LA%3D%3D.8EcxMdA4%2FwFhnkpCGfagDd7iHFNAsKXsdMBx2eyxc6HIbR7trH5BNCeBUxezGvF8sDB%2F%2FRr%2B3IdpkvMI7Q4I2A%3D%3D" rel="nofollow">更多关于类的字段以及可选参数</a><br><img src="/img/remote/1460000016373942" alt="" title=""></p>
<h3>6.2 生成数据表:</h3>
<p>命令行中进入<code>manage.p</code>同级目录执行<code>python manage.py makemigrations app_name(可选)</code>,再执行<code>python manage.py migrate</code><br><img src="/img/remote/1460000016373943" alt="" title=""></p>
<h3>6.3 查看生成的数据表</h3>
<p>Django会自动在<code>app/migrations/</code>目录下生成移植文件,执行<code>python manage.py sqlmigrate </code>应用名 文件id 查看SQL语句</p>
<p>默认<code>sqlite3</code>的数据库在项目根目录 下<code>db.sqlite3</code></p>
<p><img src="/img/remote/1460000016374238" alt="" title=""></p>
<h3>6.4 前端页面呈现数据</h3>
<p><code>views.py</code>中<code>import models</code></p>
<p><code>article = models.Article.objects.get(pk=1)</code></p>
<p><code>render(request, page, {'article' : article})</code></p>
<p>模板可直接使用对象以及对象的"."操作,如<code>{{ article.title }}</code></p>
<h2>七、Admin介绍</h2>
<p>Admin是Django自带的一个功能强大的自动化数据管理界面,被授权的用户可直接在Admin中管理数据库,Django提供了许多针对Admin的定制功能</p>
<h3>7.1 配置Admin</h3>
<p>创建超级用户:<code>python manage.py createsuperuser</code></p>
<p>后台登录地址:<a href="https://link.segmentfault.com/?enc=Bef3wgFBzH7zk60IxcyuRA%3D%3D.DNPy6uAXZqF38UrQWijGtXY%2BRyhbjm7aBWXMT2mWQyY%3D" rel="nofollow">http://127.0.0.1</a>:8000/admin/</p>
<p>更改语言为中文:修改settings.py中<code>LANGUAGE_CODE = 'zh_Hans'</code></p>
<h3>7.2配置应用</h3>
<p>在应用下<code>admin.py</code>中引入自身的models模块(或里面的模型类)</p>
<p>编辑<code>admin.py: admin.site.register(models.Article)</code></p>
<h3>7.3 修改数据默认显示名称</h3>
<p>在<code>Article</code>类下添加一个方法</p>
<p>根据Python版本选择<code>__str__(self)</code>或<code>__unicode__(self)</code>, <code>return self.title</code></p>
<h2>八、Templates过滤器</h2>
<p>写在模板中,属于Django模板语言,可以修改模板中的变量从而显示不同的内容</p>
<p>使用方法:<code>{{ value | filter }}, 如{{ list_nums | length }}</code></p>
<p>过滤器可叠加:<code>{{ value | filter1 | filter2 | … }}</code></p>
<h2>九、Django Shell</h2>
<p>Python的交互式命令行程序,它自动引入了我们的项目环境</p>
<p>使用方法:<code>python manage.py shell</code><br><img src="/img/remote/1460000016373944" alt="" title=""></p>
<p>作用:进行调试,测试一些未知方法<br><img src="/img/remote/1460000016373945" alt="" title=""></p>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
[译]区块链技术全解析入门版
https://segmentfault.com/a/1190000016282809
2018-09-05T18:07:30+08:00
2018-09-05T18:07:30+08:00
寸土币争
https://segmentfault.com/u/liaogx
51
<blockquote>原文链接:<a href="https://link.segmentfault.com/?enc=NfQdR5V%2F2VoUMwJqYLtbmg%3D%3D.LzEuhKdGIn4Fw5wmkhNlStYrYT6fun%2F5g9aL3BGgBuSWfrPoPadHU6jFJT%2By7xTR" rel="nofollow">https://www.guru99.com/blockc...</a>
</blockquote>
<h3>一、什么是区块链?</h3>
<p>简而言之,区块链就是由许多包含信息的区块组成的链条。区块链技术通过给数字信息标记<code>时间戳</code>,使其无法<strong>回溯或篡改</strong>。区块链不需要银行或政府第三方机构的参与,用于金钱、产权、合同等的安全交易,当数据记录到区块链上后,几乎不可更改。</p>
<p>区块链是一种软件协议(类似于email使用的<code>SMTP</code>),但区块链必须运行在互联网之上,由于对其它技术的影响,因此也被成为<em>元技术</em>。区块链由数据库、软件应用、互相连接的计算机等部分组成。</p>
<p>区块链有时候被用于指比特币区块链,以太坊区块链,或其它虚拟货币、数字代币,但通常情况下是指<code>分布式账本</code>。</p>
<h3>二、区块链不是比特币!</h3>
<p><img src="/img/remote/1460000016285707" alt="img" title="img"></p>
<ul>
<li>区块链不是比特币,是比特币使用了区块链技术</li>
<li>比特币是数字代币,区块链是跟踪记录数字代币拥有者的<code>账本</code>
</li>
<li>没有区块链就没有比特币,但是没有比特币照样能有区块链</li>
</ul>
<h3>三、区块链的结构</h3>
<p>接下来,我们通过理解区块链的组成部分来学习它的结构</p>
<h4>3.1 什么是区块?</h4>
<p><img src="/img/remote/1460000016285708" alt="img" title="img"></p>
<p>区块链是包含信息的区块组成的链条,存储在区块中的数据取决于区块链的类型。例如,一个比特币区块含有发送者、接收者、交易的比特币数量信息。</p>
<p><img src="/img/remote/1460000016285709" alt="img" title="img"></p>
<p>链上的第一个区块被称为<code>创世区块</code>,其后的每一个区块都与前一个区块相连接。</p>
<h4>3.2 理解SHA256 - Hash</h4>
<p>每一个区块都有一个独一无二的<code>哈希(Hash)值</code>,可以理解成一个指纹,用于鉴定区块及其中所有信息的唯一性。所以当区块创建之后,区块中任何信息的更改都会造成哈希值发生改变。</p>
<p><img src="/img/remote/1460000016285710" alt="img" title="img"></p>
<p>因此,当你想检测各区块中信息是否发生改变时,哈希值是非常有用的。如果区块的哈希值改变,那就不是原来的区块了。每一个区块都含有:</p>
<ul>
<li>数据</li>
<li>Hash值</li>
<li>上一个区块的Hash值</li>
</ul>
<p>举例如下,假设有一个三个区块的区块链,第一个区块没有上一个区块,即<code>创世区块</code>,第二次区块含有第一个区块的哈希值,第三个区块含有第二个区块的哈希值。</p>
<p><img src="/img/remote/1460000016285711" alt="img" title="img"></p>
<p>因此,除<code>创世区块</code>外,所有区块均含有上一个区块的哈希值,这是保证区块链安全的关键技术,下面将讲解它的工作原理。</p>
<p>假设攻击者可以更改区块2中的数据,区块2的哈希值对应发生改变,但是区块3依然包含原区块2哈希值,这会造成区块3以及所有后续区块失效,因为没有上一个区块正确的哈希值。</p>
<p><img src="/img/remote/1460000016285712" alt="img" title="img"></p>
<p>因此,更改一个区块会使得后续所有区块都失效。</p>
<h4>3.3 工作量证明</h4>
<p>哈希是防止篡改的良好机制,但如今高速计算机每秒钟能计算出成千上万个哈希值,攻击者在几分钟之内就能篡改一个区块,然后重新计算所有区块的哈希值使得整个区块链失效。</p>
<p>为了避免这个问题,区块链使用了<code>作量证明</code>的概念,一种降低区块创建速度的机制。工作量证明是一个计算问题,需要花费一定资源来解决,而验证这个问题的答案所需要的时间比解决起来花费的资源要少得多。</p>
<p>在比特币网络中,添加一个新的区块到区块链上需要花大概10分钟计算出所需的工作量。在上例中,如果攻击者更改了区块2中的数据,就需要花10分钟计算出区块2的工作量,然后才能更改区块3以及后续区块中的数据。</p>
<p><img src="/img/remote/1460000016285713" alt="img" title="img"></p>
<p>工作量证明机制让篡改区块变得非常困难,篡改链上一个区块则需要计算后续所有区块的工作量,因此,哈希计算和工作量证明机制保证了区块链的安全。</p>
<h4>3.4 分布式P2P网络</h4>
<p>另外,还有一种保证区块链安全的方法,那就是分布式。区块链使用了分布式的点对点网络,所有人都可以加入,而不是通过中心化的实体来管理。当有人加入到这个网络中时,他会获得区块链的完整副本,每一台计算机称之为一个节点。</p>
<p><img src="/img/remote/1460000016285714" alt="img" title="img"></p>
<p>我们来看下,如果有人创建了新的区块会发生什么。新的区块会被发送给网络中的所有人,每个节点都需要验证这个区块,确保它没有被篡改,验证完成之后,每个节点将此区块添加到各自的区块链上。</p>
<p><img src="/img/remote/1460000016285715" alt="img" title="img"></p>
<p>网络中的所有节点有了<code>共识机制</code>,他们对区块是否有效达成一致,节点会拒绝被篡改过的区块。</p>
<p>因此,如果想成功的篡改区块链:</p>
<ol>
<li>需要篡改链上的所有区块</li>
<li>重新计算所有区块的工作量</li>
<li>控制区块链网络中至少50%以上的<code>算力</code>
</li>
</ol>
<p>以上都完成之后,篡改的区块才能被网络中其它节点接受,这几乎是一项不可能完成的任务,所以区块链是相当安全的。</p>
<h3>四、区块链交易是如何运行的?</h3>
<p><img src="/img/remote/1460000016285716" alt="img" title="img"></p>
<p><strong>步骤一</strong> 有人发起一笔交易,该交易可能涉及加密货币,合同,记录或其他信息;</p>
<p><strong>步骤二</strong> 在节点的帮助下,该交易被广播到P2P网络中;</p>
<p><strong>步骤三</strong> 借助已知的算法,网络中节点验证交易的合法性和用户状态;</p>
<p><strong>步骤四</strong> 交易一旦完成,新的区块被添加到区块链上,从此永久不可篡改。</p>
<h3>五、为什么需要区块链技术?</h3>
<p>以下列举了区块链技术如此受欢迎的原因</p>
<p><strong>弹性恢复</strong> 区块链通常是冗余型的架构,即便在系统遭受大规模攻击的情况下,多数节点依然可用。</p>
<p><strong>高效率</strong> 在金融行业中,区块链由于不需要冗长的验证,结算和清算过程,可以通过更快地结算交易来发挥重要作用,因为一个对数据达成一致的共享账本版本对所有持有者可用。</p>
<p><strong>高可靠性</strong> 区块链证明并验证相关方的身份,移除了重复的记录,降低费率并加速交易。</p>
<p><strong>交易不可篡改</strong> 通过按时间顺序注册交易,区块链证明了所有操作的不可更改性,这意味着任何新的区块被添加到区块链账本后,都不能被删除或更改。</p>
<p><strong>阻止欺诈</strong> 共享信息和共识的概念可防止由于欺诈或贪污造成的可能损失。在以物流为基础的行业中,区块链作为一种监督机制,可以降低成本。</p>
<p><strong>安全性</strong> 攻击传统数据库会直接导致特定目标奔溃。有了分布式账本技术,由于任何节点都有原区块链的完整拷贝,即便大部分节点宕机,系统依然可用。</p>
<p><strong>透明性</strong> 公有链的更改会对所有人可见,这提供了更高的透明度,并且所有交易都是不可篡改的。</p>
<p><strong>协作性</strong> 每个节点如何交换区块链信息都有标准规则,由此来保证所有交易的合法性,合法的交易会被逐笔添加到区块链上。</p>
<p><strong>去中心化</strong> 不需要第三方中介的介入,允许参与方之间直接交易。</p>
<h3>六、区块链的版本</h3>
<p><img src="/img/remote/1460000016285717" alt="img" title="img"></p>
<p><strong>区块链 1.0:货币</strong></p>
<p><code>DLT(分布式账本技术)</code>的使用产生了第一个也是最明显的应用:货币。它允许基于区块链技术的金融交易,被用于货币和支付。比特币便是这一领域最突出的例子。</p>
<p><strong>区块链 2.0:智能合约</strong></p>
<p>区块链2.0时代的核心概念是<code>智能合约</code>,即“存活”在区块链上的小型计算机程序,它是能自动执行的自由计算机程序,通过检查预先定义好的条件,如简化、验证、实施,用于替代传统的合同。</p>
<p><strong>区块链 3.0 Dapps</strong></p>
<p>Dapp是<code>Decentralized application</code>的缩写,即运行在去中心化的点对点网络中的后端代码。和传统的互联网App一样,Dapp也有前端代码和用户界面,可使用任何能与后端交互的编程语言实现。</p>
<h3>七、区块链的种类</h3>
<p><strong>公有链</strong></p>
<p>在公有链中,账本对网络中所有人可见,它允许所有人验证区块,将包含交易信息的区块添加到区块链中。公共网络鼓励人们加入并自由使用,任何人都能使用公共区块链网络。</p>
<p><strong>私有链</strong></p>
<p>私有链存在于某一机构中,它只允许该机构特定的人验证和添加交易区块,但允许网络中所有人查看。</p>
<p><img src="/img/remote/1460000016285718" alt="img" title="img"></p>
<p><strong>联盟链</strong></p>
<p>对于联盟链,它只允许组织中的机构成员验证和添加交易区块,账本可以公开或开放给部分组员。联盟链用于多个机构之间,仅被已授权的节点控制。</p>
<h3>八、区块链的应用场景</h3>
<p>如下表所示,区块链技术在许多领域被广泛使用</p>
<table>
<thead><tr>
<th>行业/领域</th>
<th>使用场景</th>
</tr></thead>
<tbody>
<tr>
<td>市场</td>
<td>1. 账单数据监控和传输<br>2. 供应链网络中的配额管理</td>
</tr>
<tr>
<td>政府</td>
<td>1. 跨国个性化治理服务<br>2. 投票选举,P2P债券<br>3. 文件与合同的数字化,所有权的转让证明<br>4. 登记与鉴定<br>5. 远程律师服务<br>6. 知识产权登记与汇率<br>7. 税收收据公证服务和文件登记</td>
</tr>
<tr>
<td>物联网</td>
<td>1. 农业与无人机传感网络<br>2. 智能家居网络<br>3. 综合型智慧城市<br>4. 智能家庭传感器<br>5. 无人驾驶汽车<br>6. 个性化机器人,机器人部件<br>7. 个性化无人机<br>8. 数字助理</td>
</tr>
<tr>
<td>健康</td>
<td>1. 健康数据管理<br>2. 通用EMR健康数据库<br>3. 量化生活数据共享<br>4. 健康大数据流分析<br>5. 健康代币<br>6. 个人发展合约</td>
</tr>
<tr>
<td>科学与艺术</td>
<td>1. 超级计算<br>2. 人群分析<br>3. P2P资源<br>4. 数字思维健康服务</td>
</tr>
<tr>
<td>金融与会计</td>
<td>1. 数字货币支付<br>2. 付款和汇款<br>3. 使用区块链网络的去中心化资本市场<br>4. 部门间会计<br>5. 清算和交易及衍生品<br>6. 簿记</td>
</tr>
</tbody>
</table>
<h3>九、区块链的重要实际使用案例</h3>
<h4>9.1 迪拜 - 智慧城市</h4>
<p>聪明的迪拜政府在2016年引入了区块链战略,使用区块链技术,企业家和开发人员将能够与投资者和领先公司建立联系,目标是建设有利于各行各业发展的区块链基础系统,使迪拜成为世界上最幸福的城市。</p>
<h4>9.2 提升客户留存率</h4>
<p>这是一个靠谱的项目,基于区块链技术的<code>CRaaS(客户留存即服务)</code>,它基于为相关网络附属的业务生成代币。在这个系统中,区块链上的交易是即时的,它可以存储在用户手机的数字投资组合中或通过浏览器访问。</p>
<h4>9.3 区块链用于人道主义援助</h4>
<p>2017年1月,联合国世界粮食计划启动了一个名为人道主义援助的项目,该项目是在巴基斯坦信德的偏远地区开发的。通过使用区块链技术,被援助人员接收到的钱,食物和所有类型的交易都注册在区块链上,以此确保了过程的安全性和透明度。</p>
<h3>十、加密货币比特币:最流行的区块链应用</h3>
<p><img src="/img/remote/1460000016285719" alt="img" title="img"></p>
<p><strong>什么是加密货币?</strong></p>
<p>和传统货币美元一样,加密货币是交易的媒介,但它旨在通过某些密码学原理所实现的过程来交换数字信息。加密货币是一种数字货币,被视为替代货币和虚拟货币的一种。</p>
<p>加密货币是一种基于数字加密技术的承载工具,货币持有人拥有所有权,没有其他记录保留所有者的身份。1998年,魏岱发表了“B-Money”,这是一个匿名的分布式电子现金系统。</p>
<p><strong>什么是比特币?</strong></p>
<p>比特币是由一个化名<code>中本聪</code>的人在2009年推出的,是一种不被任何中心机构或银行管理的点对点技术。如今,发行比特币和管理交易都在网络上集中进行,比特币也是目前世界上主流的加密货币。比特币是开源和为公众设计的,没人具有控制权,发行量总共2100万枚,目前比特币市值为120亿美元。</p>
<p>任何人都可以使用比特币而无需支付任何手续费,当你交易比特币时,发送者和接收者直接交易而不需要第三方参与。</p>
<p><strong>区块链和比特币</strong></p>
<p>比特币是使用了区块链技术的数字代币,区块链是跟踪记录代币持有者的账本。没有区块链就没有比特币,而没有比特币照样能有区块链。其它主流的加货币:</p>
<ul>
<li>以太坊</li>
<li>比特现金</li>
<li>瑞波币</li>
<li>莱特币</li>
</ul>
<h3>十一、区块链 vs 分布式数据库</h3>
<p><img src="/img/remote/1460000016285720" alt="img" title="img"></p>
<table>
<thead><tr>
<th>比较参数</th>
<th>区块链</th>
<th>分布式数据库</th>
</tr></thead>
<tbody>
<tr>
<td>操作性</td>
<td>插入</td>
<td>增删改查</td>
</tr>
<tr>
<td>冗余性</td>
<td>所有节点的完整拷贝</td>
<td>主从复制或多主备</td>
</tr>
<tr>
<td>共识</td>
<td>大部分节点对交易结果达成一致</td>
<td>分布式交易分提交和确认两步进行</td>
</tr>
<tr>
<td>有效性</td>
<td>全局规则在整个区块链系统上实施</td>
<td>仅提供本地完整性约束</td>
</tr>
<tr>
<td>有无中介</td>
<td>无</td>
<td>必须有</td>
</tr>
<tr>
<td>机密性</td>
<td>完全保密</td>
<td>不完全保密</td>
</tr>
<tr>
<td>稳健性</td>
<td>完全稳健</td>
<td>不完全稳健</td>
</tr>
</tbody>
</table>
<h3>十二、关于区块链的误解</h3>
<table>
<thead><tr>
<th>误解</th>
<th>正解</th>
</tr></thead>
<tbody>
<tr>
<td>能解决所有问题</td>
<td>只是一个分布式数据库</td>
</tr>
<tr>
<td>无需信任的技术</td>
<td>可以改变并传递信用</td>
</tr>
<tr>
<td>绝对安全</td>
<td>重点是完整性和机密性</td>
</tr>
<tr>
<td>智能合约一定合法</td>
<td>只执行合法合同中的一部分</td>
</tr>
<tr>
<td>绝对不可变</td>
<td>从概率的角度讲不可变</td>
</tr>
<tr>
<td>无需浪费电力</td>
<td>需要,但新兴的区块链会更节能</td>
</tr>
<tr>
<td>本质上不可售卖</td>
<td>是的,但新兴的区块链会提供更好的扩展性</td>
</tr>
</tbody>
</table>
<h3>十三、区块链技术的局限性</h3>
<p><strong>交易费过高</strong> 节点会优先完成奖励更高的交易,这是由商业中供需关系原则决定的</p>
<p><strong>交易确认慢</strong> 由于节点会优先完成奖励更高的交易,交易量会积压</p>
<p><strong>账本太小</strong> 数据量过大是获取区块链的完整副本是不可能的,这可能会影响不变性,共识机制等</p>
<p><strong>交易成本,网络速度</strong> 在最初几年被吹捧为“几乎免费”之后,比特币的交易成本变得相当高</p>
<p><strong>错误风险</strong> 只要涉及人为因素,总会存在错误风险。区块链用作数据库,则所有传入数据必须具有高质量。虽然人为干预可以迅速解决错误</p>
<p><strong>资源浪费</strong> 所有运行在区块链上的节点必须达成共识,这使得宕机时间非常短暂,存储在区块链上的数据永久不可篡改。但是这些都是资源浪费,因为每个节点为达成共识不断重复同一任务。</p>
<h3>总结</h3>
<ul>
<li>区块链是由包含信息的区块组成的链条</li>
<li>区块链不是比特币,是比特币使用了区块链技术</li>
<li>所有区块都有唯一的哈希值</li>
<li>每一个区块都包含上一个区块的哈希值</li>
<li>向区块链(这里指比特币)中添加区块需要工作量证明</li>
<li>区块链的数据库分布在多个节点,不是中心化的</li>
<li>区块链技术具有弹性恢复、去中心化、高效率、高可靠和交易不可篡改的特点。</li>
<li>区块链的三个版本,区块链1.0:货币,区块链2.0:智能合约,区块链3.0:去中心化应用。</li>
<li>区块链的三种类型:公有链、私有链、联盟链</li>
<li>使用区块链技术的不好之处包括交易费过高,交易确认慢,账本太小,错误风险</li>
<li>区块链的重要实际使用案例有:迪拜智慧城市,提升客户留存率,联合国人道主义救援项目</li>
<li>比特币使用了区块链技术,不被任何中心机构和银行控制</li>
</ul>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>
Python基础——数据类型
https://segmentfault.com/a/1190000015759466
2018-07-25T11:30:20+08:00
2018-07-25T11:30:20+08:00
寸土币争
https://segmentfault.com/u/liaogx
1
<p><strong>本文讲解Python常用7种数据类型:int, float, str, list, set, dict. 通过剖析源码弄清楚每一种数据类型所有的内置函数,理解每一个函数的参数、返回值、使用场景是什么。</strong></p>
<h2><strong>一、整型 int</strong></h2>
<p>Python3.6源码解析</p>
<pre><code class="python">class int(object):
"""
int(x=0) -> integer
int(x, base=10) -> integer
Convert a number or string to an integer, or return 0 if no arguments
are given. If x is a number, return x.__int__(). For floating point
numbers, this truncates towards zero.
If x is not a number or if base is given, then x must be a string,
bytes, or bytearray instance representing an integer literal in the
given base. The literal can be preceded by '+' or '-' and be surrounded
by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
Base 0 means to interpret the base from the string as an integer literal.
>>> int('0b100', base=0)
4
"""
def bit_length(self): # real signature unknown; restored from __doc__
"""
int.bit_length() -> int
Number of bits necessary to represent self in binary.
>>> bin(37)
'0b100101'
>>> (37).bit_length()
6
"""
return 0
def conjugate(self, *args, **kwargs): # real signature unknown
""" Returns self, the complex conjugate of any int. """
pass
@classmethod # known case
def from_bytes(cls, bytes, byteorder, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__
"""
int.from_bytes(bytes, byteorder, *, signed=False) -> int
Return the integer represented by the given array of bytes.
The bytes argument must be a bytes-like object (e.g. bytes or bytearray).
The byteorder argument determines the byte order used to represent the
integer. If byteorder is 'big', the most significant byte is at the
beginning of the byte array. If byteorder is 'little', the most
significant byte is at the end of the byte array. To request the native
byte order of the host system, use `sys.byteorder' as the byte order value.
The signed keyword-only argument indicates whether two's complement is
used to represent the integer.
"""
pass
def to_bytes(self, length, byteorder, *args, **kwargs): # real signature unknown; NOTE: unreliably restored from __doc__
"""
int.to_bytes(length, byteorder, *, signed=False) -> bytes
Return an array of bytes representing an integer.
The integer is represented using length bytes. An OverflowError is
raised if the integer is not representable with the given number of
bytes.
The byteorder argument determines the byte order used to represent the
integer. If byteorder is 'big', the most significant byte is at the
beginning of the byte array. If byteorder is 'little', the most
significant byte is at the end of the byte array. To request the native
byte order of the host system, use `sys.byteorder' as the byte order value.
The signed keyword-only argument determines whether two's complement is
used to represent the integer. If signed is False and a negative integer
is given, an OverflowError is raised.
"""
pass</code></pre>
<ul>
<li>bit_length: 返回二进制数据所占的bit位数</li>
<li>conjugate: 获取复数的共轭复数</li>
<li>denominator:</li>
<li>
<a href="https://link.segmentfault.com/?enc=Lud8WQEKIdgmkcPh%2Fh8MtA%3D%3D.z07siZiEmSPFwnYJdFsj6NnYMsdUZWrN5xxsSTLvQx63DoRMoM%2F9AaEY%2B64XGzBXyBzk83hWrb1KWtx1auPLTAZwUjVX1tF4mjSEqDWbm1Tey%2FkSVDhvXIymetNgqne3%2FTKvkbOTxEij3AO4jIjHOw%3D%3D" rel="nofollow">from_bytes</a>: 将bytes解析为整数</li>
<li>imag:获取复数的虚部</li>
<li>numerator:</li>
<li>real: 获取复数的实部</li>
<li>
<a href="https://link.segmentfault.com/?enc=tE0OfDF6bAKTxwA6oFXw8Q%3D%3D.ZBjso5tbyTGhF%2BMs8T4yNFHd9YyFm30VlQIQ82YcKIVKxxbzRNQhVRpQgX%2FB7suTIWY5u%2B9zRrPc7TcEkZx3GRAea3H7lQs%2Bw%2F7KdoTM6bICZn5cB43L4eNqdcoWK3fo6MuA%2BoWKT20dz9kIJn%2FQwg%3D%3D" rel="nofollow">to_bytes</a>: 将一个大整数转换为一个字节字符串</li>
</ul>
<h2><strong>二、浮点型 float</strong></h2>
<p>Python3.6源码解析</p>
<pre><code class="python">class float(object):
"""
float(x) -> floating point number
Convert a string or number to a floating point number, if possible.
"""
def as_integer_ratio(self): # real signature unknown; restored from __doc__
"""
float.as_integer_ratio() -> (int, int)
Return a pair of integers, whose ratio is exactly equal to the original
float and with a positive denominator.
Raise OverflowError on infinities and a ValueError on NaNs.
>>> (10.0).as_integer_ratio()
(10, 1)
>>> (0.0).as_integer_ratio()
(0, 1)
>>> (-.25).as_integer_ratio()
(-1, 4)
"""
pass
def conjugate(self, *args, **kwargs): # real signature unknown
""" Return self, the complex conjugate of any float. """
pass
@staticmethod # known case
def fromhex(string): # real signature unknown; restored from __doc__
"""
float.fromhex(string) -> float
Create a floating-point number from a hexadecimal string.
>>> float.fromhex('0x1.ffffp10')
2047.984375
>>> float.fromhex('-0x1p-1074')
-5e-324
"""
return 0.0
def hex(self): # real signature unknown; restored from __doc__
"""
float.hex() -> string
Return a hexadecimal representation of a floating-point number.
>>> (-0.1).hex()
'-0x1.999999999999ap-4'
>>> 3.14159.hex()
'0x1.921f9f01b866ep+1'
"""
return ""
def is_integer(self, *args, **kwargs): # real signature unknown
""" Return True if the float is an integer. """
pass
</code></pre>
<ul>
<li>as_integer_ratio:</li>
<li>conjugate:</li>
<li>fromhex:</li>
<li>hex:</li>
<li>imag:</li>
<li>is_integer:</li>
<li>real:</li>
</ul>
<h2><strong>三、字符串 str</strong></h2>
<p>Python3.6源码解析</p>
<pre><code class="python">class str(object):
"""
str(object='') -> str
str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or
errors is specified, then the object must expose a data buffer
that will be decoded using the given encoding and error handler.
Otherwise, returns the result of object.__str__() (if defined)
or repr(object).
encoding defaults to sys.getdefaultencoding().
errors defaults to 'strict'.
"""
def capitalize(self): # real signature unknown; restored from __doc__
"""
S.capitalize() -> str
Return a capitalized version of S, i.e. make the first character
have upper case and the rest lower case.
"""
return ""
def casefold(self): # real signature unknown; restored from __doc__
"""
S.casefold() -> str
Return a version of S suitable for caseless comparisons.
"""
return ""
def center(self, width, fillchar=None): # real signature unknown; restored from __doc__
"""
S.center(width[, fillchar]) -> str
Return S centered in a string of length width. Padding is
done using the specified fill character (default is a space)
"""
return ""
def count(self, sub, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.count(sub[, start[, end]]) -> int
Return the number of non-overlapping occurrences of substring sub in
string S[start:end]. Optional arguments start and end are
interpreted as in slice notation.
"""
return 0
def encode(self, encoding='utf-8', errors='strict'): # real signature unknown; restored from __doc__
"""
S.encode(encoding='utf-8', errors='strict') -> bytes
Encode S using the codec registered for encoding. Default encoding
is 'utf-8'. errors may be given to set a different error
handling scheme. Default is 'strict' meaning that encoding errors raise
a UnicodeEncodeError. Other possible values are 'ignore', 'replace' and
'xmlcharrefreplace' as well as any other name registered with
codecs.register_error that can handle UnicodeEncodeErrors.
"""
return b""
def endswith(self, suffix, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.endswith(suffix[, start[, end]]) -> bool
Return True if S ends with the specified suffix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
suffix can also be a tuple of strings to try.
"""
return False
def expandtabs(self, tabsize=8): # real signature unknown; restored from __doc__
"""
S.expandtabs(tabsize=8) -> str
Return a copy of S where all tab characters are expanded using spaces.
If tabsize is not given, a tab size of 8 characters is assumed.
"""
return ""
def find(self, sub, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.find(sub[, start[, end]]) -> int
Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
"""
return 0
def format(self, *args, **kwargs): # known special case of str.format
"""
S.format(*args, **kwargs) -> str
Return a formatted version of S, using substitutions from args and kwargs.
The substitutions are identified by braces ('{' and '}').
"""
pass
def format_map(self, mapping): # real signature unknown; restored from __doc__
"""
S.format_map(mapping) -> str
Return a formatted version of S, using substitutions from mapping.
The substitutions are identified by braces ('{' and '}').
"""
return ""
def index(self, sub, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.index(sub[, start[, end]]) -> int
Return the lowest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
"""
return 0
def isalnum(self): # real signature unknown; restored from __doc__
"""
S.isalnum() -> bool
Return True if all characters in S are alphanumeric
and there is at least one character in S, False otherwise.
"""
return False
def isalpha(self): # real signature unknown; restored from __doc__
"""
S.isalpha() -> bool
Return True if all characters in S are alphabetic
and there is at least one character in S, False otherwise.
"""
return False
def isdecimal(self): # real signature unknown; restored from __doc__
"""
S.isdecimal() -> bool
Return True if there are only decimal characters in S,
False otherwise.
"""
return False
def isdigit(self): # real signature unknown; restored from __doc__
"""
S.isdigit() -> bool
Return True if all characters in S are digits
and there is at least one character in S, False otherwise.
"""
return False
def isidentifier(self): # real signature unknown; restored from __doc__
"""
S.isidentifier() -> bool
Return True if S is a valid identifier according
to the language definition.
Use keyword.iskeyword() to test for reserved identifiers
such as "def" and "class".
"""
return False
def islower(self): # real signature unknown; restored from __doc__
"""
S.islower() -> bool
Return True if all cased characters in S are lowercase and there is
at least one cased character in S, False otherwise.
"""
return False
def isnumeric(self): # real signature unknown; restored from __doc__
"""
S.isnumeric() -> bool
Return True if there are only numeric characters in S,
False otherwise.
"""
return False
def isprintable(self): # real signature unknown; restored from __doc__
"""
S.isprintable() -> bool
Return True if all characters in S are considered
printable in repr() or S is empty, False otherwise.
"""
return False
def isspace(self): # real signature unknown; restored from __doc__
"""
S.isspace() -> bool
Return True if all characters in S are whitespace
and there is at least one character in S, False otherwise.
"""
return False
def istitle(self): # real signature unknown; restored from __doc__
"""
S.istitle() -> bool
Return True if S is a titlecased string and there is at least one
character in S, i.e. upper- and titlecase characters may only
follow uncased characters and lowercase characters only cased ones.
Return False otherwise.
"""
return False
def isupper(self): # real signature unknown; restored from __doc__
"""
S.isupper() -> bool
Return True if all cased characters in S are uppercase and there is
at least one cased character in S, False otherwise.
"""
return False
def join(self, iterable): # real signature unknown; restored from __doc__
"""
S.join(iterable) -> str
Return a string which is the concatenation of the strings in the
iterable. The separator between elements is S.
"""
return ""
def ljust(self, width, fillchar=None): # real signature unknown; restored from __doc__
"""
S.ljust(width[, fillchar]) -> str
Return S left-justified in a Unicode string of length width. Padding is
done using the specified fill character (default is a space).
"""
return ""
def lower(self): # real signature unknown; restored from __doc__
"""
S.lower() -> str
Return a copy of the string S converted to lowercase.
"""
return ""
def lstrip(self, chars=None): # real signature unknown; restored from __doc__
"""
S.lstrip([chars]) -> str
Return a copy of the string S with leading whitespace removed.
If chars is given and not None, remove characters in chars instead.
"""
return ""
def maketrans(self, *args, **kwargs): # real signature unknown
"""
Return a translation table usable for str.translate().
If there is only one argument, it must be a dictionary mapping Unicode
ordinals (integers) or characters to Unicode ordinals, strings or None.
Character keys will be then converted to ordinals.
If there are two arguments, they must be strings of equal length, and
in the resulting dictionary, each character in x will be mapped to the
character at the same position in y. If there is a third argument, it
must be a string, whose characters will be mapped to None in the result.
"""
pass
def partition(self, sep): # real signature unknown; restored from __doc__
"""
S.partition(sep) -> (head, sep, tail)
Search for the separator sep in S, and return the part before it,
the separator itself, and the part after it. If the separator is not
found, return S and two empty strings.
"""
pass
def replace(self, old, new, count=None): # real signature unknown; restored from __doc__
"""
S.replace(old, new[, count]) -> str
Return a copy of S with all occurrences of substring
old replaced by new. If the optional argument count is
given, only the first count occurrences are replaced.
"""
return ""
def rfind(self, sub, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.rfind(sub[, start[, end]]) -> int
Return the highest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Return -1 on failure.
"""
return 0
def rindex(self, sub, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.rindex(sub[, start[, end]]) -> int
Return the highest index in S where substring sub is found,
such that sub is contained within S[start:end]. Optional
arguments start and end are interpreted as in slice notation.
Raises ValueError when the substring is not found.
"""
return 0
def rjust(self, width, fillchar=None): # real signature unknown; restored from __doc__
"""
S.rjust(width[, fillchar]) -> str
Return S right-justified in a string of length width. Padding is
done using the specified fill character (default is a space).
"""
return ""
def rpartition(self, sep): # real signature unknown; restored from __doc__
"""
S.rpartition(sep) -> (head, sep, tail)
Search for the separator sep in S, starting at the end of S, and return
the part before it, the separator itself, and the part after it. If the
separator is not found, return two empty strings and S.
"""
pass
def rsplit(self, sep=None, maxsplit=-1): # real signature unknown; restored from __doc__
"""
S.rsplit(sep=None, maxsplit=-1) -> list of strings
Return a list of the words in S, using sep as the
delimiter string, starting at the end of the string and
working to the front. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified, any whitespace string
is a separator.
"""
return []
def rstrip(self, chars=None): # real signature unknown; restored from __doc__
"""
S.rstrip([chars]) -> str
Return a copy of the string S with trailing whitespace removed.
If chars is given and not None, remove characters in chars instead.
"""
return ""
def split(self, sep=None, maxsplit=-1): # real signature unknown; restored from __doc__
"""
S.split(sep=None, maxsplit=-1) -> list of strings
Return a list of the words in S, using sep as the
delimiter string. If maxsplit is given, at most maxsplit
splits are done. If sep is not specified or is None, any
whitespace string is a separator and empty strings are
removed from the result.
"""
return []
def splitlines(self, keepends=None): # real signature unknown; restored from __doc__
"""
S.splitlines([keepends]) -> list of strings
Return a list of the lines in S, breaking at line boundaries.
Line breaks are not included in the resulting list unless keepends
is given and true.
"""
return []
def startswith(self, prefix, start=None, end=None): # real signature unknown; restored from __doc__
"""
S.startswith(prefix[, start[, end]]) -> bool
Return True if S starts with the specified prefix, False otherwise.
With optional start, test S beginning at that position.
With optional end, stop comparing S at that position.
prefix can also be a tuple of strings to try.
"""
return False
def strip(self, chars=None): # real signature unknown; restored from __doc__
"""
S.strip([chars]) -> str
Return a copy of the string S with leading and trailing
whitespace removed.
If chars is given and not None, remove characters in chars instead.
"""
return ""
def swapcase(self): # real signature unknown; restored from __doc__
"""
S.swapcase() -> str
Return a copy of S with uppercase characters converted to lowercase
and vice versa.
"""
return ""
def title(self): # real signature unknown; restored from __doc__
"""
S.title() -> str
Return a titlecased version of S, i.e. words start with title case
characters, all remaining cased characters have lower case.
"""
return ""
def translate(self, table): # real signature unknown; restored from __doc__
"""
S.translate(table) -> str
Return a copy of the string S in which each character has been mapped
through the given translation table. The table must implement
lookup/indexing via __getitem__, for instance a dictionary or list,
mapping Unicode ordinals to Unicode ordinals, strings, or None. If
this operation raises LookupError, the character is left untouched.
Characters mapped to None are deleted.
"""
return ""
def upper(self): # real signature unknown; restored from __doc__
"""
S.upper() -> str
Return a copy of S converted to uppercase.
"""
return ""
def zfill(self, width): # real signature unknown; restored from __doc__
"""
S.zfill(width) -> str
Pad a numeric string S with zeros on the left, to fill a field
of the specified width. The string S is never truncated.
"""
return ""</code></pre>
<ul>
<li>capitalize:</li>
<li>casefold:</li>
<li>center:</li>
<li>count:</li>
<li>encode:</li>
<li>endswith:</li>
<li>expandtabs:</li>
<li>find:</li>
<li>format:</li>
<li>format_map:</li>
<li>index:</li>
<li>isalnum:</li>
<li>isalpha:</li>
<li>isdecimal:</li>
<li>isdigit:</li>
<li>isidentifier:</li>
<li>islower:</li>
<li>isnumeric:</li>
<li>isprintable:</li>
<li>isspace:</li>
<li>istitle:</li>
<li>isupper:</li>
<li>join:</li>
<li>ljust:</li>
<li>lower:</li>
<li>lstrip:</li>
<li>maketrans:</li>
<li>partition:</li>
<li>replace:</li>
<li>rfind:</li>
<li>rindex:</li>
<li>rjust:</li>
<li>rpartition:</li>
<li>rsplit:</li>
<li>rstrip:</li>
<li>split:</li>
<li>splitlines:</li>
<li>startswith:</li>
<li>strip:</li>
<li>swapcase:</li>
<li>title:</li>
<li>translate:</li>
<li>upper:</li>
<li>zfill:</li>
</ul>
<h2><strong>四、列表 list</strong></h2>
<p>Python3.6源码解析:</p>
<pre><code class="python">class list(object):
"""
list() -> new empty list
list(iterable) -> new list initialized from iterable's items
"""
def append(self, p_object): # real signature unknown; restored from __doc__
""" L.append(object) -> None -- append object to end """
pass
def clear(self): # real signature unknown; restored from __doc__
""" L.clear() -> None -- remove all items from L """
pass
def copy(self): # real signature unknown; restored from __doc__
""" L.copy() -> list -- a shallow copy of L """
return []
def count(self, value): # real signature unknown; restored from __doc__
""" L.count(value) -> integer -- return number of occurrences of value """
return 0
def extend(self, iterable): # real signature unknown; restored from __doc__
""" L.extend(iterable) -> None -- extend list by appending elements from the iterable """
pass
def index(self, value, start=None, stop=None): # real signature unknown; restored from __doc__
"""
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
"""
return 0
def insert(self, index, p_object): # real signature unknown; restored from __doc__
""" L.insert(index, object) -- insert object before index """
pass
def pop(self, index=None): # real signature unknown; restored from __doc__
"""
L.pop([index]) -> item -- remove and return item at index (default last).
Raises IndexError if list is empty or index is out of range.
"""
pass
def remove(self, value): # real signature unknown; restored from __doc__
"""
L.remove(value) -> None -- remove first occurrence of value.
Raises ValueError if the value is not present.
"""
pass
def reverse(self): # real signature unknown; restored from __doc__
""" L.reverse() -- reverse *IN PLACE* """
pass
def sort(self, key=None, reverse=False): # real signature unknown; restored from __doc__
""" L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE* """
pass</code></pre>
<p>列表的内置函数包括</p>
<ul>
<li>append:</li>
<li>clear:</li>
<li>copy:</li>
<li>count:</li>
<li>extend:</li>
<li>index:</li>
<li>insert:</li>
<li>pop:</li>
<li>remove:</li>
<li>reverse:</li>
<li>sort:</li>
</ul>
<h2><strong>五、元组 tuple</strong></h2>
<pre><code class="python">class tuple(object):
"""
tuple() -> empty tuple
tuple(iterable) -> tuple initialized from iterable's items
If the argument is a tuple, the return value is the same object.
"""
def count(self, value): # real signature unknown; restored from __doc__
""" T.count(value) -> integer -- return number of occurrences of value """
return 0
def index(self, value, start=None, stop=None): # real signature unknown; restored from __doc__
"""
T.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.
"""
return 0
</code></pre>
<ul>
<li>count:</li>
<li>index:</li>
</ul>
<h2><strong>六、字典 dict</strong></h2>
<p>Python3.6源码解析</p>
<pre><code class="python">class dict(object):
"""
dict() -> new empty dictionary
dict(mapping) -> new dictionary initialized from a mapping object's
(key, value) pairs
dict(iterable) -> new dictionary initialized as if via:
d = {}
for k, v in iterable:
d[k] = v
dict(**kwargs) -> new dictionary initialized with the name=value pairs
in the keyword argument list. For example: dict(one=1, two=2)
"""
def clear(self): # real signature unknown; restored from __doc__
""" D.clear() -> None. Remove all items from D. """
pass
def copy(self): # real signature unknown; restored from __doc__
""" D.copy() -> a shallow copy of D """
pass
@staticmethod # known case
def fromkeys(*args, **kwargs): # real signature unknown
""" Returns a new dict with keys from iterable and values equal to value. """
pass
def get(self, k, d=None): # real signature unknown; restored from __doc__
""" D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None. """
pass
def items(self): # real signature unknown; restored from __doc__
""" D.items() -> a set-like object providing a view on D's items """
pass
def keys(self): # real signature unknown; restored from __doc__
""" D.keys() -> a set-like object providing a view on D's keys """
pass
def pop(self, k, d=None): # real signature unknown; restored from __doc__
"""
D.pop(k[,d]) -> v, remove specified key and return the corresponding value.
If key is not found, d is returned if given, otherwise KeyError is raised
"""
pass
def popitem(self): # real signature unknown; restored from __doc__
"""
D.popitem() -> (k, v), remove and return some (key, value) pair as a
2-tuple; but raise KeyError if D is empty.
"""
pass
def setdefault(self, k, d=None): # real signature unknown; restored from __doc__
""" D.setdefault(k[,d]) -> D.get(k,d), also set D[k]=d if k not in D """
pass
def update(self, E=None, **F): # known special case of dict.update
"""
D.update([E, ]**F) -> None. Update D from dict/iterable E and F.
If E is present and has a .keys() method, then does: for k in E: D[k] = E[k]
If E is present and lacks a .keys() method, then does: for k, v in E: D[k] = v
In either case, this is followed by: for k in F: D[k] = F[k]
"""
pass
def values(self): # real signature unknown; restored from __doc__
""" D.values() -> an object providing a view on D's values """
pass</code></pre>
<ul>
<li>clear:</li>
<li>copy:</li>
<li>fromkeys:</li>
<li>get:</li>
<li>items:</li>
<li>keys:</li>
<li>pop:</li>
<li>popitem:</li>
<li>setdefault:</li>
<li>update:</li>
<li>values:</li>
</ul>
<h2><strong>七、集合 set</strong></h2>
<p>Python3.6源码解析</p>
<pre><code class="python">class set(object):
"""
set() -> new empty set object
set(iterable) -> new set object
Build an unordered collection of unique elements.
"""
def add(self, *args, **kwargs): # real signature unknown
"""
Add an element to a set.
This has no effect if the element is already present.
"""
pass
def clear(self, *args, **kwargs): # real signature unknown
""" Remove all elements from this set. """
pass
def copy(self, *args, **kwargs): # real signature unknown
""" Return a shallow copy of a set. """
pass
def difference(self, *args, **kwargs): # real signature unknown
"""
Return the difference of two or more sets as a new set.
(i.e. all elements that are in this set but not the others.)
"""
pass
def difference_update(self, *args, **kwargs): # real signature unknown
""" Remove all elements of another set from this set. """
pass
def discard(self, *args, **kwargs): # real signature unknown
"""
Remove an element from a set if it is a member.
If the element is not a member, do nothing.
"""
pass
def intersection(self, *args, **kwargs): # real signature unknown
"""
Return the intersection of two sets as a new set.
(i.e. all elements that are in both sets.)
"""
pass
def intersection_update(self, *args, **kwargs): # real signature unknown
""" Update a set with the intersection of itself and another. """
pass
def isdisjoint(self, *args, **kwargs): # real signature unknown
""" Return True if two sets have a null intersection. """
pass
def issubset(self, *args, **kwargs): # real signature unknown
""" Report whether another set contains this set. """
pass
def issuperset(self, *args, **kwargs): # real signature unknown
""" Report whether this set contains another set. """
pass
def pop(self, *args, **kwargs): # real signature unknown
"""
Remove and return an arbitrary set element.
Raises KeyError if the set is empty.
"""
pass
def remove(self, *args, **kwargs): # real signature unknown
"""
Remove an element from a set; it must be a member.
If the element is not a member, raise a KeyError.
"""
pass
def symmetric_difference(self, *args, **kwargs): # real signature unknown
"""
Return the symmetric difference of two sets as a new set.
(i.e. all elements that are in exactly one of the sets.)
"""
pass
def symmetric_difference_update(self, *args, **kwargs): # real signature unknown
""" Update a set with the symmetric difference of itself and another. """
pass
def union(self, *args, **kwargs): # real signature unknown
"""
Return the union of sets as a new set.
(i.e. all elements that are in either set.)
"""
pass
def update(self, *args, **kwargs): # real signature unknown
""" Update a set with the union of itself and others. """
pass</code></pre>
<ul>
<li>add:</li>
<li>clear:</li>
<li>copy:</li>
<li>difference:</li>
<li>difference_update:</li>
<li>discard:</li>
<li>intersection:</li>
<li>intersection_update:</li>
<li>isdisjoint:</li>
<li>issubset:</li>
<li>issuperset:</li>
<li>pop:</li>
<li>remove:</li>
<li>symmetric_difference:</li>
<li>symmetric_difference_update:</li>
<li>union:</li>
<li>update:</li>
</ul>
<hr>
<p>搜索关注微信公众号:<strong>寸土币争</strong> ID: <code>bbcoins</code><br><img src="/img/bVbzFiJ?w=258&h=258" alt="bbcoins.jpg" title="bbcoins.jpg"></p>