C_Meng PSNA

Never wait for the storm to pass, just dance in the rain.

0%

2019年十大战略技术趋势

趋势5:赋能边缘

边缘计算描述了一种计算拓扑结构,其中信息处理、内容收集和传递更靠近这些信息的源和存储库。边缘计算借鉴了网格网络和分布式处理的概念。它试图将流量和处理保持在本地,目标是减少流量和延迟。因此,边缘内容交付的概念已经存在很多年了。“在哪里处理数据”的钟摆在高度集中的方法(如大型机或集中云服务)和更分散的方法(如PC和移动设备)之间摇摆。连接和延迟挑战、带宽限制以及嵌入在边缘的更大功能都有利于分布式部署模型。处理能力的优势和在超尺度下运行的低成本,加上管理和协调数千个地理上分离的端点的复杂性,有利于集中化模型。

当前对边缘计算的大部分关注来自于物联网系统向特定行业(如制造业或零售业)的嵌入式物联网世界提供断开连接或分布式功能的需求。拓扑的广泛应用以及明确的应用和网络体系结构还不常见。需要扩展系统和网络管理平台,以包括边缘位置和边缘功能特定技术。边缘计算解决了许多紧迫的问题,例如高广域网成本和不可接受的延迟。边缘计算拓扑结构将使数字业务和IT解决方案在不久的将来具有独特的优势。

边缘计算和云计算是互补的概念

趋势6:沉浸体验

到2028年,用户体验将经历用户对数字的感知方式的重大转变。
世界以及他们如何与之互动。对话平台正在改变人们与数字世界互动的方式。虚拟现实(VR)、增强现实(AR)和混合现实(MR)正在改变人们对数字世界的感知方式。这种感知和交互模式的结合转变将带来未来的沉浸式用户体验。这种模式将从一个懂技术的人转变为一个懂技术的人。翻译意图的负担将从用户转移到计算机上。通过许多人的感官与用户交流的能力将为传递细微信息提供更丰富的环境。

VR and AR

虚拟现实和现实现实是分开的,但相关的技术。MR扩展了两种方法,以更强大的方式将物理世界结合起来。体验的视觉方面很重要,但其他感官模型也很重要,如触觉(触觉反馈)和声音(空间音频)。特别是在MR中,用户可以与数字和现实世界中的对象交互,同时在物理世界中保持存在。

虚拟现实提供了一个计算机生成的三维环境,它围绕着一个用户,以一种自然的方式响应一个人的行为。这通常是通过一个身临其境的头戴式显示器(HMD),阻止用户的整个视野。手势识别或手持控制器提供手和身体跟踪,并可结合触摸敏感反馈。位置跟踪使一个或多个参与者能够在没有位置的房间中行走。基于房间的系统提供了更深的沉浸感,为多个参与者提供了一种3D体验,或者一个人可以在没有房间的房间里行走。

增强现实是以文本、图形、视频和其他与现实世界对象集成的虚拟增强的形式实时使用信息。它是使用HMD或移动设备呈现的。虚拟世界元素在现实世界背景上的叠加将AR与虚拟现实区分开来。增强现实旨在增强用户与真实物理环境的交互,而不是将它们与实际物理环境分离。这个定义也适用于MR。一般来说,MR使人们能够与虚拟对象交互。


摘译自:https://www.gartner.com

2019年十大战略技术趋势

趋势3:AI驱动开发

人工智能驱动的开发探索了将人工智能功能嵌入应用程序的工具、技术和最佳实践的演变。它还探讨了如何使用人工智能创建开发过程中使用的人工智能驱动工具。

这一趋势正沿着三个维度发展:

  • 用于构建人工智能解决方案的工具正在从面向数据科学家的工具(人工智能基础设施、人工智能框架和人工智能平台)扩展到面向专业开发人员社区的工具(人工智能平台和人工智能服务)。
  • 用于构建人工智能供电解决方案的工具本身被赋予了人工智能驱动能力,帮助专业开发人员并自动化与人工智能增强解决方案开发相关的任务。
  • 特别是,支持人工智能的工具正在从帮助和自动化与应用程序开发(AD)相关的功能发展到利用业务领域专业知识进行增强,并自动化更高层次的广告流程堆栈(从一般开发到业务解决方案设计)活动。

趋势4:数字孪生

数字孪生是指现实世界实体或系统的数字表示。数字孪生兄弟的实现是一个封装的软件对象或模型,反映了一个独特的物理对象。来自多个数字孪生兄弟的数据可以在多个现实世界实体(如发电厂或城市)中聚合为一个复合视图。对现实世界中的实体或系统进行数字表示的概念并不新鲜。它的传统可以追溯到计算机辅助的物理资产设计表示或个人客户的配置文件。数字双胞胎最新迭代的区别在于:

  • 模型在于它们如何支持特定的业务结果的健壮性
  • 数字孪生兄弟与现实世界的链接,可能实时监控
  • 应用先进的大数据分析和人工智能来推动新的业务机会
  • 与他们互动并评估“假设”情景的能力

在物联网项目的背景下,数字孪生正在引起人们的兴趣。精心设计的数字孪生资产可以显著提高企业的决策能力。它们与现实世界中的对应物相关联,用于了解事物或系统的状态、响应变化、改进操作和增加价值。


摘译自:https://www.gartner.com

关键发现:

  • AI开启了数字业务的新方向
  • 我们对技术的感知和互动方式正在发生根本性的转变
  • 事物和流程的数字化正在更多的被用于监控、分析和控制真实世界的环境
  • 确定技术趋势并依据对业务的潜在影响排列优先级可以创造竞争优势

建议:

通过技术创新进行业务转型的公司架构和技术创新领导者必须:

  • 探索基本上可以通过AI驱动的自主功能为组织内的任何物理设备或客户环境提供支持的方式
  • 与高级商业领袖一起教育,参与和思考他们的战略相关优先事项以及AI可以自动化或增强人类活动的地方
  • 开发和部署混合平台,将对话交互与虚拟,增强和混合现实相结合,以针对目标用例创建身临其境的用户体验
  • 通过开发和优先处理有针对性的高价值业务案例来构建物理事物和组织流程的数字双胞胎,从而支持物联网计划
  • 在量子计算仍处于新兴状态时,了解并监控它。 找出具有潜力的现实问题并评估其对安全的可能影响

战略规划预测

到2021年,10%的新车将具有自动驾驶功能,而2018年则不到1%。
到2020年,公民数据科学家的数量将比专家数据科学家的数量增长快五倍。
到2022年,至少40%的新应用程序开发项目将在团队中拥有人工智能联合开发人员。
到2021年,一半的大型工业公司将使用数字双胞胎,使这些组织的效率提高10%。
到2028年,存储,计算和高级AI和分析技术将扩展边缘设备的功能。
到2022年,70%的企业将尝试使用沉浸式技术进行消费和企业使用,25%的企业将其部署到生产中。
到2030年,区块链将创造3.1万亿美元的商业价值。
到2022年,超过50%在工业4.0生态系统中合作的人将使用虚拟助手或智能代理与周围环境和人们进行更自然的交互。
到2021年,那些绕过隐私要求并且缺乏隐私保护的组织将比遵守最佳实践的竞争对手支付高出100%的合规成本。
到2023年,20%的组织将为量子计算项目编制预算,而2018年则不到1%。

分析

数字化转型会导致企业不断更新其业务模型。企业领导需要接受并鼓励不断的改变,这也是在未来变化世界中的成功之道。

在未来,所有的智能设备和智能终端会组成一个“智能数字网”,这会成为一个颠覆性的技术趋势,所有的创新型公司都要做好准备应对。智能数字网的三个核心主题:

  • 智能。智能主题探讨了AI,特别强调机器学习,如何渗透到几乎所有现有技术并创建全新的技术类别。
  • 数字。数字主题专注于融合数字和物理世界,以创造自然和身临其境的数字增强体验。
  • 网络。网络主题主要开发人、业务、设备、内容、服务等之间的联系。

2019年十大战略技术趋势

趋势1:自主事物

自主事物通过AI来自动化执行原本由人类执行的行为。不同于之前死板的程式化的自动化,自主事物可以更好的在人类环境下进行更自然的交互。

自主物理事物and自主虚拟事物

自主物理事物的应用:

  • 巡逻机器人
  • 高级农业
  • 更安全的载具运输

自主虚拟事物的应用:

  • 虚拟个人助理
  • 独立代理

自主能力的范围

  • 人工辅助
  • 部分自动化
  • 条件性自动化
  • 高级自动化
  • 全自动化

自主、智能、协调

  • Intel在2018年冬奥会开幕式上使用无人机群
  • 迪拜警方准备使用自己部署的无人机盯梢
  • 自主智能汽车可以互相通讯协调以优化城市交通
  • 群智智能助理可以通过集成多终端数据满足复杂需求
  • 多代理之间的自动协调可以是IT操作变得更加流畅和安全

趋势2:增强分析

增强分析包括:

  • 增强数据准备。它使用机器学习自动化来增强数据分析和数据质量,协调,建模,操作,丰富,元数据开发和编目。
  • 增强分析。这使得业务用户和公民数据科学家能够自动查找,可视化和叙述相关发现,而无需构建模型或编写算法。
  • 增强数据科学和机器学习。它使用AI来自动化数据科学和机器学习/AI建模的关键方面,例如特征工程,模型选择(自动机器学习[autoML]),模型操作,解释,调整和管理。

赋能民间数据科学家

到2020年,民间数据科学家的数量将比专业数据科学家的数量的增长快五倍。

在民间数据科学家之上

更多地使用机器学习以及自动化和人工增强模型将意味着更少的偏差。它将减少用户浏览数据所花费的时间,使他们有更多时间根据数据采取最相关的见解。它还将使一线工作人员能够获得更多情境化的分析见解和指导性建议,以改进决策和行动。

行动起来

  • 接受增强分析作为数据化转型策略的一部分
  • 通过增强分析寻找机会
  • 开发一种定位增强分析的影响的策略

摘译自:https://www.gartner.com

ABSTRACT

这份宣言的主要内容

  • 确定阻碍现实世界中服务计算发展和潜在实现的主要障碍
  • 提出服务计算的研究方向
  • 制定路线图,使服务计算领域能够重新定义自己和 成为社会和经济活动的强大引擎之一。

推荐关注于4个主要研究方向

  1. 服务设计 service design
  2. 服务集成 service composition
  3. 基于众包的信誉 crowdsourcing based reputation
  4. 物联网 the Internet of Things

BACKGROUND

服务计算的定义

我们将服务计算(或者称为面向服务的计算)定义为:探索或开发为服务提供广泛支持的计算抽象、计算架构、计算技术和计算工具的学科。

We define service computing (alternatively termed service- oriented computing) as the discipline that seeks to develop computational abstractions, architectures, techniques, and tools to support services broadly.

服务计算的来源

在计算的早期阶段,面临的挑战是以机器可读的格式表示信息,该格式由位和字节组成,称为数据。 随着时间的推移,人们对用意义补充数据产生了浓厚的兴趣,从而将其转化为信息。随着计算技术的进一步发展,人们开始在信息中加入推理,从而产生了知识。最近,对更高抽象级别的需求导致了向知识添加行动,从而产生服务的概念。

服务计算的目标

服务计算的最终目标是弥合IT和业务服务之间的差距,使IT服务能够更有效地运行业务服务。

The ultimate goal of service computing is to bridge the gap between IT and business services to en- able IT services to run business services more effectively and efficiently.

服务计算的目标是利用服务范例的功能和简单性及其功能和非功能组件来构建模块化软件应用程序,并为选择和组合服务提供更高级别的抽象,从而将其提升到第一类对象状态。

服务计算的相关机构和会议

为了自动化组合服务资源,以根据用户的目标和偏好提供定制的IT服务,标准化机构,如万维网联盟(W3C)和结构化信息标准促进组织(OASIS),已经为实施服务系统领导了规范和标准化工作。

服务计算的挑战

现有的Web服务标准和技术无法为关键新兴领域的计算需求提供足够的支持,包括移动计算,云计算,大数据和社交计算。这些是IDC命名的第三平台的四项关键技术,目前正在影响全球业务的格局。

服务计算和SOA的区别

面向服务的体系结构(SOA)是一种独立于技术的框架,用于定义,注册和调用服务。

服务计算比SOA更广泛,包括对较低级别的服务数据管理和分析的业务流程建模,管理和分析的上层。

SOA已成为服务计算的核心概念,并为实现服务计算提供了基础技术。

服务计算和传统计算的区别

  1. 服务计算的驱动因素是将服务计算与技术分离,以实现面向服务的系统,充分利用服务计算的承诺和期望
  2. 这项工作强调服务计算对计算新兴趋势的贡献和影响

CHALLENGES IN SERVICE COMPUTING RESEARCH

当前的服务计算研究主要集中在七个问题领域:架构,规范语言,协议,框架,生命周期,服务质量,以及跨越自治企业边界建立信任和声誉。

current service computing research focuses mostly on seven problem areas: architecture, specification languages, protocols, frameworks, lifecycle, quality of service, and the establishment of trust and reputation across the boundaries of autonomous enterprises.

服务计算中经常被忽视的战略挑战是分析为什么服务计算尚未在现实世界中发挥其全部潜力,以及需要采取哪些措施来改变这一点。

一项重大挑战是实现在不同平台上工作的多个组织的无缝合作,以满足消费者的需求。

我们确定了服务计算中的四个新兴研究挑战:服务设计,服务组合,基于群体的声誉和物联网(IoT)。

We identify four emerging research challenges in service computing: Service Design, Service Composition, Crowdsourcing-Based Reputation, and the Internet of Things (IoT).

Challenges in Service Design

服务设计是关于对服务性质及其关系的正式理解的映射。

现有设计方法:

  1. 通常不会考虑到服务系统固有地将自治部件集合在一起这一事实
  2. 没有任何全面的理论框架来定义和分析Web上复杂的服务系统

Challenges in Service Composition

由于需要对大规模的Web和云服务进行组合,有以下几个挑战:

  1. 准确有效地从这些大型存储库中搜索服务正成为一个至关重要的挑战
  2. 现有服务选择,组合和推荐方法都是在假设静态数据环境下运行的,这是不充分的
  3. 从众多不断变化的设备和服务中选择和组合服务,以实时和上下文感知的方式满足用户需求
  4. 基于社会关系的服务构成构成了根本的严峻挑战

Challenges in Crowdsourcing-Based Reputation

  1. 众包的质量。鉴于声誉受到若干相关因素的影响,因此强烈需要预测众包声誉的结果。目前尚不清楚这些因素如何影响众包的质量。
  2. 众包贡献者的可信度。一些服务用户的意见可能是不公平的,甚至是对特定服务产品的恶意。
  3. 测试平台。对设计适当的评估指标以比较服务的信任和信誉模型存在强烈需求。

Challenges in the IoT

物联网(IoT)是一个新兴和有前景的领域,它建议将每个有形实体转变为互联网上的一个节点。

物联网提出了两个基本挑战:(1)与事物的沟通(2)事物的管理。

一个挑战是资源有限,传统标准(如SOAP和BPEL)太庞大,无法应用于物联网。 此外,由于架构差异,现有的服务组合模型不能直接用于物联网互操作。与单类型Web服务组件模型(即,服务)相反,IoT组件模型是异构的和多层的(例如,设备,数据,服务和组织)。与传统设置相比,组件的所需功能更具动态性和上下文感知能力。

与服务计算相关的基本物联网挑战包括:

  1. 持续维护物联网设备的网络个性和环境。 特别是,物联网事物需要具有反映其物理空间的Web身份和Web表示(例如,Web代理)。 他们还需要在社交,环境,以用户为中心和应用程序环境中进行连接和通信,并且需要维护和管理此类上下文。
  2. 不断发现,集成和(重新)使用物联网事物及其数据。 具体而言,物联网环境是一个联合环境,其中事物及其数据,云服务和IT服务(例如,用于数据分析和可视化)通常由具有不同接口的独立提供商以及业务,成本提供。 和QoS模型。 为了提供新的互联网规模的服务,物联网必须(重新)使用他人部署的物联网和其他人为自己的目的收集的数据。

SERVICE COMPUTING RESEARCH ROADMAP

Service Design

服务系统的设计应建立在正式的服务模型之上,以便能够有效地访问具有不同功能的大型服务空间。

服务模型支持不同服务及其操作之间的依赖关系非常重要。

总之,满足上述要求的正式服务模型将成为通过服务提供高效透明的计算资源访问的中心,这是充分发挥服务计算潜力的关键一步。

特别是,服务的三个关键特征至关重要:功能,行为和质量。 功能由服务提供的操作指定; 行为反映了如何调用服务操作,并由服务操作之间的依赖性约束决定; 质量决定了服务的非功能特性。

Service Composition

几个研究方向:

  • 大规模的Web和云服务组合。 服务组合研究应扩展到由纯文本描述的非WSDL描述的服务或服务。
  • 大数据驱动的服务组合。当前大数据研究的一个重要主题是开发在线处理数据的算法和模型
  • 基于社交网络的服务组合。大规模社交网络中的服务选择,推荐和组合应该结合社交网络和复杂的网络分析方法以及信任计算技术。 一个有希望的方向是结合记录服务用户与服务数据的交互的社交网络数据,以检测服务之间的隐藏关系并生成潜在的服务组合。可以通过捕获用户个人判断的社交媒体服务来提取反映用户选择和组合服务的兴趣的特定于域的质量特征

云计算环境为部署服务提供了一个有吸引力的选择,因为它提供了潜在的可扩展性和可访问性。 但是,它引入了与以下问题相关的问题:

  1. 维护 - 资源不受服务提供商的明确控制。
  2. 安全性 - 云可能不在服务提供商的企业边界内。
  3. 服务级别协议(SLA) - 资源分配是云提供商的责任。 例如,服务可能不可用,不仅是由于服务提供商的更新,还因为云提供商的更新。

Crowdsourcing-Based Reputation

  • 众包的质量。应进行社会研究,以调查这些利益因素对众包可靠性的影响以及众包贡献者的范围。这两种因素,例如社会关系和个人偏好,可以同时相互影响。 未来的研究应该针对如何模拟两组因素之间的相互关系以及如何将它们整合起来预测它们对众包数据质量的影响。
  • 众包贡献者的可信度。还应探索用于选择具有不同成本和可信赖的众包用户的权衡策略。

Internet of Things

物联网研究的新方向在于设备发现和集成领域。一个有趣的方向是多跳连接,它利用人与物之间的相互作用来关联物联网事物。

CONCLUSION

服务计算拥有光明的未来,支持新兴计算领域的巨大进步,如移动计算,云计算,大数据,社交计算等。 我们在本宣言中提出,服务计算的潜力远远大于迄今为止所取得的成就。 我们为将服务计算提升到创新的新高度铺平了道路。 为了开拓进取,我们做出了一个重要的声明,即,要使服务计算范例取得成功,就需要将其与当时的技术分离开来。 挑战可能很困难,但收益很大,没有理由为什么雄心勃勃的研究议程不会给计算机科学和社会带来巨大的好处。

原文链接:http://www.gzjundian.com/show-19-93-1.html

如何能让你的分析报告真正为企业带来价值?如何拉近一套数据与实际生活生产之间距离,做到报告从数据中来、分析到业务中去?今天我们就零售行业中涉及到的三大块业务,探究如何为零售企业做切实有用的分析报告。

众所周知,人、货、场是零售业基本的思维模式。无论是线上还是线下,人、货、场都是零售营运的核心三要素。我们今天的探讨就从零售行业的人、货、场三个维度开始思考。

人包括店铺员工、顾客和第三方人员等;货泛指商品;场指卖场、电子商务的销售平台、渠道等,因此,零售业常用的分析指标有:

人货场只是第一个层次,员工、顾客、卖场、商品等为第二层。

一、“人”的部分

1.销售指标

【成交率】=成交顾客数÷客流量×100%

成交率和店员和销售技巧、产品陈列、产品销售价格、促销价格等都有关系。但是在产品、促销状态等都一致的情况下,成交率就只和店员的销售技巧有关了,所以这个指标可以用来判断店铺员工的销售能力。

【完成率】=销售完成数÷目标数×100%

这是一个判断销售目标进度的一个指标,在人货场三个领域都可以用到。

2.服务指标

【平均成交时长】=每一位顾客成交的时间总和÷成交顾客数

这是一个考察店铺员工效率的指标。一般还需要和客单价结合起来看会比较客观(可以做四象限),用最短的时间成交最高的金额,这样员工一般认为都是最优秀的员工。

【平均接待时长】=接待每一位顾客的时间总和÷接待顾客数

目前需要店铺手动计算这个指标。还有一个指标和平均接待时长类似,就是顾客平均停留时长。区别是前者是从开始接待顾客到离开店铺的时间段计算时长,后者是用顾客进门到出门的时间段来计算的。这两个指标同样不仅仅和“人”有关,还与“场”“货”有关。对于零售店铺来说大部分时候是希望顾客的停留时间越长越好。

【投诉率】=投诉的顾客总数÷顾客总数×100%

3.管理指标

【定编满足率】=实际员工总数÷标准配置人数×100%

这是考核企业招聘能力强弱的一个指标,同时它也是一个内控指标。定编满足率太低势必会影响效率,太高且超过100%又会造成人效的浪费。定编满足率还可以细分为部门定编满足率、普通员工定编满足率、管理层员工定编满足率等。

【员工流失率】=某段周期内流失员工数÷((期初员工总数+期末员工总数)÷2)×100%

员工流失率分月流失率、季度流失率、年流失率等。处在不同周期的流失率是不能直接对比的。人事部经常用的是员工离职率,员工流失率和员工离职率有一点点区别,员工离职指正常人才转移,而员工流失包含不正常人才流失。

【工资占比】=企业支付的员工工资总额÷销售额×100%

4.顾客指标

【客单价】=销售总金额÷有交易的顾客总数

一般用成交总笔数来代替顾客总数,理论上这两个数字是一致的,但是顾客经常会出现逛一次商场多次开单交易的情况,所以成交笔数实际上是大于等于有交易顾客数的。客单价既可以反映顾客的质量,也可以反映店铺员工的销售能力,还可以反映店铺的商品组合等。

【件单价】=销售总金额÷销售总数量

【连带率】=销售总数量÷成交总单数

连带率有不同的称谓,例如附加值、效益比、平均客件数、购物篮系数等。连带率反映的是顾客每次购物的深度。对于超市来说,除了分析常规连带率之外,还可以分析单品连带率、品类连带率,连带率越大说明该单品或品类越重要,需要在陈列、促销、库存管理等方面特别关注。百货行业还可以统计叫品牌连带率的指标,即计算顾客每次购物时平均消费几个品牌的产品。

5.会员指标

【新增会员数】=期末会员数—期初会员总数

如果将会员看成是企业的财富,新增会员就是在不断地积累财富。大部分零售企业会把这一项作为店铺员工KPI考核指标之一。新增会员数的一个附加指标是未办卡率,统计那些达到会员办卡条件却没有开新卡的顾客占比情况,这个指标可以反映店铺开新卡的能力以及顾客对品牌的喜好程度,这是一个分析指标,不建议作为考核治疗。

【会员增长率】=某段时间内新增会员数÷期初有效会员数×100%

会员增长率是体现企业会员增长速度的一个指标。

【会员贡献率】=会员销售总金额÷销售总金额×100%

会员贡献率不是越高越好,在每个企业会有一个合理的区间,太高就显得新增顾客太少,增长被局限了,太低则没有稳定的销售来源。行业不一样这个区间段也会不一样,店铺间也会不一样,例如商业区的店铺和写字楼、社区店铺的会员贡献率都是不一样的。

【有效会员数】

【有效会员占比】=有效会员数÷累积会员数×100%

会员总数多不一定强,有效会员数多才是硬道理。有效会员就是满足一定贸易条件的会员。随着企业的发展,必然会存在很在一段时间内没有交易过的会员,这些会员实际上已经没有任何的价值了,需要在分析中剔除出去,否则会员分析也没有意义。有效会员的贸易条件一般根据时间和交易量来设定,例如在12个月内必须有至少1次消费,6个月内必须有不少于3次消费记录等,这两个设定标准需要结合顾客的消费频率来定,行业不同标准也会有差异。

【会员回购率】=某段时间内有交易的老会员数÷期初有效会员总数×100%

会员回购率一般用在月、季和年度的分析上,是衡量顾客忠诚度的一个指标,严格地说这是一个老会员的回购率公式,因为期间新增会员的回购不包含在其中。

回购率和回头率常被误解为一回事,其实会员回购率和会员回头率是有区别的,回头率公式中的分子应该是某段时间内到达过店铺的会员,他们不一定实施了购物。对于店铺来说,先得让顾客回头,其次才是回购,所以这个两个指标是有先后顺序的。没有高的回头率,哪来的高回购率,所以零售商们都在想尽办法促使会员顾客高频次地回头。

【会员流失率】=某段时间内流失掉的会员数÷期初有效会员总数×100%

这个指标反映了会员顾客的流失速度,也反应了企业营运现状,它和会员增长率是一对相向指标,建议每月都追踪这两个指标。会员流失有它合理的一面,例如对定位在20~30岁的服装品牌来说,顾客年龄变大自然就会流失,再如对超市来说,如果顾客搬家了,流失也是合理的。

会员流失率反应了顾客总量的流失情况,却没有办法反映出流失顾客的质量,流失掉一个客单价为300元和流失掉客单价为3000元的顾客显然不能划等号。这就衍生出一个新的指标,相对会员流失率,公式如下:

【相对会员流失率】=某段时间流失的会员数量÷期初有效会员数×流失率权重值×100%

【流失率权重值】=流失会员的平均客单价÷有效会员的平均客单价

【会员回购频率】

【会员回购频率1】=某段时间内所有会员消费次数÷(期初有效会员总数+期中新增会员数)

【会员回购频率2】=某段时间内所有老会员消费次数÷期初有效会员总数

该指标反映会员顾客在某个时间段内的消费频次,分析这个指标选取合适的时间周期很重要,时间周期太短,这个值基本上就接近为1.0,没有丝毫意义。服装专卖店、手机专卖、电器专卖等可按6或12个月为一个滚动周期,百货商场一般用3或6个月为一个滚动周期,超市可以按1或者3个月来滚动分析。3个月为一个滚动周期并不是数一个季度才分析一次,而是每个月都可以分析。

【会员回购频率3】=某段时间内所有会员消费次数÷期间有交易的会员总数

【会员回购频率4】=某段时间内所有老会员消费次数÷期间有交易的老会员总数

这4个公式各有侧重,公式1或2侧重于研究回购频率的趋势,公司3和4侧重短期会员购物行为分析,零售企业在实践使用时应该以老会员的分析为主。

【平均年龄】=某个事件点会员年龄总和÷有效会员总数

平均年龄是衡量品牌定位的一个标准,不过这个指标收数据源的影响非常大。有很多顾客不愿意提供自己的私人信息,还有就是终端店员不负责任地录入数据,所以在系统中很可能看到上有古稀老人,下有婴儿的年龄数据。分析平均年龄时需要剔除这些异常数据,否则那些90岁以上的顾客就足以把平均年龄拉大好几岁。对年龄的扩展分析是将顾客年龄分段分析,就是年龄分析。
平均年龄属于对顾客基础信息分析的范畴,这个范畴还包括性别、职业、地域、收入等。

二、“货”的部分

正如“人”“货”“场”是零售分析的基本思维模式一样,商品分析也有它的基本模式,这就是“进”“销”“存”,“进”即为采购环节,“销”自然是销售环节,狭义的“存”指商品库存管理环节,广义的“存”指整个商品的供应链管理。人货场是一个平行关系,而进销存却是一个又先后顺序的三角关系,前者是基于业务的分析管理,后者是基于商品的流程管理。大部分零售业的POS系统都是基于进销存的一种软件系统。

某种商品的库存太大、占用资金,我们常常理所当然地认为是采购进货不合理,进得太多,所以采购部经常背黑锅。其实销售环节和供应链环节都会影响库存,例如商品在卖场陈列不合理,仓库发货不及时,盘点错误造成系统显示有库存而实际库存为0等。所以分析商品的问题务必从进销存三个维度进行思考,不能一遇到问题就武断地认为是进销存某个环节的问题。

商品的分析指标很多,常用的如商品的折扣率、动销率、周转率等,还有商品的三度(广度、宽度、深度)等。一般来说大店看重商品的周转,小店看重商品的单词利润,线上看重商品的折扣,线下侧重商品的库存。大家的侧重点不同,不过总体来说商品的分析如图所示。

1.采购环节

(1)采购三度

【广度】

广度=采购的商品品类

广度比=采购的商品品类数÷可采购的商品总品类数×100%

广度关系到商品品类多样化,很多追求消费者一站式购买的卖场就是追求大广度。例如一个服装专卖店,公司当季商品有20个品类,买手实际采购了16个品类,则广度为16,广度比未80%。再比如一个中型超市有200个品类的商品在销售,可供销售的总品类数是300个,则广度为200,广度比为67%。商品的广度体现了商品的丰富程度。广度也不是越大越好,这和零售店铺的消费群体有关,也和营运成本有关,所以最佳的广度是指用最经济的成本且最能满足目标消费群体绝大部分需求的值。

【宽度】

宽度=采购的SKU总数

宽度比=采购的SKU总数÷可采购的商品SKU总数×100%

商品的宽度代表了商品的丰富且可供选择的程度,宽度越大的店铺消费者挑选的余地就越大。而宽度比则是反应和竞争对手宽度、自己目标宽度或上游供应商宽度的对比程度。例如对于一个化妆品专卖店来说,店铺共有1000个SKU商品在销售,而最大的竞争对手同期销售的商品是1500个SKU,则该专卖店商品的宽度为1000,相对于竞争对手的宽度比67%。由于资源局限性,大型超市等一般会限定商品的宽度值,所以就会出现每新增一个商品必须要剔除一个旧品的规定。电子商务网网站则相对宽松一些,他们的陈列没有实体零售店铺的空间限制,所以理想状态下宽度是可以做大无限大。

【深度】

深度=采购的商品总数量÷采购的SKU总数

深度比=深度÷采购目标深度×100%

深度是指平均每个SKU的商品数量,它的意义代表了商品可销售的数量的多少,比如某个服装专卖店某次采购了400个SKU的商品,一共1000件,则深度为2.5。深度越大越不容易缺货,但是也可能会造成高库存。

(2)覆盖度(也叫铺货率)

覆盖度=有某款或品类产品销售的店铺数÷适合销售该产品的总店铺数×100%
商品的覆盖度指标适合连锁性质的公司使用,它是衡量商品铺货率的一个指标,需要注意覆盖度公式的分母不是总店铺数,而是适合销售该产品的总店铺数,二者差距较大。一般来讲,覆盖度越大商品的销售就会越好。

(3)采销匹配度

采销匹配度不是一个具体的指标,它实际上是一种分析方法。通过对比品类、型号、价格等方面在某段销售周期内采购和销售的比重来判断商品销售进度的一种方式。

2.供应链环节

(1)服务指标

【订单满足率】=订单中能够供应的商品数量总和÷订单商品数量总和×100%

例如物流部收到5张订单供1000件商品,由于缺货等原因实际可以发出的商品只有920件,则订单满足率就是92%。这是一个反应仓库缺货状态的指标,对于连锁企业来讲,100%的订单满足率是一个理想状态,一般都达不到。如果真能够做到100%满足率,意味着不但需要预测非常准,还需要增加更多库存来满足突发订单,这样的代价就是仓储成本增加,资金成本增加,这也是一种资源的浪费。

【订单执行率】=能够执行的订单数量÷总订单数量×100%

某天物流部收到100张订单,但是其中10张订单由于缺货或其他原因不能执行,则订单执行率90%。仓库缺货,物流配送(有货但是送不出去)等都会影响这个指标。

订单满足率和订单执行率的区别是,前者计算的是商品数量的满足情况,后者计算的是订单数量的执行情况。后者常常被很多企业作为订单满足率,这其实是不严谨的。订单满足率侧重用来衡量商品库存状况,订单执行率侧重用来衡量储运状况。

【准时交货率】=准时交货的订单数÷能够执行的订单总数×100%

准时交货率是一个反应供应链效率的指标,需要注意的是分母并不是订单总数,而是能够执行的订单总数,对于那些不能执行的订单去计算他们的准时交货率是非常滑稽的一件事。计算准时交货率的前提是先要明确什么是“准时交货”,24小时?48小时?还是根据距离远近区别对待?

【订单响应周期】=系统中收货时确认的时间-系统中下订单的时间

一张订单的处理是从客户在系统中下订单(对于非系统下单的情况,就应该以收到订单的时间来准)开始到确认收货这样的一个完整的流程,这是一个反应供货效率的指标,一般计算平均订单响应周期。需要注意的是,随着新客户的不断增加、客户类型的变化等,平均订单响应周期自然会发生变化。所以平均订单响应周期变长和供应链效率降低并不能划等号,要进一步分析数据突变的原因。

在实际分析过程中还需要结合订单区域、产品类型、客户类型等进行详细分析。

(2)管理指标

【库存周转率】

库存周转率1=出库数量÷((期初库存数量+期末库存数量)÷2)

库存周转率2=销售数量÷((期初库存数量+期末库存数量)÷2)

公式1是从供应链管理角度的指标,公司2是对公司销售周转率的衡量,二者是有区别的。一件商品一般只会被销售一次,但是因为退货回仓库的原因而会有大于1次的出库情况。“((期初库存数量+期末库存数量)÷2)”这部分也可以用评价库存来代替,就是每月的平均库存。用平均库存的好处是营运人员投机取巧拉高周转率的难度加大,有的营运人员会在期初和期末这两个时间节点故意压低库存,甚至是牺牲销售的前提下压低节点库存,如果计算12个月的平均库存则投机难度就非常大了。

【物流成本占比】=物流成本÷((期末库存金额+期中库存金额)÷2)×100%

广义的物流成本包括仓储成本、运输成本、管理成本等。狭义的物流成本仅仅指运输成本,狭义的物流成本占比就是运输成本和所运输的商品总值的比。

【客户投诉率】=客户投诉率=客户投诉订单批次÷订单总数×100%

这个公式很理解,但是在实际操作中缺失错误百出。问题出在公式的分子和分母的不对等上面。

(3)库存指标

【期初库存、期末库存、平均库存】

平均库存=(期初库存+期末库存)÷2

年平均库存还可以直接取每月末库存的平均值,一般财务部习惯用期初加期末除以2的计算方法,销售营运部喜欢用平均库存的算法。

【库存天数】=期末库存金额÷(某个销售期的销售金额÷销售期天数)

库存天数是一个极为重要的库存管理指标,是有效衡量库存滚动变化的量化标准,也是用来衡量库存可持续销售时间的追踪指标。

我们可以用库存天数来判断店铺是否有缺货的风险,某个店铺的安全库存天数是45天,如果实际库存低于这个值则有缺货风险,反之则表示库存过大。这个指标既可以计算整体企业的库存天数,也可以计算每个品类或单品的库存天数,在分析具体问题的时候,常常需要结合起来看。另外,有些企业喜欢用库存周数的概念,实质是一样的,将库存天数除以7即为库存周数。一般来讲快速消费品行业使用库存天数,耐用消费品使用库存周数。

【库销比】=期末库存金额÷某个销售期的销售金额×100%

库销比的销售周期一般取月,也就是月库销比,当然也可以取周,如果是周库销比实际上就是和库存周数一个概念。月库销比在年度同比的时候是有参考价值的,但是在环比时就有问题了,因为每个月的天数是不一致的,有28天、29天、30天和31天4种情况,销售期不同销售金额就会不同,这样的月库销比实际上是没有可比性的。而库存周数和库存天数就不存在这个问题,所以我一般很少用这个指标。

【有效库存比】=有效库存金额÷总库存金额×100%

要计算有效库存比首先需要定义有效库存的标准,有效库存是指能给门店带来销售价值的商品库存,也就是能产生销售贡献的商品库存。从定义上看残次商品、过季商品和没有销售的商品都不属于有效库存商品。不过在实际上的分析过程中有效库存的确会复杂很多,首先需要剔除残次商品、过季商品、一段时间内没有销售的商品,然后再确定一个标准值将有销售的商品分成有效库存和无效库存,这个标准一般以周销售量或月销售量来衡量,并且渠道不同标准是不一样的。

确定有效库存的标准可以利用二八法则来辅助计算,占总销售20%的商品的平均销量值即为有无效库存的分界线。当然也可以人为确定这个分界线的值。

3.销售环节

(1)商品指标

【货龄】=商品的年龄

对于有保质期的商品,例如食品、饮料等,货龄是从生产日期开始计算的,对于没有严格保质期或有效期的商品,例如服装、手机等,货龄应该是从开始上架销售的日期开始计算的。分析货龄目的一是防止商品过期,二是作为制定商品价格调整的依据。货龄越大,库存越高的商品就是价格调整的首选。

【售罄率】=某段时间内的销售数量÷(期初库存数量+期中进货数量)×100%

售罄率是检验商品库存消化速度的一个指标。一般采取期货制订货的企业,如鞋服行业用得比较多,可以随时补货的快速消费品一般不同这个指标。特殊时期的囤货制也可以使用售罄率这个指标,例如包销或买断销售都属于囤货制。根据销售期的不同,一般有周售罄率、月售罄率、季售罄率、季末售罄率等。季末售罄率指整个商品消化期的销售数量和商品的总到货数量的比值。

【折扣率】=商品实收金额÷商品标准零售价金额×100%

商品的折扣率直接影响到企业的利润水平,是企业的生命线,但遗憾的是很多企业只是在财务报表中才有这个数据。财务报表只是一个结果,折扣率更应该是一个营运指标,需要定期追踪它是否正常、分析趋势是否向坏等。

【动销率】=某段周期内销售过的商品SKU数÷(期初有库存的商品SKU数+期中新进商品SKU数)×100%

动销率的统计周期一般是周、月、季度,分析的对象可以是品类、类别、SKU等。动销率属于一个追踪和管理指标,一般传统零售比较重视这个指标,动销率都比较高。但是电子商务由于追求长尾效应,动销率都比较低,不过最近有些电子商务也开始重视这个指标了。

【缺货率】=某个周期内卖场有缺货记录的商品数÷(期初有库存的商品数+期中新进商品数)×100%

对于供应链的缺货分析建议使用【订单满足率】,这里的缺货率主要是针对销售端的缺货,适用于采购部和销售部。注意这个缺货率是分析缺货的商品比率,不是缺货的数量或金额多少(缺货数量和缺货金额很难量化)。缺货率比较难以统计的是缺货记录,POS系统弱的门店只能靠人工统计,软件系统好的客户可以通过设置商品零库存状态用来自动判断是否缺货。库存为0一般是缺货,但是库存大于0的商品也可能是“缺货”状态,因为这里的库存很可能是残次或虚假库存,实际可供销售的库存为0,这种情况比较难以统计,需要人工加系统的方法来识别。缺货率中的销售周期最短可以是1天,最长不建议超过1个月。在计算年平均缺货率的时候可以计算月缺货率的平均值。

(2)结构指标

【品类结构占比】=某品类销售额÷总销售额×100%

【价位段占比】=某价格段销售额÷总销售额×100%

【正价销售占比】=正价商品销售额÷总销售额×100%

正价商品为标准零售价的商品,与之对应的是折扣商品或特价商品。正价商品销售占比越高,企业利润越高。对于促销频率高的行业,以及有议价空间的行业(如手机专卖店)等该指标显得尤为重要,它是员工销售能力和企业管理水平的综合体现。但遗憾的是很多企业只重视折扣率,而忽视了这个指标。

(3)价格体系指标

【商品现值】

商品现值就是商品当前被消费者认可的价值。一台手机刚出来时售价是4000元,一年后消费者可以接受的零售价只有2800元,这个2800元就是这台手机目前的现值。随着时间的流逝,新机型的推出,手机现值还会不断变化着。商品价格会随着时间流逝而变化的商品适合用商品现值的概念来管理,例如服装、手机、食品等。

【价格弹性指数】

价格弹性指数是商品价格变化1%时,商品销量变化的百分比。例如某款商品价格下降1%时,销量就上升5%,则价格弹性指数就是5.0%。价格变动时不光会影响到自身的销量变化,还会影响到竞争对手的销售变化。所以还有一个品牌间的价格弹性指数,品牌A相对于品牌B的价格弹性指数为4.2,这表示品牌A的价格每下降1%便能够从品牌B那里抢到相当于品牌B4.2%的销量,也就是品牌B销售会下降4.2%。确定商品的价格弹性指数最好的方法是最随机测试。

(4)畅滞销分析

【前十大销售及占比】

前十大销售就是在所有商品中销售额或销售量最好的十个商品的总销量,前十大商品占比也就是他们的销售额或销售量占总销售量的比重。这是一个常规分析指标和追踪指标,除了对总销售进行前十大排名分析外,还可以对具体的类别进行同样的分析。

前十大商品销售占比越大,商品销售就越集中,销售管理更容易,但是销售风险也会加大。很多电子商务的卖家非常追求爆款,恨不得前三个商品就能占到公司总销售的80%以上。爆款一般综合毛利都偏低,且一旦生产或物流环节出现状况,对企业的销售影响可能是致命的。

【前十大库存及占比】

和前十大销售及占比概念一样,只是前者是基于销售,后者是基于库存。这是一个库存管理指标,同样是看趋势,看数据是否异常。

【滞销品销售占比】

滞销商品销售占比指的是滞销商品占总销售的比重,同理还可以演化出一个滞销商品库存占比。

4.售后环节

【退货率】

退货率1=某个周期内退货数÷总销售数×100%

退货率2=某个周期内退货单数÷总销售单数×100%

退货率公式非常简单,不过它和【客户投诉率】有一个同样的问题,就是本周期内的退货数并不一定来源于本期内的销售即不含在分母中。处理方法同客户投诉率一样有三种方法:综合处理法(不考虑退货单的来源问题),追踪来源法(将退货单还原到发货期进行分析),剔除法(将非当日退单剔除再计算退货率)。

【特殊服务率】=特殊服务的顾客÷总销售顾客数×100%

有些零售店铺为了提高顾客的体验感,会搞一些特殊的服务活动,例如有的服装专卖店有免费熨洗服务,有些电器商场有以旧换新的服务等,这个指标就是用啦检验这种服务效果的。

【残损率】=残损商品数÷商品总数×100%

残损商品会影响企业和门店的销售和利润,残损率不仅仅是一个分析指标,它更应该是一个追踪指标,并且还应该根据残损商品的来源进行分析,找到残损的主要原因,是仓储残损率高,还是销售渠道残损率高等。

三、“场”的部分

1.销售额

【时段、日、周、月、季度、年】

月销售额指标、季度销售额指标、年销售额指标这是最常用且和绩效挂钩的硬指标。日和时段指标往往不受管理层重视,其实这是不合理的。零售行业的销售是靠一个个时段、一天天追出来的,没有基础指标的完成,谈何月、年指标的完成?

【预测额】

一般分为【日销售预测额】、【月销售预测额】和【年销售预测额】,日销售预测在大型百货商场、超市、电子商务的销售中经常使用,对日销售进行预测,只需要根据历史数据中每日各个时段的销售百分比就可以计算出来。月和年的预测,前面已经讲解过了。

2.追踪指标

【进店率】=进店人数÷路过人数×100%

进店率公式并不难,难的是如何提高进店率,此时各位又可以搬出人货场的思维模式来操练一下。进店率有个系统误差,就是店铺工作人员的进出会影响精度,可以统计工作人员每天大致的重复进店次数然后在进店人数中扣除。

【上楼率】=本层向上的顾客数÷进入本层的顾客数×100%

有5000名顾客进入首层,总共有3000名顾客上到二层及以上楼层,则一层的上楼率为60%。上楼率对多层经营的卖场来说是一个非常重要的指标。

【接触率】

随着科技的发展,管理更多精细化,接触率越来越受零售商重视,通过它可以深层次地了解顾客的购买行为。接触率就是消费者和商品的接触比率。又可以分为试穿率、试用率、触摸率等。

(1)【试穿率】=试穿顾客数÷进店人数×100%

这个指标常用语鞋服行业,目前还没有发现有仪器能监控此指标,大多靠人工统计,需要注意的是同一个顾客无论试穿多少次都只能统计一次。

(2)【试用率】=试用顾客数÷进店人数×100%

这个指标常用于化妆品、食品等行业,如果是封闭销售(例如专卖店)则用进店人数作为分母,不过这些行业大多在超市和百货商场开放式销售,所以进店人数可以转换为有接触的顾客数(例如和促销人员有语言交流的或者是驻足一段时间的顾客),绝对不能轻易用路过人数。

(3)【触摸率】=触摸某商品的顾客数÷路过某商品的人数×100%

触摸率反应商品外观被关注的程度,目前借助一些视频设备可以自动采集这个数据。一般来说某商品的触摸率和成交数量成正比,但是有时候触摸率很高,但是交易很低,作为管理者可能需要分析这种现象产生的原因,为什么消费者有冲动而无行动,出现这种情况很大可能是价格原因。

【成交率】=成交顾客数÷进店人数×100%

【完成率】=完成数÷目标数×100%

完成率根据统计时间段的不同又可以分为实时完成率、滚动完成率、累积完成率、预测完成率。

【大宗交易占比】=大宗购物金额÷总销售额×100%

大宗交易需要企业自己定义何为大宗交易,例如超市可定义单笔成交额大于1万为大宗交易,化妆品和服务专卖店可以定义每次购物数量大于10件为大宗交易等。之所以要监控大宗交易,是因为大宗交易中藏着很多见不得人的交易,而这些交易对渠道和品牌都是伤害。现在很多百货公司的团购部俨然变成了网购批发入口。

很多服装品牌为了维护价格的统一性,会严格控制向非直接客户的发货,而很多网络销售的店主没办法直接从品牌商进货,于是他们选择在店铺做大型促销的时候从零售店铺大量采购,这里面大多会有里应外合的配合,甚至很多零售百货公司会有专人来促进这种交易,大家各取所需。对于很多大型超市,为了冲业绩,采购人员会伙同供应商做虚假交易,首先由超市向供应商下一张大订单,供应商也会发货,不过这批货不会进入超市仓库(采购人员会协调仓库人员做虚拟入仓),直接会以较低的价格卖给如批发市场等渠道,最后采购人员再用这批货款从超市将这批已经不存在的货买出来,这样所有流程走完,采购和供应商都收获了销售额。

3.分析指标

【增长率】=增长数÷基础数×100%=(报告期数-基础数)÷基础数×100%

基础数的选择有三种情况,基础数为同期的数据则是同比,基础数为上一个周期的数据则为环比,和2013年9月的销售额对比就是环比,和2013年1月对比为定基比。这三种情况分别对应同比增长率、环比增长率、相对增长率,前两者是用得最多的。

同比增长率中经常使用同店同比增长率(以下简称同店同比)的概念,即本期和同期在对等条件下(相同的店铺)进行对比。同比增长率体现了企业总体的增长情况,同店同比则可以看出企业绝对增长情况。很多企业的增长率非常高,但是大部分增长都来源于新开门店的增长,靠新开店铺的增长是不可能长期持续的。

4.效率指标

【坪效】

【销售坪效】=销售额÷店铺面积

【利润坪效】=利润额÷店铺面积

坪效是反映店铺单位面积产出的指标,常常纳入KPI考核项目。坪效的使用需要注意已下几点:

(1)计算坪效的最小周期是月,完全没有必须要去计算周、日坪效

(2)如果店铺面积、位置等状态没有发生变化,销售坪效一定和销售成正比,没有必要再去分析坪效趋势。

(3)坪效的对比具有强弱对比性,同一个商场同一楼层的同品类商品具有强对比性,不同品类的对比性会稍微弱一些,不同楼层的不同品类对比又更加弱。同一个商圈的同样业态对比性强,不同的商圈同样业态对比稍弱,不同的商圈不同的业态有可能根本就没有可对比性。同一品牌专卖店在一线城市和三线城市的坪效对比性也不强。所以不要轻易以坪效论营销。

(4)坪效另一个意义在于店铺面积、位置发生变化后进行前后差异的对比分析。

(5)有的企业将坪效用在新开门店销售预估的使用上,这是可以的,但是一定要注意可比性。

【人效】

【销售人效】=销售额÷店铺面积

【利润人效】=利润额÷店铺面积

人效反应的是单人产出,它常常用来管理店铺的人力资源配置、人力成本核算等。

【每平米租金】=租金÷面积

这是用来判断店铺租金相对高低的一个指标。包括每平米日租金、每平米月租金、每平米年租金等

【租金倍率】=销售额÷租金

租金倍率是衡量投入1元租金能产生多少销售额的一个指标。每平米租金由于城市、商圈等差异,没办法直接对比,而租金倍率由于考虑到租金产生的效益则可以直接对比。

5.竞争状况

【市场占有率】

也称市场份额,是指一个企业的销售量或销售额在同类市场产品中所占的比重,它直接反应了消费者对商品的喜好程度,同类市场是一个变化的值,既可以是广义的总体市场,也可以是企业的目标市场,甚至可以是某个商圈或商场。例如含氟牙膏可以和牙膏对比,也可以和含氟牙膏对比,甚至计算它在家乐福或沃尔玛超市中的市场占有率。正因为标准的多样性,市场中才充斥着各种号称自己市场占有率第一的品牌。这个指标一般通过市场调查获得。

【竞品指数】=本公司销售额/量÷竞争对手销售额/量

竞品指数是对市场占有率的一种简化,因为我们大部分时间没有办法统计出同类市场的销售数据,所以只能锚定其中一个或几个对手的数据对比。通过分析竞品指标我们也能大致了解自己品牌的市场占有率走势。

【平均排名】

竞争对手的销售数据也不是很容易拿到的,但是每个商场自己品牌的排名值却比较容易到手,这时就可以计算品牌间的平均排名值,通过分析平均排名的变化也可以侧面了解自己的市场占有率情况。平均排名常常被鞋服、化妆品等行业用来作为对店长、销售主管、区域经理等的考核指标。

6.促销指标

【费销比】=促销费用金额÷促销期间产生的销售额×100%

【目标完成率】=促销期间销售完成数÷促销目标×100%

【同比增长率】=同比增长数÷同期销售额×100%

【促销爆发度】=(促销期间的平均权重销售额-促销后的平均权重销售额)÷促销前的平均权重销售额×100%

【品牌参活度】=参与促销活动的品牌数÷卖场总品牌数×100%

这个指标常常用在百货和超市的促销活动准备期,用来衡量营运经理促销活动时的执行力。对于品牌商可以将此指标修改为单品参活度,例如公司一共有200个SKU产品,五一期间有40个SKU做促销,单品参活度即为20%。十一促销有50个SKU参与,但是总SKU为300个,单品参活度反而降低为16.7%

【会员参与率】=参与促销活动的会员数÷有效会员总数×100%

促销活动前我们一般会通过邮件、短信、微信、电话等手段通知会员顾客,而会员参与度就是用来评估这些手段效果的一个指标。

7.渠道扩展

【净开店率】=(开店数-关店数)÷期初店铺数×100%

【渠道结构占比】=该渠道销售额÷总销售×100%

渠道结构分析是销售分析中最常见的一种分析方式,也是著名的营销4P理论中的一个P(place)。

【重要客户占比】=重要客户销售额÷总销售额×100%

重要客户如何定义是这个指标的关键,有如下几种确定重要客户的方法供参考:

①以销售额的前N名客户作为重要客户,例如前十大客户等

②根据二八法则,以总销售额80%的客户作为重要客户

③根据ABC分析法以A类客户作为重点客户

④根据企业未来战略制定重点客户

单看每个月的重要客户占比没有太大的意义,需要连续观察该数据的走势才有判断的依据,同时需要注意不能经常更改重要客户名单。

四、财务-部分

1.销售利润率

【毛利率】=(销售收入-营业成本)÷销售收入×100%

【纯毛利】=(销售收入-营业成本-费用)÷销售收入×100%

【交叉比率】=商品毛利率×商品周转率

商品周转率=销售收入÷((期初库存值+期末库存值)÷2)

毛利率大,周转次数高的商品是优质产品,但是这种商品是比较少的。很多商家采取薄利多销的策略实际上就是牺牲部分商品的毛利率,从而换取较高的周转率。交叉比率一般以季度、半年、年为计算周期。

2.回款指标

【回款(金额)达标率】=回款金额÷欠款金额×100%

【回款(客户)达标率】=回款客户÷欠款客户×100%

回款考核中的金额达标率和客户达标率两个指标是孪生兄弟,谁也离不开谁。前者确保回款金额的重要性,后者确保回款客户的普遍性。有的企业只考核回款金额达标率,这就有可能造成一些小额欠款客户的款不被收款人员关心,因为对金额回款率的影响极小。

3.贸易条件

【联营扣率】

联营扣率是百货公司为了确保自己的经营利润而和商家合同约定在销售收入中扣除的比率,例如商场某品牌的联营扣率是23%,意味着在商场结款时只能结到销售收入的77%

【租售比】=租金÷销售额×100%

对品牌商来说租售比可以和联营扣率进行对比分析,都是为了取得经营权所需要付出的代价。前面谈到的租金倍率指标实际上是租售比的倒数。

这是个竞争不断加剧的时代,我们必须更加专业的利用数据。数据并不是人们最终需要的东西,他们需要的是信息,是对未来发展的洞察力。

作为数据分析师,最怕你的分析报告没有产生价值,本文的指标可以帮助你在分析零售数据的时候,提高对数据的认识,并真正帮助企业提高运营管理深度。

除此之外,如何从数据中发现商业规则、洞察消费者行为、量化商业价值,都需要数据分析师们拥有能融合商业理解、数据分析并具备从海量数据中发现知识的能力。希望本文章能作为大家学习零售数据分析指标的小手册,随取随用。

译自:https://learnxinyminutes.com/docs/java/

ps:好多类都写到一起了,自己要运行的话记得写到不同的java文件中哦

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
// 导入java.util包中的ArrayList类
import java.io.BufferedReader;
import java.io.FileReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
// 导入java.util包中的Scanner类
// 导入java.security包中的所有类
import java.security.*;
import java.util.function.Supplier;


public class LearnJava {

// 要运行一个java程序,必须要有一个main方法作为入口
public static void main(String[] args) {

///////////////////////////////////////
// 输入/输出
///////////////////////////////////////

/*
* 输出
*/

//通过 System.out.println() 来输出一行数据
System.out.println("Hello World!");
System.out.println(
"Integer: " + 10 +
" Double: " + 3.14 +
" Boolean: " + true
);

//如果输出之后不想换行,可以使用System.out.print()
System.out.print("Hello ");
System.out.print("World");

// /*
// * 输入
// */
//
// //通过Scanner读取输入
// //必须import java.util.Scanner;
// Scanner scanner = new Scanner(System.in);
//
// //读取string输入
// String name = scanner.next();
//
// //读取byte输入
// byte numByte = scanner.nextByte();
//
// //读取int输入
// int numInt = scanner.nextInt();
//
// //读取long输入
// float numFloat = scanner.nextFloat();
//
// //读取oduble输入
// double numDouble = scanner.nextDouble();
//
// //读取boolean输入
// boolean bool = scanner.nextBoolean();

///////////////////////////////////////
// 变量
///////////////////////////////////////

/*
* 变量声明
*/
//通过<type> <name>声明变量
int fooInt;
//声明多个变量:
// <type> <name1>, <name2>, <name3>
int fooInt1, fooInt2, fooInt3;

/*
* 变量初始化
*/

// 通过<type> <name> = <val>来初始变量
int barInt = 1;
// 初始化多个变量:
// <type> <name1>, <name2>, <name3>
// <name1> = <name2> = <name3> = <val>
int barInt1, barInt2, barInt3;
barInt1 = barInt2 = barInt3 = 1;

/*
* 变量类型
*/
// Byte - 8位有符号二进制补码整数
// (-128 <= byte <= 127)
byte fooByte = -100;

// 如果您想将一个字节解释为无符号整数
// 只需要下边这句
int unsignedIntLessThan256 = 0xff & fooByte;
// 下边这句
int signedInt = (int) fooByte;


// Short - 16位有符号二进制补码整数
// (-32,768 <= short <= 32,767)
short fooShort = 10000;

// Integer - 32位有符号二进制补码整数
// (-2,147,483,648 <= int <= 2,147,483,647)
int bazInt = 1;

// Long - 64位有符号二进制补码整数
// (-9,223,372,036,854,775,808 <= long <= 9,223,372,036,854,775,807)
long fooLong = 100000L;
// 数值后边的'L'指示这个变量是long类型
// 没有L的话依然会默认用int存储

// 注意: byte, short, int 和 long 都是有符号的. 也就是说可以为正数或负数
// 没有无符号变量
// 然而,char就是16位无符号的

// Float - 单精度32位IEEE 754浮点数
// 2^-149 <= float <= (2-2^-23) * 2^127
float fooFloat = 234.5f;
// 数字末尾的f 或者 F 是用来标识这个变量通过float进行存储
// 否则就会默认按照double存储

// Double - 双精度64位IEEE 754浮点数
// 2^-1074 <= x <= (2-2^-52) * 2^1023
double fooDouble = 123.4;

// Boolean - true & false
boolean fooBoolean = true;
boolean barBoolean = false;

// Char - 一个16位的unicode字符
char fooChar = 'A';

// final 变量不能被重新赋值
final int HOURS_I_WORK_PER_WEEK = 9001;
// 但是可以稍后初始化
final double E;
E = 2.71828;

// BigInteger - 不可变的任意精度整数
//
// BigInteger是一类数据类型,允许程序员操作超过64位长度的整数
// 这样生成的整数存储为字节组成的数组,并通过内建在BigInteger中的函数进行操作
//
// BigInteger 可以通过一个字节组成的数组或者字符串初始化
String fooByteArray = "1000000000000000000000000000000000000000000";
BigInteger fooBigInteger = new BigInteger(fooByteArray);

// BigDecimal - 不可变的,任意精度的带符号十进制数
//
// BigDecimal包含两个部分:一个任意精度的整数无标度值和一个32位整数标度
//
// BigDecimal允许程序员完全控制十进制舍入
// 建议将BigDecimal与精度值一起使用,并在需要精确小数精度的地方使用BigDecimal
//
// BigDecimal 可以使用int、long、double或String初始化
// 也可以初始化未缩放值(BigInteger)和scale (int)
fooInt = 1;
BigDecimal fooBigDecimal = new BigDecimal(fooBigInteger, fooInt);

//警惕采用float或double的构造函数
//float/double的不准确性也会被拷贝到BigDecimal中
//当您需要精确值时,首选String构造函数
BigDecimal tenCents = new BigDecimal("0.1");

// String:字符串
String fooString = "My String Is Here!";

// \n 是一个转义字符,开始一个新行
String barString = "Printing on a new line?\nNo Problem!";
// \t 是一个转义字符,用于添加制表符
String bazString = "Do you want to add a tab?\tNo Problem!";
System.out.println(fooString);
System.out.println(barString);
System.out.println(bazString);

// 字符串构建
// #1 - 通过加号"+"运算符
// 这是实现它的基本方法(在通过引擎优化)
String plusConcatenated = "Strings can " + "be concatenated " + "via + operator.";
System.out.println(plusConcatenated);
// 输出: 字符串可以通过+运算符连接

// #2 - 通过StringBuilder
//这种方式不会创建任何中间字符串。 它只存储字符串片段,并在调用toString()时将它们连接在一起
//提示:此类不是线程安全的。 StringBuffer是一种线程安全的替代方案(对性能有一些影响)。
StringBuilder builderConcatenated = new StringBuilder();
builderConcatenated.append("You ");
builderConcatenated.append("can use ");
builderConcatenated.append("the StringBuilder class.");
System.out.println(builderConcatenated.toString()); //字符串只在现在构建
// 输出: You can use the StringBuilder class.

// 在完成某些处理结束之前不需要完全构造的String时,StringBuilder非常有效。
StringBuilder stringBuilder = new StringBuilder();
String inefficientString = "";
for (int i = 0 ; i < 10; i++) {
stringBuilder.append(i).append(" ");
inefficientString += i + " ";
}
System.out.println(inefficientString);
System.out.println(stringBuilder.toString());
// inefficientString需要更多的工作来生成,因为它在每次循环迭代时都会生成一个String。
// 使用+进行简单字符串连接,编译后相当于同时调用StringBuilder和toString()
// 使用StringBuilder可以避免循环中的字符串连接。

// #3 - 使用String格式化器
// 另一种创建字符串的替代方法,快速且可读。
String.format("%s may prefer %s.", "Or you", "String.format()");
// 输出: Or you may prefer String.format().


// Arrays:数组
// 必须在实例化时确定数组大小
// 以下格式用于声明数组
// <datatype>[] <var name> = new <datatype>[<array size>];
// <datatype> <var name>[] = new <datatype>[<array size>];
int[] intArray = new int[10];
String[] stringArray = new String[1];
boolean boolArray[] = new boolean[100];

// 声明和初始化数组的另一种方法
int[] y = {9000, 1000, 1337};
String names[] = {"Bob", "John", "Fred", "Juan Pedro"};
boolean bools[] = {true, false, false};

// 索引数组 - 访问元素
System.out.println("intArray @ 0: " + intArray[0]);

// 数组是零索引且可变的
intArray[1] = 1;
System.out.println("intArray @ 1: " + intArray[1]);

// 其他值得一试的数据类型
// ArrayLists - 除了提供更多功能之外的类似数组,且数组长度是可变的
// LinkedLists - 双向链表的实现,全部操作按照双向链表执行。
// Maps - 键对象到值对象的映射。 Map是一个接口,因此无法实例化。 必须在实现类的实例化时指定Map中包含的键和值的类型。 每个键可以仅映射到一个对应的值,并且每个键可以仅出现一次(没有重复)。
// HashMaps - 此类使用哈希表来实现Map接口。 这允许基本操作的执行时间(例如get和insert元素)即使对于大型集合也保持不变。
// TreeMap - 按键排序的映射。 每个修改都维护由实例化时提供的Comparator定义的排序,或者如果它们实现Comparable接口则对每个Object进行比较。 密钥实现Comparable失败以及无法提供Comparator将导致ClassCastExceptions。 插入和删除操作需要O(log(n))时间,因此除非您正在利用排序,否则请避免使用此数据结构。

///////////////////////////////////////
// Operators:运算符
///////////////////////////////////////
System.out.println("\n->Operators");

int i1 = 1, i2 = 2; // 多个声明的简写

// 算数很直接
System.out.println("1+2 = " + (i1 + i2)); // => 3
System.out.println("2-1 = " + (i2 - i1)); // => 1
System.out.println("2*1 = " + (i2 * i1)); // => 2
System.out.println("1/2 = " + (i1 / i2)); // => 0 (int/int 返回 int)
System.out.println("1/2.0 = " + (i1 / (double)i2)); // => 0.5

// Modulo:模运算
System.out.println("11%3 = "+(11 % 3)); // => 2

// 比较运算符
System.out.println("3 == 2? " + (3 == 2)); // => false
System.out.println("3 != 2? " + (3 != 2)); // => true
System.out.println("3 > 2? " + (3 > 2)); // => true
System.out.println("3 < 2? " + (3 < 2)); // => false
System.out.println("2 <= 2? " + (2 <= 2)); // => true
System.out.println("2 >= 2? " + (2 >= 2)); // => true

// 布尔运算符
System.out.println("3 > 2 && 2 > 3? " + ((3 > 2) && (2 > 3))); // => false
System.out.println("3 > 2 || 2 > 3? " + ((3 > 2) || (2 > 3))); // => true
System.out.println("!(3 == 2)? " + (!(3 == 2))); // => true

// 位运算符!
/*
~ 一元位补
<< 带符号左移
>> 带符号/算术右移
>>> 无符号/逻辑右移
& 按位与运算
^ 按位异或运算
| 按位或运算
*/

// 增量运算符
int i = 0;
System.out.println("\n->Inc/Dec-rementation");
// ++ 和 -- 运算符分别表示递增和递减1
// 如果它们放在变量之前,它们会先递增后返回
// 放在变量之后表示先返回后递增
System.out.println(i++); // i = 1, prints 0 (后递增)
System.out.println(++i); // i = 2, prints 2 (先递增)
System.out.println(i--); // i = 1, prints 2 (后递减)
System.out.println(--i); // i = 0, prints 0 (先递减)

///////////////////////////////////////
// Control Structures:控制结构
///////////////////////////////////////
System.out.println("\n->Control Structures");

// if语句和c语言里边差不多
int j = 10;
if (j == 10) {
System.out.println("I get printed");
} else if (j > 10) {
System.out.println("I don't");
} else {
System.out.println("I also don't");
}

// While循环
int fooWhile = 0;
while(fooWhile < 100) {
System.out.println(fooWhile);
fooWhile++;
}
System.out.println("fooWhile Value: " + fooWhile);

// Do While 循环
int fooDoWhile = 0;
do {
System.out.println(fooDoWhile);
fooDoWhile++;
} while(fooDoWhile < 100);
System.out.println("fooDoWhile Value: " + fooDoWhile);

// For 循环
// for 循环声明的结构 => for(<start_statement>; <conditional>; <step>)
for (int fooFor = 0; fooFor < 10; fooFor++) {
System.out.println(fooFor);
// 迭代10次, fooFor 0->9
}
// System.out.println("fooFor Value: " + fooFor); 这句会报错,因为fooFor在for循环内部声明,无法在循环外部调用

// 嵌套的for循环,通过标签退出
outer:
for (int ii = 0; ii < 10; ii++) {
for (int jj = 0; jj < 10; jj++) {
if (ii == 5 && jj ==5) {
break outer;
// 跳出外部的outer循环,而不是只有内部的
}
}
}

// For Each 循环
// for循环还能够遍历数组和通过Iterable接口实现的对象
int[] fooList = {1, 2, 3, 4, 5, 6, 7, 8, 9};
// for each 循环结构 => for (<object> : <iterable>)
// 可以读成: 对于迭代对象中的每个元素
// 注意: 对象类型必须匹配可迭代对象中的元素类型
for (int bar : fooList) {
System.out.println(bar);
//迭代9次并输出1-9
}

// Switch Case
// switch使用byte,short,char和int数据类型
// 它也适用于枚举类型(在枚举类型中讨论)
// String类,以及一些包装基本类型的特殊类:字符,字节,短整数和整数
// 从Java 7及更高版本开始,我们也可以使用String类型
// 注意:请记住,不在任何特定情况下添加“break”会导致其接着执行下一个case(假设它满足所提供的条件)。
int month = 3;
String monthString;
switch (month) {
case 1: monthString = "January";
break;
case 2: monthString = "February";
break;
case 3: monthString = "March";
break;
default: monthString = "Some other month";
break;
}
System.out.println("Switch Case Result: " + monthString);

// Try-with-resources语句(Java 7+)
// Try-catch-finally语句在Java中按预期工作,但在Java 7+中,try-with-resources语句也可用
// Try-with-resources通过自动关闭资源简化了try-catch-finally语句

// 为了使用try-with-resources,先在try语句内包含一个类的实例。 该类必须应用java.lang.AutoCloseable。
try (BufferedReader br = new BufferedReader(new FileReader("foo.txt"))) {
// 你可以试着干一些会抛出异常的事情
System.out.println(br.readLine());
// 在Java 7中,即使抛出了异常,资源也会被关闭
} catch (Exception ex) {
// 在catch语句生效之前,资源就会关闭
System.out.println("readLine() failed.");
}
// 在这个例子中,不需要finally声明,BufferReader就已经关闭了
// 这可以被用来避免在一些边缘情况中,有些finally声明不会被调用的情况
// 了解更多请访问:
// https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html


// 条件语句的简写
// 你可以使用'?'操作符来进行快速分配或逻辑分叉
// 可以解读成 "If (statement) is true, use <first value>, otherwise, use <second value>"
int foo = 5;
String bar = (foo < 10) ? "A" : "B";
System.out.println("bar : " + bar); // 打印 "bar : A", 因为声明foo<10 为 true.
// 或者就简单的这么写
System.out.println("bar : " + (foo < 10 ? "A" : "B"));


////////////////////////////////////////
// Converting Data Types:转换数据类型
////////////////////////////////////////

// 转换数据

// 字符串 到 整数
Integer.parseInt("123");//返回一个整数123

// 整数 到 字符串
Integer.toString(123);//返回一个字符串123

// 对于其他转换,可以看一下下面的类
// Double
// Long
// String

///////////////////////////////////////
// Classes And Functions:类和函数
///////////////////////////////////////

System.out.println("\n->Classes & Functions");

// (Bicycle类的定义在后边)

// 通过new来实例化一个类
Bicycle trek = new Bicycle();

// 调用对象的方法
trek.speedUp(3); // You should always use setter and getter methods
trek.setCadence(100);

// toString 会返回这个对象的字符串表示
System.out.println("trek info: " + trek.toString());

}// main方法的结束
}// LearnJava类的结束


// 您可以在一个.java文件中包含其他非公共外层类,但这不是一个好习惯
// 正确的做法是将不同的类拆分为单独的文件

// Class 声明语法:
// <public/private/protected> class <class name> {
// // 数据字段,构造函数,函数都在里面
// // 函数在Java中称为方法
// }


class Bicycle {

// Bicycle类的字段/变量
public int cadence; // Public: 可以从任何地方访问
private int speed; // Private: 只能从类内部访问
protected int gear; // Protected: 可以从类和子类中访问
String name; // 默认只能从这个包中访问
static String className; // 静态的类变量

// Static block:静态块
// Java没有静态构造函数的实现,但有一个静态块可用于初始化类变量(静态变量)
// 加载类时将调用此块
static {
className = "Bicycle";
}

// Double Brace Initialization:双大括号初始化
// Java语言没有关于如何以简单方式创建静态集合的语法。 通常您最终会使用一下方式:
private static final Set<String> COUNTRIES = new HashSet<String>();
static {
COUNTRIES.add("DENMARK");
COUNTRIES.add("SWEDEN");
COUNTRIES.add("FINLAND");
}

// 但是通过使用一种叫做Double Brace Initialization的东西,可以通过一种更简单的方式实现同样的事情。
private static final Set<String> COUNTRIES2 = new HashSet<String>() {{
add("DENMARK");
add("SWEDEN");
add("FINLAND");
}};
// 第一个大括号是创建一个新的AnonymousInnerClass,第二个大括号是声明一个实例初始化块
// 创建匿名内部类时调用此块
// 这不仅适用于集合,它适用于所有非最终类

// 构造函数是一种创建类的方法
// 这就是一个构造函数
public Bicycle() {
// 你也可以调用另一个构造函数: this(1, 50, 5, "Bontrager");
gear = 1;
cadence = 50;
speed = 5;
name = "Bontrager";
}
// 这是一个带参数的构造函数
public Bicycle(int startCadence, int startSpeed, int startGear,
String name) {
this.gear = startGear;
this.cadence = startCadence;
this.speed = startSpeed;
this.name = name;
}

// Method 语法:
// <public/private/protected> <return type> <function name>(<args>)

// Java类通常为其字段实现getter和setter

// Method 声明语法:
// <access modifier:访问修饰符> <return type> <method name>(<args>)
public int getCadence() {
return cadence;
}

// void方法不需要return
public void setCadence(int newValue) {
cadence = newValue;
}
public void setGear(int newValue) {
gear = newValue;
}
public void speedUp(int increment) {
speed += increment;
}
public void slowDown(int decrement) {
speed -= decrement;
}
public void setName(String newName) {
name = newName;
}
public String getName() {
return name;
}

//显示此对象的属性值的方法
@Override // 从Object类中继承.
public String toString() {
return "gear: " + gear + " cadence: " + cadence + " speed: " + speed +
" name: " + name;
}
} // Bicycle类的结束

// PennyFarthing 是 Bicycle 的一个子类
class PennyFarthing extends Bicycle {
// (Penny Farthings是那些带有大前轮的自行车,这种自行车没有齿轮)

public PennyFarthing(int startCadence, int startSpeed) {
// 通过super调用父类的构造函数
super(startCadence, startSpeed, 0, "PennyFarthing");
}

// 如果要覆盖一个父类的方法,您应该用@annotation标记一下(这里是@Override)
// 了解更多请访问: http://docs.oracle.com/javase/tutorial/java/annotations/
@Override
public void setGear(int gear) {
this.gear = 0;
}
}

// Object casting:对象转换
// 由于PennyFarthing类扩展自Bicycle类,我们可以说PennyFarthing是一个Bicycle并写道:
// Bicycle bicycle = new PennyFarthing();
// 这称为对象转换,其中一个对象被用于另一个对象。 这里有许多细节和处理更多中间概念: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html

// Interfaces:接口
// Interface 声明语法
// <access-level> interface <interface-name> extends <super-interfaces> {
// // Constants
// // Method declarations
// }

// 例子 - Food:
public interface Edible {
public void eat(); // 任何实现此接口的类都必须实现此方法
}

public interface Digestible {
public void digest();
// 从Java 8开始,接口可以有默认方法
public default void defaultMethod() {
System.out.println("Hi from default method ...");
}
}

// 我们现在可以创建一个实现这两个接口的类。
public class Fruit implements Edible, Digestible {
@Override
public void eat() {
// ...
}

@Override
public void digest() {
// ...
}
}

// 在Java中,你只能extend一个类,但是你可以实现多个接口,如下:
public class ExampleClass extends ExampleClassParent implements InterfaceOne,
InterfaceTwo {
@Override
public void InterfaceOneMethod() {
}

@Override
public void InterfaceTwoMethod() {
}

}

// Abstract Classes:抽象类

// 抽象类声明语法
// <access-level> abstract class <abstract-class-name> extends
// <super-abstract-classes> {
// // Constants and variables
// // Method declarations
// }

// 抽象类不能被实例化
// 抽象类可以定义抽象方法
// 抽象方法没有正文并且标记为抽象,非抽象子类必须通过@Override来覆盖来自其超类的所有抽象方法
// 在将重复逻辑与自定义行为相结合时,抽象类可能很有用,但由于抽象类需要继承,因此它们违反了“基于继承的组合”,因此需要组合时请考虑使用其他方法
// https://en.wikipedia.org/wiki/Composition_over_inheritance

public abstract class Animal
{
private int age;

public abstract void makeSound();

// 非抽象方法可以有正文
public void eat()
{
System.out.println("I am an animal and I am Eating.");
// 注意,在这里我们可以获取私有变量
age = 30;
}

public void printAge()
{
System.out.println(age);
}

// 抽象类可以有main函数
public static void main(String[] args)
{
System.out.println("I am abstract");
}
}

class Dog extends Animal
{
// 注意,仍需重写抽象类中的抽象方法
@Override
public void makeSound()
{
System.out.println("Bark");
// age = 30; ==> ERROR! 这里会报错,age是Animal的私有变量
}

// 注意,如果你在这里使用@Override注解会发生错误,因为java不允许重写静态方法
// 这种情况被成为方法隐藏
// 了解更多请访问: http://stackoverflow.com/questions/16313649/
public static void main(String[] args)
{
Dog pluto = new Dog();
pluto.makeSound();
pluto.eat();
pluto.printAge();
}
}


// Final Classes:final类

// Final Class 声明语法
// <access-level> final <final-class-name> {
// // Constants and variables
// // Method declarations
// }

// final类不能被继承,因此最终一定是一个child
// 在某种程度上,final类与抽象类相反,因为抽象类必须被扩展才能使用,而final类不能被扩展
public final class SaberToothedCat extends Animal
{
// 注意,仍需重写抽象类中的抽象方法
@Override
public void makeSound()
{
System.out.println("Roar");
}
}

// Final Methods:final方法
public abstract class Mammal
{
// 如果用final来修饰变量的话,则该变量的值不能被修改,成为常量,如下:
protected final int finalFoo = 0;

// Final Method 语法:
// <access modifier> final <return type> <function name>(<args>)

// final方法和final类一样,不能在子类中被重写
// 因此一定是该方法的最终实现
public final boolean isWarmBlooded()
{
return true;
}
}

// Enum Type:枚举类型
//
// 枚举类型是一种特殊的数据类型,它使变量成为一组预定义的常量。
// 变量必须等于为其预定义的值之一。 因为它们是常量,所以枚举类型字段的名称是大写字母。
// 在Java编程语言中,使用enum关键字定义枚举类型。
// 例如,您可以将星期几的枚举类型指定为:
public enum Day {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
THURSDAY, FRIDAY, SATURDAY
}

// 我们可以像这样使用Day
public class EnumTest {
// enum变量
Day day;

public EnumTest(Day day) {
this.day = day;
}

public void tellItLikeItIs() {
switch (day) {
case MONDAY:
System.out.println("Mondays are bad.");
break;
case FRIDAY:
System.out.println("Fridays are better.");
break;
case SATURDAY:
case SUNDAY:
System.out.println("Weekends are best.");
break;
default:
System.out.println("Midweek days are so-so.");
break;
}
}

public static void main(String[] args) {
EnumTest firstDay = new EnumTest(Day.MONDAY);
firstDay.tellItLikeItIs(); // => Mondays are bad.
EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
thirdDay.tellItLikeItIs(); // => Midweek days are so-so.
}
}

// Enum types(枚举类型) 比我们上边展示的要强大的多
// enum正文可以包含各种方法和字段
// 详细的可以看: https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html

// 现在开始学Lambda表达式
//
// Java8版本的新增功能是lambda表达式。
// Lambda在函数式编程语言中更常见,这意味着它们是可以在不属于类的情况下创建的方法,如同它本身就是一个对象一样传递,并按需执行。

// 最后要注意,lambdas必须通过一个功能接口实现
// 功能接口是仅声明了一个抽象方法的接口
// 它可以有任意数量的默认方法
// Lambda表达式可以用作该功能接口的实例
// 满足要求的任何接口都被视为功能接口
// 您可以阅读更多有关上述接口的资料
//
import java.util.Map;
import java.util.HashMap;
import java.util.function.*;
import java.security.SecureRandom;

public class Lambdas {
public static void main(String[] args) {
// Lambda 声明语句:
// <zero or more parameters> -> <expression body or statement block>

// 我们将在接下来的例子中使用这个hashmap
Map<String, String> planets = new HashMap<>();
planets.put("Mercury", "87.969");
planets.put("Venus", "224.7");
planets.put("Earth", "365.2564");
planets.put("Mars", "687");
planets.put("Jupiter", "4,332.59");
planets.put("Saturn", "10,759");
planets.put("Uranus", "30,688.5");
planets.put("Neptune", "60,182");

// 下边这个例子是一个没有参数,使用了java.util.function.Supplier中的Supplier功能接口的Lambda
// 实际的lambda表达式是在numPlanets =之后出现的内容
Supplier<String> numPlanets = () -> Integer.toString(planets.size());
System.out.format("Number of Planets: %s\n\n", numPlanets.get());

// 一下例子是具有一个参数并使用java.util.function.Consumer中的Consumer功能接口的Lambda
// 这是因为行星是一个Map,它实现了Collection和Iterable
// 此处使用的forEach(可以在Iterable中找到)将lambda表达式应用于Collection的每个成员
// forEach的默认实现表现如下:
/*
for (T t : this)
action.accept(t);
*/

// 实际上lambda表达式是传给forEach的参数
planets.keySet().forEach((p) -> System.out.format("%s\n", p));

// 如果你只有一个参数,也可以写成 (注意p周围的括号没了):
planets.keySet().forEach(p -> System.out.format("%s\n", p));

// 在以上内容中,我们可以看到planets是一个HashMap,keySet()方法返回一个它的键集,forEach将每个元素应用于lambda表达式:(parameter p) -> System.out.format("%s\n", p)
// 每次,该元素被称为“消耗”,并且应用lambda体中引用的语句
// lambda体是在->之后出现的部分

// 上边的语句如果不用lambda写的话会看起来更加传统
for (String planet : planets.keySet()) {
System.out.format("%s\n", planet);
}

// 这个例子与上面的不同之处在于使用了不同的forEach实现:在实现Map接口的HashMap类中找到的forEach
// 这个forEach接受一个BiConsumer,一般来说这是一种奇特的方式,也就是说它处理的是每个Key -> Value对的Set
// 此默认实现表现如下:
/*
for (Map.Entry<K, V> entry : map.entrySet())
action.accept(entry.getKey(), entry.getValue());
*/

// 实际的lambda表达式是传给forEach的参数
String orbits = "%s orbits the Sun in %s Earth days.\n";
planets.forEach((K, V) -> System.out.format(orbits, K, V));

// 上边的语句如果不用lambda写的话会看起来更加传统
for (String planet : planets.keySet()) {
System.out.format(orbits, planet, planets.get(planet));
}

// 或者,如果更严格地遵循默认实现提供的规范
for (Map.Entry<String, String> planet : planets.entrySet()) {
System.out.format(orbits, planet.getKey(), planet.getValue());
}

// 这些例子仅涵盖了lambda的基本用法
// 它可能看起来不是非常有用,但请记住,lambda可以创建为一个对象,以后可以作为参数传递给其他方法
}
}

前言

这篇文章译自:https://learnxinyminutes.com/docs/lambda-calculus/,写的精简了点,理解起来可能有些困难

建议配合让我们谈谈 $\lambda$ 演算.pdf一起食用(出自https://github.com/txyyss/Lambda-Calculus/releases)。这篇不算长,深入浅出,写的也极好。

整体介绍

Lambda演算( $\lambda$ 演算)由Alonzo Church提出,是世界上最简洁的编程语言。尽管没有数字、字符串、布尔值等非函数数据类型,lambda演算还是可以表达任何图灵机。

Lambda演算由三种元素组成:变量(variables),函数(functions),以及应用(applications)。

名称 语法 例子 解释
Variable <name> x 一个名为“x”的变量
Function $\lambda$ <parameters>.<body> $\lambda$ x.x 一个拥有参数“x”以及函数体x的函数
Application <function><variable or function> ( $\lambda$ x.x).a 调用函数“ $\lambda$ x.x”且参数值为“a”

最基础的函数就是恒等函数: $\lambda$ x.x(即f(x)=x)。第一个“x”代表函数的参数,第二个“x”代表函数体。

自由变量vs约束变量

  • 在 $\lambda$ x.x函数中,x被称为约束变量,因为它同时位于函数体和参数中。
  • 在 $\lambda$ x.y函数中,y被称为自由变量,因为它从未被事先声明过。

计算

通过 $\beta$ 规约进行计算,其基本上是词法范围的替代。

在计算表达式( $\lambda$ x.x)a时,我们用“a”替换函数体中出现的所有“x”。

  • ( $\lambda$ x.x)a 计算结果为:a
  • ( $\lambda$ x.y)a 计算结果为:y

也可以创建高阶函数:

  • ( $\lambda$ x.( $\lambda$ y.x))a 计算结果为: $\lambda$ y.a

虽然lambda演算传统上只支持单参数函数,但是我们可以使用一种称为currying的技术创建多参数函数。

  • ( $\lambda$ x. $\lambda$ y. $\lambda$ z.xyz) 即 f(x, y, z) = ((x y) z)

有时 $\lambda$ xy.<body>可与 $\lambda$ x. $\lambda$ y.<body>交替使用。

重要的是要认识到传统的lambda演算没有数字,字符或任何非函数数据类型!

布尔逻辑

在lambda演算中没有“True”或“False”。甚至没有1或0。

取而代之的是:

  • T表示为: $\lambda$ x. $\lambda$ y.x
  • F表示为: $\lambda$ x. $\lambda$ y.y

首先,我们可以定义一个“if”函数 $\lambda$ btf,如果b为True则返回t,如果b为False则返回f

IF 也等同于 $\lambda$ b. $\lambda$ t. $\lambda$ f.b t f

通过使用IF,我们可以定义基础的布尔逻辑运算:

  • a AND b 等同于: $\lambda$ ab.IF a b F
  • a OR b 等同于: $\lambda$ ab.IF a T b
  • NOT a 等同于: $\lambda$ a.IF a F T

注意: IF a b c 本质上是: IF((a b) c)

数字

尽管lambda演算中没有数字,我们可以通过邱奇数编码数字。

任意数字n都可以编码为: $n = \lambda f.f^n$ 。因此:

  • 0 = $\lambda$ f. $\lambda$ x.x
  • 1 = $\lambda$ f. $\lambda$ x.f x
  • 2 = $\lambda$ f. $\lambda$ x.f(f x)
  • 3 = $\lambda$ f. $\lambda$ x.f(f(f x))

为了增加邱奇数,我们使用继承函数s(n)=n+1,即

S = $\lambda$ n. $\lambda$ f. $\lambda$ x.f((n f) x)

通过继承,我们可以定义add:

ADD = $\lambda$ ab.(a S)b

挑战:试着定义你自己的乘法函数!

变得更精致:SKI,SK以及Iota

SKI组合子演算

使S, K, I,分别为以下函数:

  • I x = x
  • K x y = x
  • S x y z = x z (y z)

我们可以将lambda演算中的表达式转换为SKI组合子演算中的表达式:

  1. $\lambda$ x.x = I
  2. $\lambda$ x.c = Kc
  3. $\lambda$ x.(y z) = S ( $\lambda$ x.y) ( $\lambda$ x.z)

以邱奇数2为例子:

2 = $\lambda$ f. $\lambda$ x.f(f x)

对于内部部分 $\lambda$ x.f(f x):

$$\begin{split}
\lambda x.f(f x) &=& S ( \lambda x.f) ( \lambda x.(f x)) (case 3) \\
&=& S (K f) (S ( \lambda x.f) ( \lambda x.x)) (case 2, 3) \\
&=& S (K f) (S (K f) I) (case 2, 1)
\end{split}$$

因此:

$$\begin{split}
2
&=& \lambda f. \lambda x.f(f x) \\
&=& \lambda f.(S (K f) (S (K f) I)) \\
&=& \lambda f.((S (K f)) (S (K f) I)) \\
&=& S ( \lambda f.(S (K f))) ( \lambda f.(S (K f) I)) (case 3)
\end{split}$$

对于第一个参数 $\lambda f.(S (K f))$ :

$$\begin{split}
\lambda f.(S (K f))
&=& S ( \lambda f.S) ( \lambda f.(K f)) (case 3)\\
&=& S (K S) (S ( \lambda f.K) ( \lambda f.f)) (case 2, 3)\\
&=& S (K S) (S (K K) I) (case 2, 3)
\end{split}$$

对于第二个参数 $\lambda f.(S (K f) I)$ :

$$\begin{split}
\lambda f.(S (K f) I)
&=& \lambda f.((S (K f)) I)\\
&=& S ( \lambda f.(S (K f))) ( \lambda f.I) (case 3)\\
&=& S (S ( \lambda f.S) ( \lambda f.(K f))) (K I) (case 2, 3)\\
&=& S (S (K S) (S ( \lambda f.K) ( \lambda f.f))) (K I) (case 1, 3)\\
&=& S (S (K S) (S (K K) I)) (K I) (case 1, 2)
\end{split}$$

合到一起:

$$\begin{split}
2
&=& S ( \lambda f.(S (K f))) ( \lambda f.(S (K f) I))\\
&=& S (S (K S) (S (K K) I)) (S (S (K S) (S (K K) I)) (K I))
\end{split}$$

SK 组合子运算

SKI组合子运算仍可进一步简化。我们可以通过注意I = SKK来移除I组合子。我们可以用SKK替换所有I。

Iota组合子

SK组合子运算依然不是最简洁的。定义:

$$\begin{split}
ι = \lambda f.((f S) K)
\end{split}$$

我们就有:

$$\begin{split}
I &=& ιι\\
K &=& ι(ιI) = ι(ι(ιι))\\
S &=& ι(K) = ι(ι(ι(ιι)))
\end{split}$$

Abstract

purpose

This paper seeks to make sense of the myriad BPM standards, organizing them in a classification framework, and to identify key industry trends.

Design/methodology/approach

Proposed BPM Standards Classification Framework to list each standard’s distinct features, strengths and weaknesses.

Findings

An attempt is made to classify BPM languages, standards and notations into four main groups: execution, interchange, graphical, and diagnosis(lack) standards.

Practical implications

Researchers and practitioners may wish to position their work around this review.

Originality/value

No body did before.

Keywords

Process management, Standards, Work flow

Paper type

Literature review

Introduction

The growth of business process management

Some factors:

  • the rise in frequency of goods ordered;
  • the need for fast information transfer;
  • quick decision making;
  • the need to adapt to change in demand;
  • more international competitors; and
  • demands for shorter cycle times

Software tools supporting the management of such operational processes became known as business process management systems (BPMS).

The proliferation of BPM languages, standards and software systems

Naturally, interest in BPM from practitioners and researchers grew rapidly.

Many new BPM terminologies and technologies are often not well defined and understood by many practitioners and researchers using them.New languages and notations proposed often contain duplicating features for similar concepts, and loosely claim to be based on theoretical formalisms such as Pi-calculus and Petri nets. Most of them have also not been validated, especially in a real business and office environment.

Motivation of this paper

This paper’s goal is to leave the reader with some semblance of order out of a disparate collection of specifications, white papers, journal publications, conference publications and workshop notes to be consolidated as a single paper.

  • discuss and rationalize the terminologies associated with BPM and its standards;
  • systematically categorize/classify BPM standards;
  • discuss the current strengths and limitations of each standard;
  • clarify, the differences of theoretical underpinnings of prominent BPM standards; and
  • explore the gaps of knowledge of current BPM standards and how these may be bridged.

BPM basics

The BPM life cycle

Term Explanation
Process design In this stage, fax- or paper-based as-is business processes are electronically modeled into BPMS. Graphical standards are dominant in this stage.
System configuration This stage configures the BPMS and the underlying system infrastructure. This stage is hard to standardize due to the differing IT architectures of different enterprises.
Process enactment Electronically modeled business processes are deployed in BPMS engines. Execution standards dominate this stage.
Diagnosis Given appropriate analysis and monitoring tools, the BPM analyst can identify and improve on bottlenecks and potential fraudulent loopholes in the business processes. The tools to do this are embodied in diagnosis standards.

BPM vs BPR vs WfM

  • BPM: Business Process Management
  • BPR: Business Process Reengineering
  • WfM: Workflow Management

BPM vs BPR

BPR calls for a radical obliteration of existing business processes, its descendant BPM is more practical, iterative and incremental in fine-tuning business processes.

BPM vs WfM

  • One viewpoint by Gartner research views BPM as a management discipline with WfM supporting it as a technology.
  • Another viewpoint from academics is that the features stated in WfM according to Georgakopoulos et al. is a subset of BPM defined by van der Aalst et al., with the diagnosis stage of the BPM life cycle as the main difference.

BPM theory vs BPM standards and languages vs BPMS

BPMS/BPMSs: Business Process Management Suites

BPM vs service oriented architecture

SOA: Service Oriented Architecture

BPM is a process-oriented management discipline aided by IT while SOA is an IT architectural paradigm.

According to Gartner (Hill et al., 2006), BPM “organizes people for greater agility” while SOA “organizes technology for greater agility”.

Categorising the BPM standards

B2B: business-to-business

  • Graphical standards. This allows users to express business processes and their possible flows and transitions in a diagrammatic way.
  • Execution standards. It computerizes the deployment and automation of business processes.
  • Interchange standards. It facilitates portability of data, e.g. the portability of business process designs in different graphical standards across BPMS; different execution standards across disparate BPMS, and the context-less translation of graphical standards to execution standards and vice versa.
  • Diagnosis standards. It provides administrative and monitoring (such as runtime and post-modeling) capabilities. These standards can identify bottlenecks, audit and query real-time the business processes in a company.

译自:https://learnxinyminutes.com/docs/python3/

阅前须知:

  • “#”后边的是注释
  • 带行号的是python代码
  • 不带行号的是代码的输出
  • 把下边的语句对着敲一边自然就会了,博主用的是jupyter notebook
1
2
3
####################################################
## 6. Classes
####################################################
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# 通过class声明,来创建一个类
# 类内方法中,self为一个保留字,代表类实例化后instance自身
# 类内方法中,cls也是一个保留字,代表类class自身
# 通过self.***可以给类内属性赋值,或调用类内方法
class Human:

# 直接定义的变量,是这个类的共享属性,所有实例都可以访问
species = "H. sapiens"

# __init__是一个保留方法,用于类的实例化(生成实例时自动调用)
# 注意:名称前后有双下划线__,代表这个对象或者属性是python调用、用户定义的
# 这类方法(对象、属性)包括: __init__, __str__, __repr__ etc.
# 这类特殊方法,也被称作(dunder method)
# 不要自己创造这类方法
def __init__(self, name):
# 将参数分配给实例的name属性
self.name = name

# 初始化私有属性,前方带下划线_的属性无法在外部直接访问
self._age = 0

# 这是类的一个内建方法,所有内建的方法都需要把self作为其第一个形式参数
def say(self, msg):
print("{name}: {message}".format(name=self.name, message=msg))

# 另一个方法
def sing(self):
return 'yo... yo... microphone check... one two... one two...'

# @classmethod是一个声明,声明接下来定义的方法是该类所有实例的共享方法
# 这种方法被调用时,必须有cls作为第一个参数
# 类方法的特点在于,可以被类自身调用,如Human.get_species()
@classmethod
def get_species(cls):
return cls.species

# @staticmethod声明接下来定义的是一个静态方法
# 静态方法可以被类单独调用
@staticmethod
def grunt():
return "*grunt*"

# @property就是一个getter,声明该方法用于访问内部属性
# @property这个声明,将age()方法转换为同名的只读属性。
# 但是,不需要在Python中编写琐碎的getter和setter。
@property
def age(self):
return self._age

# 如果还想要让该属性可更改,可以这么写
@age.setter
def age(self, age):
self._age = age

# deleter可以让该属性可删除
@age.deleter
def age(self):
del self._age
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# __name__代表的是运行进程的名称
# __name__ == '__main__',判断用户是否是将该python文件当作主要脚本运行
# 简单来说,if __name__ == '__main__':代码块中的内容
# 只有在运行该python文件时才会生效,如果该python文件是以import形式被调用,则不会运行
# 而写在if __name__ == '__main__':代码块外的内容,被import时,也会运行
if __name__ == '__main__':
# 生成Human类的实例
# 类名加括号,直接调用__init__方法
i = Human(name="Ian")
i.say("hi") # "Ian: hi"
j = Human("Joel")
j.say("hello") # "Joel: hello"
# i and j 是Human类的两个实例
# 调用类方法
i.say(Human.get_species()) # "Ian: H. sapiens"
# 共享属性改了之后,大家都改了
Human.species = "H. neanderthalensis"
i.say(i.get_species()) # => "Ian: H. neanderthalensis"
j.say(j.get_species()) # => "Joel: H. neanderthalensis"

# 类可以调用静态函数
print(Human.grunt()) # => "*grunt*"

# 有些版本中实例是不能调用静态函数的
print(i.grunt())

# 更新实例的属性
i.age = 42
# 获取property
i.say(i.age) # => "Ian: 42"
j.say(j.age) # => "Joel: 0"
# 删除i的age属性
del i.age
Ian: hi
Joel: hello
Ian: H. sapiens
Ian: H. neanderthalensis
Joel: H. neanderthalensis
*grunt*
*grunt*
Ian: 42
Joel: 0
1
2
# 再访问i的年龄就会报错
i.age
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-207-993258cc61d3> in <module>()
      1 # 再访问i的年龄就会报错
----> 2 i.age


<ipython-input-186-b3205f030117> in age(self)
     44     @property
     45     def age(self):
---> 46         return self._age
     47 
     48     # 如果还想要让该属性可更改,可以这么写


AttributeError: 'Human' object has no attribute '_age'
1
2
# 不仅仅是age()没了,_age这个属性是真的没了
i._age
---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-208-4ea879b64970> in <module>()
      1 # 不仅仅是age()没了,_age这个属性是真的没了
----> 2 i._age


AttributeError: 'Human' object has no attribute '_age'
1
2
3
####################################################
## 6.1 继承
####################################################
1
# 继承允许定义新的子类,这些子类从父类继承方法和变量
1
2
3
4
5
6
7
8
9
10
# 使用上面定义的Human类作为基类或父类,我们可以定义一个子类Superhero
# 它继承了类的变量如“species”,“name”和“age”,
# 以及“sing”和“grunt”等方法
# 但superhero也可以拥有自己的属性

# 如果要将文件模块化,您可以将上面的类放在自己的文件中,命名为human.py

# 要从其他文件导入功能,请使用以下格式
# from “filename(不加扩展名.py)” import “函数名或类名”
from human import Human
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 将父类当作参数写进子类定义作为声明
# 如:class child(parent):

class Superhero(Human):

# 如果您想让子类继承父类的所有定义且没有任何修改
# 您可以只使用“pass”关键字(而不使用其他关键字)
# 如
# class Human2(Human):
# pass

# 子类可以重写其父类的属性
species = 'Superhuman'

# 子类自动继承其父类的构造函数(__init__),包括它的参数
# 但也可以定义其他参数或定义并重写其方法
# 此构造函数从“human”类继承“name”参数
# 并且添加“superpower”和“movie”参数:
def __init__(self, name, movie=False,
superpowers=["super strength", "bulletproofing"]):

# 增加新的属性
self.fictional = True
self.movie = movie
# 注意可变的默认值,因为默认值是共享的
self.superpowers = superpowers

# “super”是一个保留函数,该函数允许您访问父类的方法
# 下面的语句将调用父类构造函数:
super().__init__(name)

# 覆盖sing方法
def sing(self):
return 'Dun, dun, DUN!'

# 增加实例方法
def boast(self):
for power in self.superpowers:
print("I wield the power of {pwr}!".format(pwr=power))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
if __name__ == '__main__':
sup = Superhero(name="Tick")

# 通过isinstance方法,可以判断,实例和类的关系
if isinstance(sup, Human):
print('I am human')
# 通过type(instance)可以得到实例的class对象
if type(sup) is Superhero:
print('I am a superhero')

# 通过__mro__方法,可以获取类的继承链(super方法或者getattr方法)
print(Superhero.__mro__) # => (<class '__main__.Superhero'>, <class '__main__.Human'>, <class 'object'>)

# 使用父类方法,访问子类属性
print(sup.get_species()) # => Superhuman

# 调用覆盖了的方法
print(sup.sing()) # => Dun, dun, DUN!

# 调用父类的方法
sup.say('Spoon') # => Tick: Spoon

# 调用子类独有的方法
sup.boast() # => I wield the power of super strength!
# => I wield the power of bulletproofing!

# 继承了的类属性
sup.age = 31
print(sup.age) # => 31

# 子类独有的属性
print('Am I Oscar eligible? ' + str(sup.movie))
I am human
I am a superhero
(<class '__main__.Superhero'>, <class '__main__.Human'>, <class 'object'>)
Superhuman
Dun, dun, DUN!
Tick: Spoon
I wield the power of super strength!
I wield the power of bulletproofing!
31
Am I Oscar eligible? False
1
2
3
####################################################
## 6.2 多重继承
####################################################
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 定义一个蝙蝠类
class Bat:

species = 'Baty'

def __init__(self, can_fly=True):
self.fly = can_fly

# 这个类页游say的方法
def say(self, msg):
msg = '... ... ...'
return msg

# 还有独有的方法
def sonar(self):
return '))) ... ((('
1
2
3
4
if __name__ == '__main__':
b = Bat()
print(b.say('hello'))
print(b.fly)
... ... ...
True
1
2
3
# 如果您写了多个文件,就需要导入一下
from superhero import Superhero
from bat import Bat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 定义蝙蝠侠,继承自超级英雄和蝙蝠两个类
class Batman(Superhero, Bat):

def __init__(self, *args, **kwargs):
# 通常,要继承属性,必须调用super
# 然而,我们在这里处理多个继承
# 而super()只适用于MRO列表中的下一个基类。
# 因此,我们明确地为所有祖先(父类)调用__init__
# 使用“*args”和“*kwargs”可以以一种干净的方式传递参数
# 每个父类“剥一层洋葱皮”
Superhero.__init__(self, 'anonymous', movie=True,
superpowers=['Wealthy'], *args, **kwargs)
Bat.__init__(self, *args, can_fly=False, **kwargs)
# override the value for the name attribute
self.name = 'Sad Affleck'

def sing(self):
return 'nan nan nan nan nan batman!'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if __name__ == '__main__':
sup = Batman()


# 通过__mro__方法,可以获取类的继承链(super方法或者getattr方法)
print(Batman.__mro__) # => (<class '__main__.Batman'>,
# => <class 'superhero.Superhero'>,
# => <class 'human.Human'>,
# => <class 'bat.Bat'>, <class 'object'>)

# 调用父类方法获取子类属性
print(sup.get_species()) # => Superhuman

# 调用覆盖后的方法
print(sup.sing()) # => nan nan nan nan nan batman!

# 两个父类有重名方法时,顺序在前的优先级更高
sup.say('I agree') # => Sad Affleck: I agree

# 调用第二父类方法
print(sup.sonar()) # => ))) ... (((

# 继承类属性
sup.age = 100
print(sup.age) # => 100

# 输出从第二父类继承的属性,该属性已被覆盖
print('Can I fly? ' + str(sup.fly)) # => Can I fly? False
(<class '__main__.Batman'>, <class '__main__.Superhero'>, <class '__main__.Human'>, <class '__main__.Bat'>, <class 'object'>)
Superhuman
nan nan nan nan nan batman!
Sad Affleck: I agree
))) ... (((
100
Can I fly? False
1
2
3
####################################################
## 7. Advanced
####################################################
1
2
3
4
# 生成器可以帮你偷很多懒
def double_numbers(iterable):
for i in iterable:
yield i + i
1
2
3
4
5
6
7
8
9
# 生成器可以节省很多内存
# 因为它们只加载所需处理iterable中的下一个值的数据(边生成边处理)
# 普通方法需要 先生成后处理
# 这使其可以进行大范围的数据操作(其他方法可能不行)
# 注意:python 3中,“range”替换了“xrange”
for i in double_numbers(range(1, 900000000)): # `range` is a generator.
print(i)
if i >= 30:
break
2
4
6
8
10
12
14
16
18
20
22
24
26
28
30
1
2
3
4
5
6
# 正如可以创建列表理解一样,也可以创建生成器理解
# 这里,圆括号是关键,你以为是tuples,实际上是生成器
values = (-x for x in [1,2,3,4,5])
print(values)
for x in values:
print(x) # prints -1 -2 -3 -4 -5 to console/terminal
<generator object <genexpr> at 0x102e9c990>
-1
-2
-3
-4
-5
1
2
3
4
# 也可以直接把一个生成器理解投射到list上
values = (-x for x in [1,2,3,4,5])
gen_to_list = list(values)
print(gen_to_list) # => [-1, -2, -3, -4, -5]
[-1, -2, -3, -4, -5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 修饰器
from functools import wraps


def beg(target_function):

@wraps(target_function)
def wrapper(*args, **kwargs):
msg, say_please = target_function(*args, **kwargs)
if say_please:
return "{} {}".format(msg, "Please! I am poor :(")
return msg

return wrapper

# 这里通过beg修饰say
# 可以改变say的输出
@beg
def say(say_please=False):
msg = "Can you buy me a beer?"
return msg, say_please
1
2
print(say())                 # Can you buy me a beer?
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
Can you buy me a beer?
Can you buy me a beer? Please! I am poor :(

译自:https://learnxinyminutes.com/docs/python3/

阅前须知:

  • “#”后边的是注释
  • 带行号的是python代码
  • 不带行号的是代码的输出
  • 把下边的语句对着敲一边自然就会了,博主用的是jupyter notebook
1
2
3
####################################################
## 5. 模块
####################################################
1
2
3
# 可以通过import语句导入模块(包)
import math
print(math.sqrt(16)) # => 4.0
4.0
1
2
3
4
# 也可以通过from import语句,从包中调用特定函数
from math import ceil, floor
print(ceil(3.7)) # => 4.0
print(floor(3.7)) # => 3.0
4
3
1
2
3
# 也可以通过*,导入包中所有函数
# 不建议这样做,命名空间容易冲突(重名)
from math import *
1
2
3
# 也可以通过import as语句来对包名进行缩写
import math as m
math.sqrt(16) == m.sqrt(16) # => True
True
1
2
3
4
5
# Python包都是提前写好普通的python文件
# 也可以自己写,import名称为文件名
# 通过dir方法,可以看包中所有方法的directory
import math
dir(math)
['__doc__',
 '__file__',
 '__loader__',
 '__name__',
 '__package__',
 '__spec__',
 'acos',
 'acosh',
 'asin',
 'asinh',
 'atan',
 'atan2',
 'atanh',
 'ceil',
 'copysign',
 'cos',
 'cosh',
 'degrees',
 'e',
 'erf',
 'erfc',
 'exp',
 'expm1',
 'fabs',
 'factorial',
 'floor',
 'fmod',
 'frexp',
 'fsum',
 'gamma',
 'gcd',
 'hypot',
 'inf',
 'isclose',
 'isfinite',
 'isinf',
 'isnan',
 'ldexp',
 'lgamma',
 'log',
 'log10',
 'log1p',
 'log2',
 'modf',
 'nan',
 'pi',
 'pow',
 'radians',
 'sin',
 'sinh',
 'sqrt',
 'tan',
 'tanh',
 'tau',
 'trunc']
1
2
3
# 如果你调用了一个自己写的包
# 其名称和内建包重复
# 则默认调用自己写的