基于Kubernetes的混合云的优缺点

混合云平台越来越分为两大类:基于Kubernetes的平台和不基于Kubernetes的平台。因此,在构建一个将内部或托管基础设施与公共云集成的架构时,这是必须做出的首要基本决策之一。

Kubernetes和混合云

当然,开源容器编排器Kubernetes不仅仅是一个混合云平台。它是一种将应用程序(尤其是,但不一定是在容器中运行的应用程序)部署到任何内部或公共云基础设施或其组合上的方法。支持混合云架构甚至不是Kubernetes项目的主要重点。

尽管如此,Kubernetes为混合部署提供了一个关键好处。它提供了一种统一的方法来部署和管理应用程序,而不管它们在哪个基础设施上运行。它通过从应用程序环境中抽象底层基础设施来实现这一点。当你在Kubernetes上部署应用程序时,无论是在公共云、托管数据中心,甚至是用于测试的备用笔记本电脑中进行部署,过程基本相同。

而且,由于Kubernetes可以同时管理跨多种类型基础设施的应用程序环境,它提供了一致的部署和管理体验,即使你的一些服务器和应用程序运行在公共云中,而其他服务器和应用程序运行在内部或托管设施中。

基于Kubernetes的混合平台

意识到这一点,过去几年中一些供应商已经采用了Kubernetes优先的混合云方法。*突出的例子可能是,Google Anthos使用Google Kubernetes Engine管理运行在任何公共云或私有数据中心的集群。VMware的Tanzu平台是另一个例子。

AWS的EKS Anywhere可以通过Amazon的Elastic Kubernetes服务管理内部集群(也可能是运行在其他公共云中的集群),可以算是某种混合云平台。它并不是亚马逊主要的混合解决方案(AWS Outposts提供了更广泛的混合服务集),但就EKS Anywhere支持跨多个托管环境的容器化应用程序的部署而言,它符合混合云的要求。

基于Kubernetes的混合平台列表到此为止。其他主要的混合解决方案,包括AWS Outposts、Azure Stack和Azure Arc,使用其他技术作为混合云管理的基础。它们通过混合架构支持Kubernetes部署,但是它们不使用Kubernetes作为底层混合环境的管理层。

为什么或为什么不选择混合云上的Kubernetes

混合云的一种实现方法比另一种更好吗?这取决于几个因素。

*重要的是,相比通过公共云的标准工具来管理工作负载,你是否更喜欢通过Kubernetes来管理它们。Anthos和Tanzu等平台使用Kubernetes来编排一切,而Outposts和Azure Stack等解决方案则使用原生管理工具(CloudWatch、CloudTrail、CloudFormation等)进行应用程序部署和管理。如果你更喜欢使用Kubernetes方法来部署和管理应用程序,那么基于Kubernetes的混合云平台可能正适合你。

第二个要考虑的因素是应用程序的容器化程度。Kubernetes可以管理虚拟机和容器,事实上,VM编排在Tanzu和Anthos中都是重要功能。但归根结底,在Kubernetes中管理虚拟机可能会让人感到奇怪,Kubernetes的设计首先是编排容器。虚拟机的启动和停止速度通常不如容器快,而且你很少像容器那样启动多个虚拟机实例。如果你的工作负载主要由虚拟机组成,那么*好使用不围着Kubernetes转的混合云平台。

同样值得考虑的是,你是否看好Kubernetes。这个平台如今非常流行(这也是谷歌和VMware选择它作为混合战略基础的部分原因),但它只有7年的历史。有理由认为Kubernetes更像是一种时尚,而不是一种长期的技术主流。

毕竟,五六年前,当Kubernetes只是一个没有人能说出名字的新贵项目时,Docker似乎要永远统治世界,那时候把你的工具与Docker结合似乎是一个稳妥的选择。但现在完全不是如此。

那么,致力于一个基于Kubernetes的混合平台,就有可能像是在2015年左右全力以赴押注Docker:只要炒作持续下去,它就会起作用,但当时尚消退时,你可能不得不重建一切。

灵活性是另一个需要考虑的因素。一般来说,基于Kubernetes的混合云比那些依赖云供应商专有工具的混合云更灵活。例如,如果你使用Azure Stack,那么很难迁移到AWS Outposts,因为这基本上相当于从Azure迁移到AWS。但是从Anthos迁移到Tanzu会更容易(虽然不是无缝的),因为这两个平台都是建立在Kubernetes之上的。

结论

有充分的理由选择Kubernetes作为混合云战略的基础。而选择一个不需要Kubernetes工具并且支持Kubernetes无法管理的工作负载类型的平台也有一些很好的理由。请想好。

控制流作业

控制流作业

# ————————-*题—————————#
number = input(‘请输入一个整数:’)
if (int(number)%7 == 0) | (number.find(‘7’) != -1):
print(‘该数与7相关’)
else:
print(‘该数与7无关’)

# ————————-第二题—————————#
id = input(‘请输入身份证号码:’)
if len(id) == 18:
birthday = id[6:14]
print(‘你的出生日期是:’,birthday)
elif len(id) == 15:
birthday = ’19’ + id[6:12]
print(‘你的出生日期是:’,birthday)
else:
print(‘请重新输入身份证号码!’)

# ————————-第三题—————————#
id = input(‘请输入身份证号码:’)
if len(id) == 18:
if int(id[-2]) % 2 == 0:
print(‘女’)
else:
print(‘男’)
elif (len(id)) == 15:
if int(id[-1]) % 2 == 0:
print(‘女’)
else:
print(‘男’)
else:
print(‘请重新输入身份证号码!’)

# ————————-第四题—————————#
list6 = [1,5,2,8,10,13,17,4,6]
## 方法一:
result = []
for i in list6:
result.append(i**2+1)
print(result)

## 方法二:
result = [i**2+1 for i in list6]
print(result)

# ————————-第五题—————————#
list7 = [‘one’,’two’,’three’,’four’,’five’,’six’,’seven’,’eight’,’nine’]
## 方法一:
result = []
for i in list7:
if i.find(‘e’) != -1:
new_i = i.replace(i[:],’^-^’)
result.append(new_i)
else:
result.append(i)
print(result)

## 方法二:
result = [i for i in list7 if i.find(‘e’)!=-1]
print(result)

#————————-第六题—————————#
# 同第四题

# ————————-第七题—————————#
list8 = [‘A’,’C’,’A’,’C’,’B’,’C’,’A’,’A’,’B’,’C’]
dict = {}
for i in set(list8):
dict[i] = list8.count(i)
print(dict)

# ————————-第八题—————————–#
n = 1
s = 0
while s<=1000:
s += 3*n+5
n += 1
print(n,’–>’,s)

# ————————–第九题—————————–#
import random
A = int(input(‘范围*小值:’))
B = int(input(‘范围*大值:’))
number = random.randint(A,B)

while True:
guess = int(input(‘请在{}、{}之间猜一个整数:’.format(A,B)))
if guess > number:
B = guess
elif guess < number:
A = guess
else:
print(‘你真棒,猜中了。’)
break

Dijkstra算法流程及基于Python仿真

Dijkstra算法流程及基于Python仿真

Dijkstra流程:

%title插图%num
基于Python的程序仿真
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import matplotlib.pyplot as plt
import math

show_animation = True

class Dijkstra:

def __init__(self, ox, oy, resolution, robot_radius):
“””
Initialize map for planning

ox: x position list of Obstacles [m]
oy: y position list of Obstacles [m]
resolution: grid resolution [m]
rr: robot radius[m]
“””

self.min_x = None
self.min_y = None
self.max_x = None
self.max_y = None
self.x_width = None
self.y_width = None
self.obstacle_map = None

self.resolution = resolution
self.robot_radius = robot_radius
#构建栅格地图
self.calc_obstacle_map(ox, oy)
self.motion = self.get_motion_model()

class Node:
def __init__(self, x, y, cost, parent_index):
self.x = x # index of grid
self.y = y # index of grid
self.cost = cost # g(n)
self.parent_index = parent_index
# index of previous Node

def __str__(self):
return str(self.x) + “,” + str(self.y) + “,” + str(
self.cost) + “,” + str(self.parent_index)

def planning(self, sx, sy, gx, gy):
“””
dijkstra path search

input:
s_x: start x position [m]
s_y: start y position [m]
gx: goal x position [m]
gx: goal x position [m]

output:
rx: x position list of the final path
ry: y position list of the final path
“””
#将起点和终点转换为节点形式,即包含下标,代价值和父节点信息
start_node = self.Node(self.calc_xy_index(sx, self.min_x),
self.calc_xy_index(sy, self.min_y), 0.0, -1)
# round((position – minp) / self.resolution)
goal_node = self.Node(self.calc_xy_index(gx, self.min_x),
self.calc_xy_index(gy, self.min_y), 0.0, -1)

open_set, closed_set = dict(), dict() # key – value: hash表
#key是表示索引,value 是节点信息
open_set[self.calc_index(start_node)] = start_node

while 1:
c_id = min(open_set, key=lambda o: open_set[o].cost)
# 取cost*小的节点
current = open_set[c_id]

# show graph 动画仿真
if show_animation: # pragma: no cover
plt.plot(self.calc_position(current.x, self.min_x),
self.calc_position(current.y, self.min_y), “xc”)
# for stopping simulation with the esc key.
plt.gcf().canvas.mpl_connect(
‘key_release_event’,
lambda event: [exit(0) if event.key == ‘escape’ else None])
if len(closed_set.keys()) % 10 == 0:
plt.pause(0.001)

# 判断是否是终点
if current.x == goal_node.x and current.y == goal_node.y:
print(“Find goal”)
goal_node.parent_index = current.parent_index
goal_node.cost = current.cost
break

# Remove the item from the open set
del open_set[c_id]

# Add it to the closed set
closed_set[c_id] = current

# expand search grid based on motion model
for move_x, move_y, move_cost in self.motion:
node = self.Node(current.x + move_x,
current.y + move_y,
current.cost + move_cost, c_id)
n_id = self.calc_index(node)

if n_id in closed_set:
continue

if not self.verify_node(node):
continue

if n_id not in open_set:
open_set[n_id] = node # Discover a new node
else:
if open_set[n_id].cost >= node.cost:
# This path is the best until now. record it!
open_set[n_id] = node

rx, ry = self.calc_final_path(goal_node, closed_set)

return rx, ry
#通过父节点追溯从起点到终点的*佳路径
def calc_final_path(self, goal_node, closed_set):
# generate final course
rx, ry = [self.calc_position(goal_node.x, self.min_x)], [
self.calc_position(goal_node.y, self.min_y)]
parent_index = goal_node.parent_index
while parent_index != -1:
n = closed_set[parent_index]
rx.append(self.calc_position(n.x, self.min_x))
ry.append(self.calc_position(n.y, self.min_y))
parent_index = n.parent_index

return rx, ry

def calc_position(self, index, minp):
pos = index * self.resolution + minp
return pos

def calc_xy_index(self, position, minp):
return round((position – minp) / self.resolution)

def calc_index(self, node):
return node.y * self.x_width + node.x
#检查是否超出地图范围或有障碍物
def verify_node(self, node):
px = self.calc_position(node.x, self.min_x)
py = self.calc_position(node.y, self.min_y)

if px < self.min_x:
return False
if py < self.min_y:
return False
if px >= self.max_x:
return False
if py >= self.max_y:
return False

if self.obstacle_map[int(node.x)][int(node.y)]:
return False

return True

def calc_obstacle_map(self, ox, oy):
”’ 第1步:构建栅格地图 ”’
self.min_x = round(min(ox))
self.min_y = round(min(oy))
self.max_x = round(max(ox))
self.max_y = round(max(oy))
print(“min_x:”, self.min_x)
print(“min_y:”, self.min_y)
print(“max_x:”, self.max_x)
print(“max_y:”, self.max_y)

#计算X和Y方向 栅格的个数
self.x_width = round((self.max_x – self.min_x) / self.resolution)
self.y_width = round((self.max_y – self.min_y) / self.resolution)
print(“x_width:”, self.x_width)
print(“y_width:”, self.y_width)

# obstacle map generation
# 初始化地图,地图是要用二维向量表示的,在这里采用两层列表来表示
#初始化为false,内层为Y方向栅格的个数,外层为X方向栅格个数
self.obstacle_map = [[False for _ in range(int(self.y_width))]
for _ in range(int(self.x_width))]
# 设置障碍物
for ix in range(int(self.x_width)):
x = self.calc_position(ix, self.min_x)
for iy in range(int(self.y_width)):
y = self.calc_position(iy, self.min_y)
for iox, ioy in zip(ox, oy):
#障碍物到栅格的距离,如果小于车体半径,就标记为true,障碍物膨胀
d = math.hypot(iox – x, ioy – y)
if d <= self.robot_radius:
self.obstacle_map[ix][iy] = True
break

@staticmethod
def get_motion_model():
# dx, dy, cost
#定义机器人行走的代价,以当前点为中心周围八个栅格的代价
motion = [[1, 0, 1],
[0, 1, 1],
[-1, 0, 1],
[0, -1, 1],
[-1, -1, math.sqrt(2)],
[-1, 1, math.sqrt(2)],
[1, -1, math.sqrt(2)],
[1, 1, math.sqrt(2)]]

return motion

def main():
# start and goal position
sx = -5.0 # [m]
sy = -5.0 # [m]
gx = 50.0 # [m]
gy = 50.0 # [m]
grid_size = 2.0 # [m]
robot_radius = 1.0 # [m]

# set obstacle positions
ox, oy = [], []
for i in range(-10, 60):
ox.append(i)
oy.append(-10.0)
for i in range(-10, 60):
ox.append(60.0)
oy.append(i)
for i in range(-10, 61):
ox.append(i)
oy.append(60.0)
for i in range(-10, 61):
ox.append(-10.0)
oy.append(i)
for i in range(-10, 40):
ox.append(20.0)
oy.append(i)
for i in range(0, 40):
ox.append(40.0)
oy.append(60.0 – i)

if show_animation: # pragma: no cover
plt.plot(ox, oy, “.k”)
plt.plot(sx, sy, “og”)
plt.plot(gx, gy, “xb”)
plt.grid(True)
plt.axis(“equal”)

dijkstra = Dijkstra(ox, oy, grid_size, robot_radius)
rx, ry = dijkstra.planning(sx, sy, gx, gy)

if show_animation: # pragma: no cover
plt.plot(rx, ry, “-r”)
plt.pause(0.01)
plt.show()

if __name__ == ‘__main__’:
main()

仿真结果:

%title插图%num

Reference:
1.Dijkstra
2.PythonRobotics

print格式化输出

稍息!立正!——print格式化输出

痴月熊学Python
文章目录
痴月熊学Python
往期文章
前言
一、f-String格式化
二、占位符
三、format格式化
总结
往期文章
*章:Python-新人报道
第二章:小学生都会的数学计算,痴月熊学Python
第三章:变量-从此你就叫张三了!,痴月熊学python
第四章:神奇的变身器-转义字符(改),痴月熊学python

前言
福宝们,下午好啊。改版后的第4.5章阅读量有点少呀,不知道是不是拖更了一天的缘故。呜呜呜,以后一定要做个不拖更的好熊,所以今天继续爆肝第五章:print格式化输出。在写第三章的时候用到过其中一种: ” f … {} ” 的组合。之前的评论下面有小伙伴疑惑,那今天就来详细讲解一下这个东西,另外还有其他格式化的方式。那我们开始今天的学习吧。

提示:以下是本篇文章正文内容,下面案例可供参考

一、f-String格式化
所谓格式化输出,就是创建一个可以嵌入变量内容的字符串。如果不进行格式化,变量名就会被直接打印出来,发挥不了他的作用。所以我们现在开始讲之前用到的:f-String格式化。这个上面也说过,格式: f” … {} … “,其中你要在字符串里调用变量,需要把变量写在 ” { } ” 中,字符串的开头还要写个 ” f ” 。f 就代表着format,也就是格式化的意思。这个组合是固定的,缺一不可,你写出了 ” f “,就相当于告诉了python,这是一个已经格式化的字符串。python就会去看那些变量,当然你要是前面写了f,中间没有写中括号,也是可以正常执行的。只不过没有去调用变量。

name = “痴月熊”
name2 = “憨憨熊”
age = 18
age2 = 19
print(f”{name}:下午好各位,我是{name},{age}的文艺小青年。这是我铁子{name2},他{age2},请多关照”)
print(f”{name2}:嗷嗷嗷~”)

RUN:

痴月熊:下午好各位,我是痴月熊,18的文艺小青年。这是我铁子憨憨熊,他19,请多关照
憨憨熊:嗷嗷嗷~

二、占位符
首先还是看个表,常见的占位符号

符号 意义
%d 整数
%f 浮点数
%s 字符串
占位符,顾名思义。就是在一段字符串中占一个位置,然后引用变量插进来。具体格式是 print(“…%d…” % (变量)),下面还是直接通过练习来看一下效果。

name = “憨憨熊”
once = 1
num = 4.2
print(“%s *喜欢的事情就是打游戏,他*擅长的还是动作冒险类” % name)
print(“魂斗罗他甚至只需要 %d 条命就可以通关” % once)
print(“即使他两个眼睛都已经%f度了,还是不能放下游戏机” %num)

RUN:

憨憨熊 *喜欢的事情就是打游戏,他*擅长的还是动作冒险类
魂斗罗他甚至只需要 1 条命就可以通关
即使他两个眼睛都已经4.200000度了,还是不能放下游戏机

效果就是这样啦,当然也可以放在一起试一下。

name = “憨憨熊”
once = 1
num = 4.2
print(“””
%s *喜欢的事情就是打游戏,他*擅长的还是动作冒险类.
魂斗罗他甚至只需要 %d 条命就可以通关.
即使他两个眼睛都已经%f度了,还是不能放下游戏机
“”” % (name,once,num))

RUN:

憨憨熊 *喜欢的事情就是打游戏,他*擅长的还是动作冒险类.
魂斗罗他甚至只需要 1 条命就可以通关.
即使他两个眼睛都已经4.200000度了,还是不能放下游戏机

使用占位符的时候,一定要想好变量的数据类型,如果你写了个%d,结果你放了个字符串进去就会报错。当然数字也可以作为字符串,你写成%s也可以执行。不过为了方便浏览,*好根据数据类型填入相应的占位符。另外如果你占位符是%d,你放了个浮点型进去,他就会给你强制转换为整数,反之也是一样的。如下:

num1 = 4.2
num2 = 4
print(“%d” % num1)
print(“%f” % num2)

RUN:

4.000000

三、format格式化
第三种就是利用format函数,在python里也叫方法。基本语法是在字符串中写入 ” {} “,*后再字符串的末尾调用.format方法,将变量插入到{}。看起来是不是像f-string格式化,format格式化是在python2.6更新的,而f-string是在python3.6。当然个人认为这个用起来不太舒服,还是上面两个好用点。有很多时候,想要插入变量,都要在后面写一大堆参数。好麻烦! 以下就是效果啦。

name1 = “痴月熊”
name2 = “憨憨熊”
time = 12
num = 2
print(“此时半夜{}点:\”呜呜呜, {}.\””.format(time,name1))
print(“{name2},大晚上{time}点的,你在瞎叫啥”.format(time=time, name2=name2))
print(“我居然花了{}条命才过这个关卡”.format(num))
print(f”{name1}心里独白:这玩意能一条命就过去的才不是正常熊吧。”.format(name1=name1))
print(“<玛丽奥制造>….”)

RUN:

此时半夜12点:”呜呜呜, 痴月熊.”
憨憨熊,大晚上12点的,你在瞎叫啥
我居然花了2条命才过这个关卡
痴月熊心里独白:这玩意能一条命就过去的才不是正常熊吧。
<玛丽奥制造>….

蓝桥杯Python部分小套路

蓝桥杯Python部分小套路(超详细分析!!)

蓝桥杯Python部分小套路
一、说明
本人是小白,以下小套路是对前段所刷题的小小总结,不全面,仅仅作为小分享,各位大佬多多包涵啦~
欢迎大家进入我的主页浏览其它文章。

二、部分小套路
1.同时输入多个参数
n,m=map(int,input().split())

不要漏掉 map
不要漏掉split()
2.输入列表的3种表达方法
list1=list(input().split())
print(list1)

*简单直接的一种,不要在前面漏掉list
如果加上map和int是错误的
list1=list(map(int,input().split()))
`
n=3
list1=[]
for i in range(3):
list1.append(input().split())
print(list1)

将会得到3行x列的列表(x:具体有多少列看自己一行输入多少个数字)
h,l=map(int,input().split())
list1=[[]for i in range(h)]
for j in range(h):
arr=list(input().split())
for k in range(l):
list1[j].append(arr[k])
print(list1)

*行:h与l分布代表行与列数
第二行:首先先建立一个有h个[ ]的列表list1,之后再把数字加入到[ ]中
第三、四行:然后针对h个[ ],输入对应的数字进去
第五、六行:*后,把arr放入list1的对应j行
这种表示方法没有前2种简单,但是可以用于题目要求输入h行,l列时

混合云的五大好处

混合云提供了许多重要的功能,可以使各种形状和规模的企业受益。这些新功能使企业能够利用混合云,以前所未有的方式扩展IT基础架构。我们来看看混合云的五大优点。

  1. 降低成本

    降低成本是云计算*吸引人的优势之一,也是驱使企业管理层考虑云服务的重要因素。升级预置基础设施的增量成本很高,增加预置的计算资源需要购置额外的服务器、存储、电力以及在某些*端情况下新建数据中心的需求。混合云可以帮助企业降低成本,利用“即用即付”云计算资源来消除购买本地资源的需求。

  2. 增加存储和可扩展性

    混合云为企业扩展存储提供了经济高效的方式,云存储的成本相比等量本地存储要低得多,是备份、复制VM和数据归档的不错选择。除此之外,增加云存储没有前置成本和本地资源需求。

  3. 提高可用性和访问能力

    虽然云计算目前并不能保证服务永远正常,但公有云通常会比大多数本地基础设施具有更高的可用性。云内置有冗余功能并提供关键数据的geo-replication。另外,像Hyper-V副本和SQL Server AlwaysOn可用性组等技术可以让我们利用云计算来改进HA和DR。云还提供了几乎无处不在的连接,使全球组织可以从几乎任何位置访问云服务。

  4. 提高敏捷性和灵活性

    混合云*大的好处之一就是灵活性。混合云使您能够将资源和工作负载从本地迁移到云,反之亦然。对于开发和测试而言,混合云使开发人员能够轻松搞定新的虚拟机和应用程序,而无需IT运维人员的协助。您还可以利用具有弹性伸缩的混合云,将部分应用程序扩展到云中以处理峰值处理需求。云还提供了各种各样的服务,如BI、分析、物联网等,您可以随时使用这些服务,而不是自己构建。

  5. 获得应用集成优势

    今天,许多应用程序都提供了内置的混合云集成功能。例如,如前所述,Hyper-V副本和SQL Server AlwaysOn可用性组都具有内置的云集成功能。 SQL Server的Stretch Databases功能等新技术也使您能够将数据库从内部部署到云中。

混合云已经成为许多企业IT基础架构的核心组件。就像电视节目“The Price is Right”,混合云即付即用的模式使其成为一种高成本效益的选择,可以为各类企业带来诸多好处。

控制结构与函数

控制结构与函数

3.1 分支结构
3.1.1 单分支结构
Python 的单分支结构使用 if 保留字对条件进行判断,使用方式如下:

if <条件>:
<语句块>

<语句块> 是 if 条件满足后执行的一个或多个语句序列,缩进表达 <语句块> 与 if 的包含关系。<条件> 是一个产生 True 或 False 结果的语句,当结果为 True 时,执行 <语句块>,否则跳过 <语句块>。

3.1.2 二分支结构
Python 的二分支结构使用 if-else 保留字对条件进行判断,语法格式如下:

if <条件>:
<语句块 1>
else:
<语句块 2>

<语句块 1> 在 if 中 <条件> 满足即为 True 时执行,<语句块 2> 在 if 中 <条件> 不满足即为 False 时执行。简单来说,二分支结构根据条件的 True 或 False 结果产生两条路径。

二分支结构还有一种更简洁的表达方式,适合 <语句块 1> 和 <语句块 2> 都只包含简单表达式的情况,语法格式如下:

<变量> = <表达式 1> if <条件> else <表达式 2>
1
如果 <条件> 为 True,则将 <表达式 1> 的结果赋值给 <变量>,否则将 <表达式 2> 的结果赋值给 <变量>。

first_num = eval(input(‘请输入*个数:’))
second_num = eval(input(‘请输入第二个数:’))
bigger_num = first_num if first_num >= second_num else second_num
print(f’较大的数是{bigger_num}。’)
————————————————————————
请输入*个数:50
请输入第二个数:25
较大的数是50。

3.1.3 多分支结构
Python 的 if-elif-else 用于描述多分支结构,语句格式如下:

if <条件 1>:
<语句块 1>
elif <条件 2>:
<语句块 2>

else:
<语句块 n>

多分支结构通常用于判断同一个条件或一类条件的多个执行路径。Python 会按照多分支结构的代码顺序依次评估判断条件,寻找并执行*个结果为 True 的条件所对应的语句块。当 if-elif-else 中的某个语句块执行后,Python 就会跳过整个 if-elif-else 结构。即使后续的条件测试为真,其对应的语句块也不会被执行。

此外,Python 并不要求 if-elif 结构后面的代码必须有 else 代码块。else 代码块是一个包罗万象的语句,只要不满足任何 if 或 elif 中的条件测试,else 中的代码就会被执行。这可能会引入无效甚至恶意的数据。如果知道*终要测试的条件,应考虑使用一个 elif 代码块代替 else 代码块。这样就可以肯定,仅当满足相应的条件时,代码才会执行。

3.1.4 条件判断及组合
分支结构中的条件判断可以使用任何能够产生 True 或 False 的语句或函数。形成判断条件*常见的方式是采用关系操作符:<、<=、>、>=、==、!=。

Python 语言中,任何非零的数值、非空的数据类型都等价于 True,0 或空类型等价于 False,它们可以直接用作判断条件。

Python 语言使用保留字 not、and 和 or 对条件进行逻辑运算或组合。保留字 not 表示单个条件的“否”关系,and 表示多个条件之间的“与”关系,保留字 or 表示多个条件之间的“或”关系。

3.1.5 测试多个条件
if-elif-else 结构功能强大,但仅适用于只有一个条件满足的情况:遇到了通过了的测试后,Python 便会跳过余下的测试。这种设定效率很高,但只能测试一个特定的条件。

如果需要检查多个条件,应使用一系列不包含 elif 和 else 代码块的简单 if 语句。在可能有多个条件为 True 且需要在每个条件为 True 时都采取响应措施时,这种方法将非常适合。

3.2 循环结构
3.2.1 遍历循环
遍历循环可以理解为从遍历结构中逐一提取元素,放在循环变量中,对于每个所提取的元素执行一次语句块。for 语句的循环执行次数是根据遍历结构中元素个数确定的。其语法结构如下:

for <循环变量> in <遍历结构>:
<语句块>

<遍历结构> 可以是字符串、range() 函数或组合数据类型、文件等。对于字符串,可以逐一遍历字符串的每个字符,基本使用方式如下:

for <循环变量> in <字符串变量>:
<语句块>

使用 range() 函数,可以指定语句块的循环次数,基本使用方式如下:

for <循环变量> in range(<循环次数>):
<语句块>

除了在 range() 函数里直接指定循环次数,也可以使用如下用法:range(start, stop[, step])。表示计数从 start 开始,到 stop 结束,但不包括 stop。step 为步长,缺省时步长为 1。

3.2.2 无限循环
Python 通过保留字 while 实现无限循环:

while <条件>:
<语句块>

当程序执行到 while 语句时,条件测试如果为 True,执行循环体语句,语句结束后返回再次判断 while 语句的条件;当条件测试为 False 时,循环终止,执行与 while 同级别缩进的后续语句。

while 定义的是无限循环,让其在恰当的时候停止运行是很重要的。如果让 while 循环停止的条件不多时,通过简单的条件测试即可结束它的运行。但在更复杂的程序当中,很可能会有众多的事件将导致循环的停止,在这种情况下如果在一条 while 语句中检查所有的这些条件,将既复杂又困难。

一种很好的方法是定义一个变量将其作为标志(flag),用于判断整个程序是否处于活动状态。它相当于程序的交通信号灯,当所有的条件满足时,它的值为 True,循环继续执行;一旦循环条件不满足时就为 False,以此来结束程序的运行。

prompt = “\n我是一个复读机。”
prompt += “\n我会重复你的话,输入 quit 结束程序。”

active = True
while active:
message = input(prompt)

if message == ‘quit’:
active = False
else:
print(message)
————————————————————————
我是一个复读机。
我会重复你的话,输入 quit 结束程序。你好
你好

我是一个复读机。
我会重复你的话,输入 quit 结束程序。你是只鹦鹉
你是只鹦鹉

我是一个复读机。
我会重复你的话,输入 quit 结束程序。quit

上述程序中,变量 active 被设置成了标志位,用于判断输入的内容是不是 quit 以确定程序是否继续执行。

3.2.3 循环控制
循环结构有两个辅助循环控制的保留字:break 和 continue。

break 用来跳出 for 或 while 循环,脱离该循环后程序从循环后的代码继续执行。如果有 2 层或多层循环,break 只能退出*内层循环。

利用 break 可将上述代码改写:

prompt = ‘\n我是一个复读机。’
prompt += ‘\n输入 quit 结束程序。’

while True:
message = input(prompt)

if message == ‘quit’:
break
else:
print(message)
————————————————————————
我是一个复读机。
我会重复你的话,输入 quit 结束程序。你好
你好

我是一个复读机。
我会重复你的话,输入 quit 结束程序。你是只鹦鹉
你是只鹦鹉

我是一个复读机。
我会重复你的话,输入 quit 结束程序。quit

continue 用来结束本次循环,即跳出循环体中下面尚未执行的语句,但不跳出当前循环。

current_number = 0
while current_number < 10:
current_number += 1
if current_number % 2 == 0:
continue

print(current_number)
————————————————————————

continue 语句和 break 语句的区别是:continue 语句只结束本次循环,不终止整个循环的执行,而 break 具备结束循环的能力。

3.2.4 循环中的 else 子句
循环语句支持 else 子句。for 循环中,可迭代对象中的元素全部循环完毕时,或当 while 循环的条件为假时,执行该子句;break 语句终止循环时,不执行该子句。

for i in range(10):
print(i, end=’ ‘)
else:
print(‘循环结束。’)
————————————————————————
0 1 2 3 4 5 6 7 8 9 循环结束。

for i in range(10):
print(i, end=’ ‘)
if i == 5:
break # break终止了循环,不执行else子句
else:
print(‘循环结束。’)
————————————————————————
0 1 2 3 4 5

num = 9
while num >= 0:
print(num, end=’ ‘)
num -= 1
else:
print(‘循环结束。’)
————————————————————————
9 8 7 6 5 4 3 2 1 0 循环结束。

num = 0
while num >= 10:
print(num, end=’ ‘)
num -= 1
else:
print(‘循环结束。’)
————————————————————————
循环结束。

3.3 函数的基本使用
3.3.1 函数的概念
函数是一段具有特定功能的、可重用的代码块,通过函数名来表示和调用。经过定义,一组语句等价于一个函数,在需要使用这组语句的地方,直接调用函数名称即可。

Python 定义一个函数使用 def 保留字,语法形式如下:

def <函数名>(<参数列表>):
<函数体>
return <返回值列表>

函数名可以是任何有效的 Python 标识符。参数列表是调用该函数时传递给它的值,可以有零个、一个或多个。当传递多个参数时各参数由逗号分隔,没有参数时也要保留圆括号。函数体是函数每次被调用时执行的代码,由一行或多行语句组成。

如果需要返回值,使用保留字 return 和返回值列表。函数可以没有 return 语句,表示函数没有返回值。函数体运行结束后会将控制权返回给调用者。

3.3.2 基本用法
定义后的函数不能直接运行,需要经过调用才能运行。调用函数的基本方法如下:

<函数名>(<实际赋值参数列表>)
1
具体来说,函数的使用一共分为四个步骤:函数定义、函数调用、函数执行、函数返回。

函数定义:使用 def 保留字将一段代码定义为函数,需要确定函数的名字、参数的名字、参数的个数,使用参数名称作为形式参数(占位符)编写函数内部的功能代码。

函数调用:通过函数名调用函数功能,对函数的各个参数赋予实际值,实际值可以是实际数据,也可以是在调用函数前已经定义过的变量。

函数执行:函数被调用后,使用实际参数(赋予形式参数的实际值)参与函数内部代码的运行。

函数返回:函数执行结束后,根据 return 保留字的指示决定是否返回结果。如果返回结果,则结果将被放置到函数被调用的位置。函数使用完毕,程序继续运行。

3.3.2 传递实参
向函数传递实参的方式很多。可使用位置实参,这要求实参的顺序与形参的顺序相同;也可用关键字实参,其中每个实参都由变量名和值组成;还可以向函数传递列表和字典。

调用函数时,Python 必须将函数调用中的每个实参都关联到函数定义中的形参。为此,*简单的关联方式是基于实参的顺序。这种关联方式称为位置实参。

def describe_pet(animal_type, pet_name):
“””显示宠物信息。”””
print(f”\nI have a {animal_type}.”)
print(f”My {animal_type}’s name is {pet_name.title()}.”)

describe_pet(‘parrot’, ‘polly’)
————————————————————————
I have a parrot.
My parrot’s name is Polly.

位置实参的顺序很重要,如果实参的顺序不正确,结果可能会出乎意料。

关键字实参则是传递给函数的名称值对。因为直接在实参中将名称和值关联起来,所以向函数传递实参时不会混淆。关键字实参让你无须考虑函数调用中的实参顺序,还清楚地指出了函数调用中各个值得用途。

def describe_pet(animal_type, pet_name):
“””显示宠物信息。”””
print(f”\nI have a {animal_type}.”)
print(f”My {animal_type}’s name is {pet_name.title()}.”)

describe_pet(animal_type=’parrot’, pet_name=’polly’)
————————————————————————
I have a parrot.
My parrot’s name is Polly.

3.3.3 返回简单值
return 语句用来结束函数并将程序返回到函数被调用的位置继续执行。return 语句可以出现在函数中的任何部分,当执行 return 语句时,即使函数主体中还有其他语句,函数执行也会停止,同时可以将 0 个、1 个或多个函数运算的结果返回给函数被调用处的变量。

函数可以没有 return,此时函数并不返回值。当函数使用 return 返回多个值,应该使用一个变量或多个变量保存结果。如果使用一个变量接收多个返回值的话,Python 将把多个返回值以元组的形式赋值给该变量。

def caluculate(x, y=10):
“””返回两个参数相乘和相加的结果。”””
return x*y, x+y

s = caluculate(99, 2)
print(s)

a, b = caluculate(99, 2)
print(a)
print(b)
————————————————————————
(198, 101)
198
101

3.3.4 为形参指定默认值
函数的参数在定义时可以指定默认值,当函数被调用时,如果没有传入对应的参数值,则使用函数定义时的默认值替代。函数定义时的语法形式如下:

def <函数名>(<非可选参数列表>, <可选参数>=<默认值>):
<函数体>
return <返回值列表>
1
2
3
使用默认值时,必须先在形参列表中列出没有默认值的形参,再列出有默认值的实参。这样才能让 Python 正确地解读位置实参。

def describe_pet(pet_name, animal_type=’dog’):
“””显示宠物信息。”””
print(f”\nI have a {animal_type}.”)
print(f”My {animal_type}’s name is {pet_name.title()}.”)

describe_pet(pet_name=’willie’)
————————————————————————
I have a dog.
My dog’s name is Willie.

3.3.5 让实参变成可选的
有时候,需要让实参变成可选的,这样使用函数的人就能只在必要的时候提供额外的信息。可使用默认值来让实参变成可选的。

例如要处理一位西方人的姓名,他们的姓名都有 first name 与 last name,但并非每个人的名字都有 middle name。下面的程序便演示了怎样处理这个问题:

def get_formatted_name(first_name, last_name, middle_name=”):
“””返回整洁的姓名。”””
if middle_name:
full_name = f”{first_name} {middle_name} {last_name}”
else:
full_name = f”{first_name} {last_name}”
return full_name.title()

musician = get_formatted_name(‘michael’, ‘jackson’)
print(musician)

musician = get_formatted_name(‘michael’, ‘jackson’, ‘joseph’)
print(musician)
————————————————————————
Michael Jackson
Michael Joseph Jackson

3.4 更多的函数使用细节
3.4.1 等效的函数调用
Python 支持混合使用位置参数、关键字参数和默认值,因此有多种等效的函数调用方式。例如下面对函数 describe_pet() 的定义中,给一个形参提供了默认值:

def describe_pet(pet_name, animal_type=’dog’):
1
基于这种定义,在任何情况下都必须给 pet_name 提供实参,指定该实参时可采用位置方式,也可采用关键字方式。如果要函数描述的动物不是小狗,还必须在函数调用中给 animal_type 提供实参。同样,指定该实参时可以采用位置方式,也可采用关键字方式。

下面对这个函数的调用方式都可行:

# 一条名为 Willie 的小狗
describe_pet(‘willie’)
describe_pet(pet_name=’willie’)

# 一只名为 Polly 的鹦鹉
describe_pet(‘polly’, ‘parrot’)
describe_pet(pet_name=’polly’, animal_type=’parrot’)
describe_pet(animal_type=’parrot’, pet_name=’polly’)

3.4.2 返回字典
函数可返回任何类型的值,包括列表和字典等比较复杂的数据结构。下面的函数接受姓名的组成部分,并返回一个表示个人信息的字典:

def build_person(first_name, last_name, age=None):
“””返回一个字典,其中包含有关一个人的信息。”””
person = {‘first’: first_name, ‘last’: last_name}
if age:
person[‘age’] = age
return person

musician = build_person(‘michael’, ‘jackson’)
print(musician)

musician = build_person(‘michael’, ‘jackson’, age=’50’)
print(musician)
————————————————————————
{‘first’: ‘michael’, ‘last’: ‘jackson’}
{‘first’: ‘michael’, ‘last’: ‘jackson’, ‘age’: ’50’}

在函数定义中,定义了一个可选形参 age,其默认值设置成了 None,表示变量没有值。可以将 None 视为占位符,在条件测试中,None 相当于 False。如果函数调用中包含形参 age 的值,这个值也将被存储到字典中。

3.4.3 结合使用函数和 while 循环
下面的程序使用函数 get_formatted_name() 和 while 循环,以更正式的方式问候用户。同时,该程序提供了退出的方式。

def get_formatted_name(first_name, last_name):
“””返回整洁的姓名。”””
full_name = f”{first_name} {last_name}”
return full_name.title()

while True:
print(“\nPlease tell me your name:”)
print(“(enter’q’at any time to quit)”)

f_name = input(“First name:”)
if f_name == ‘q’:
break

l_name = input(“Last name:”)
if l_name == ‘q’:
break

formatted_name = get_formatted_name(f_name, l_name)
print(f”\nHello, {formatted_name}!”)
————————————————————————
Please tell me your name:
(enter ‘q’ at any time to quit)
First name: john
Last name: lennon

Hello, John Lennon!

Please tell me your name:
(enter ‘q’ at any time to quit)
First name: michael
Last name: jackson

Hello, Michael Jackson!

Please tell me your name:
(enter ‘q’ at any time to quit)
First name: q

3.4.4 列表的传递
将列表传递给函数后,函数就可对其进行修改。在函数中对这个列表所做的任何修改都是永久性的。假设有一家为用户提交的设计制作 3D 打印模型的公司,需要将打印的设计存储到一个列表中,打印后将移到另一个列表中。下面的程序展示了这一实现:

def print_models(unprinted_designs, completed_models):
“””
模拟打印每个设计,直到没有未打印的设计为止。
打印每个设计后,都将其移到列表 completed_models 中。
“””
while unprinted_designs:
current_design = unprinted_designs.pop()
print(f”Printing model: {current_design}”)
completed_models.append(current_design)

def show_completed_models(completed_models):
“””显示打印好的模型。”””
print(“\nThe following models have been printed:”)
for completed_model in completed_models:
print(completed_model)

unprinted_designs = [‘phone case’, ‘robot pendant’, ‘dodecahedron’]
completed_models = []

print_models(unprinted_designs, completed_models)
show_completed_models(completed_models)
————————————————————————
Printing model: dodecahedron
Printing model: robot pendant
Printing model: phone case

The following models have been printed:
dodecahedron
robot pendant
phone case

有时候,需要禁止函数修改列表。例如在上面的程序中,如果需要保留原来的未打印的设计列表以供备案,那么就不应该让函数修改列表。为了实现这个目的,可以向函数传递列表的副本而非原件。要将列表的副本传递给函数,可以使用列表的切片表示法:

print_models(unprinted_designs[:], completed_models)
1
不过,给函数传递列表副本将会降低程序运行效率,尤其是在处理大型列表时。因此除非有充足的利用,否则还是应该将原始列表传递给函数。

3.4.5 传递任意数量的实参
有时候,预先不知道函数需要接受多少个实参,不过好在 Python 允许函数从调用语句中收集任意数量的实参。

下面是一个模拟制作比萨的程序,形参名 * toppings 中的星号表示创建一个名为 toppings 的空元组。此外,这个程序结合使用了位置实参和任意数量的实参。为了让函数正确接收参数,应当把接收任意数量实参的形参放到参数列表的*后。

def make_pizza(size, *toppings):
“””概述要制作的比萨。”””
print(f”\nMaking a {size}-inch pizza with the following toppings:”)
for topping in toppings:
print(f”- {topping}”)

make_pizza(16, ‘pepperoni’)
make_pizza(12, ‘mushrooms’, ‘green peppers’, ‘extra cheese’)
————————————————————————
Making a 16-inch pizza with the following toppings:
– pepperoni

Making a 12-inch pizza with the following toppings:
– mushrooms
– green peppers
– extra cheese

在上面的程序中,函数需要接收任意数量的实参,但尚且知道接受的是怎样的信息:比萨的尺寸及配料。有时,函数不仅需要接受任意数量的实参,而且预先也不知道传递给函数的会是怎样的信息。在这种情况下,可将函数编写成能接受任意数量的键值对——调用语句提供了多少就接受多少。下面的程序演示了创建用户的简介:

def build_profile(first, last, **user_info):
“””创建一个字典,其中包含获悉的有关用户的一切。”””
user_info[‘first_name’] = first
user_info[‘last_name’] = last
return user_info

user_profile = build_profile(‘albert’, ‘einstein’,
location=’princeton’,
field=’physics’)
print(user_profile)
————————————————————————
{‘location’: ‘princeton’, ‘field’: ‘physics’, ‘first_name’: ‘albert’, ‘last_name’: ‘einstein’}

上述程序中的函数要求必须提供名和姓,同时允许调用者根据需要提供任意数量的名称值对。形参 **user_info 中的两个星号表示创建一个名为 user_info 的空字典,并将收到的所有名称值对都放到这个字典中。显然,为了创建键值对,在向形参 **user_info 传递实参时应使用关键字实参。

3.5 函数的存储及编写规范
3.5.1 将函数存储在模块中
使用函数可以将代码块与主程序分离,通过给函数指定描述性的名称,可以让主程序更加容易理解。进一步地,可以将函数存储在被称为模块的独立文件中(扩展名为. py),再将模块导入到主程序中。Python 语言使用 import 保留字实现引用功能。

3.5.2 使用 import
如果要导入整个模块可以使用如下语句:

import <模块名称>

引用整个模块之后,采用 <模块名称>.<函数名称>() 的方式调用具体的函数。

如果需要从模块中导入特定的函数,可以使用下面的语句:

from <模块名称> import <函数名> # 从模块中调用指定函数
from <模块名称> import <函数名 1>, …, <函数名 N> # 从模块调用任意数量的函数

使用这种引用方式,不再需要 <模块名称>. 作为前导,而是使用 <函数名>() 的形式直接调用模块中的函数。

如果要导入的函数名称可能与程序中现有的名称冲突,或者函数的名称太长,可指定简短而独一无二的函数别名:

from <模块名称> import <函数名> as <函数别名>

使用这种方式后,在程序中使用 <函数别名>() 的形式即可调用函数。

as 除了可以给函数指定别名,还可以给模块指定别名:

import <模块名称> as <模块别名>

在调用时采用 <模块别名>.<函数名>() 的形式调用模块中的函数。这种做法比给函数指定别名会更好,因为模块名通常无关紧要,而函数名则指明了函数的功能。对于理解代码而言,函数名比模块名更重要。

如果要导入模块中的所有函数,使用 * 运算符即可完成该功能:

from <模块名称> import *

此,使用 <函数名>() 的形式即可调用模块中的任意函数。不过,使用并非自己编写的大型模块时,*好不要采用这种导入方法。这是因为如果模块中有函数的名称与当前项目中使用的名称相同,将可能导致错误:Python 可能遇到多个名称相同的函数或变量,进而覆盖函数,而不是分别导入所有函数。

*佳的做法是,要么只导入需要使用的函数,要么导入整个模块并使用句点表示法。

3.5.3 函数的编写规范
编写函数时,应当遵循以下的规范:

为函数指定描述性名称,且只在其中使用小写字母及下划线。

每个函数都应包含阐述功能的简要注释。该注释应紧跟在函数定义后,并采用文档字符串格式。

给形参指定默认值时,等号两边不要有空格。对于函数调用中的关键字实参,也应遵循这种约定。

如果程序或模块包含多个函数,使用两个空行将相邻的函数分开。

所有 import 语句都应放在文件开头,除非文件开头使用了注释来描述整个程序。

如果形参很多,导致函数定义长度超过了 PEP 8 建议的代码行长,可在函数定义中输入左括号后按回车键,并在下一行按两次 Tab 键,从而将形参列表和只缩进一层的函数体区分开。

def <函数名>(
<参数 1>, <参数 2>,
<参数 3>, <参数 4>,

):

企业采用混合云的好处

混合云可以帮助弥合不同数据源之间的差距,并允许企业更好地利用他们收集的信息。这些只是混合云具备的各种优点的其中两个。

在分析当前趋势时,很明显,社交软件和移动应用更可能对买方参与方式产生影响。因此,企业有必要相应地改造以适应变化。随着所有这些变化,企业需要确保其功能的连续性顺利进行。为此,他们需要创建一个环保,可扩展,额外的敏捷IT基础设施。这就是混合云解决方案发挥作用的地方。

混合云具有反映用于动态IT设置的架构框架的能力。这种模式将有能力处理在供应和利用前景中可能出现的各种不可预测的波动。混合云解决方案还将提供增强的灵活性,以根据每个企业变革中的增长方式进行调整,并将在部署方式的组合中呈现统一的设置。这可以提高其响应速度和运营敏捷性。

由于这些原因,混合云解决方案已成为大多数组织所采用的*佳策略,而这些组织需要在短时间内回应更改的买方期望。

为了了解混合云解决方案对企业带来的影响,重要的是要清楚地了解这种创新技术的基础。混合云将整合传统IT以及管理,私有云或公共云的混合环境。混合云将转变为数字计算环境,将公共云中的不同企业混合在一起。这可以给环境的混合物赋予生命,这可以帮助系统在短时间内响应转移体验需求的状态。

拥有混合云解决方案的企业可以考虑使用中间数据来处理买方交易。所有这些交易将链接到一个公共云,它有一个基于Web的前端。这样可以方便在线购买商品。客户支持也可以集成到混合云解决方案。在高峰假期期间,计算活动需要额外的资源,并且它们可以从公共云获取。正如人们所看到的,企业可以自由地*大限度地利用云服务,以及时获得适当的工作负载的帮助。

行业专家表示,如今,很多传统公司被那些使用分析,知识和应用科学的企业所赶超。企业将能够在混合云基础架构的帮助下获得可盈利的分析技术,这可能适合那些工作量增加和需要大量的专业知识才能得以生存的企业。

混合云解决方案能够推动所有更高级的企业选择以及从各种数据点获得的所需分析。这些来源可能来自完全不同的程序,这些进程的结果将会迅速获得。

如今,企业需要分析他们从多个来源获得的各种信息。在分析信息之后,他们需要利用认知计算能力和高生产力的先进技术。混合云就是在这种情况下所提供的完美解决方案,因为它可以为大数据分析提供革命性和简化的基础。