简易的JS计算器实现代码


Posted in Javascript onOctober 18, 2016

看看手机中的计算器,分为普通计算器和科学计算器

简易的JS计算器实现代码

 自认脑袋不够大,就实现一个普通版本的吧(支持正负数加减乘除等基本连续的运算,未提供括号功能)

看看图示效果:

简易的JS计算器实现代码

一、知识准备

1+1 = ?

正常来说,我们看到这个表达式都知道怎么运算,知道运算结果

但计算机不一样,计算机无法识别出这串表达式,它只能识别特定的规则:前缀表达式+ 1 1 或后缀表达式1 1 +

举个栗子

(3 + 4) × 5 - 6 就是中缀表达式
- × + 3 4 5 6 前缀表达式
3 4 + 5 × 6 - 后缀表达式 

所以为了实现程序的自动运算,我们需要将输入的数据转化为前缀或后缀表达式

前缀、中缀、后缀表达式的概念以及相互转换方法在这里就不多说了,这篇博文 说得比较清楚了

所以,在这个计算器的实现中,采用了后缀表达式的实现方式,参考以上文章,重点关注这两个算法:

与转换为前缀表达式相似,遵循以下步骤:
(1) 初始化两个栈:运算符栈S1和储存中间结果的栈S2;
(2) 从左至右扫描中缀表达式;
(3) 遇到操作数时,将其压入S2;
(4) 遇到运算符时,比较其与S1栈顶运算符的优先级:
(4-1) 如果S1为空,或栈顶运算符为左括号“(”,则直接将此运算符入栈;
(4-2) 否则,若优先级比栈顶运算符的高,也将运算符压入S1(注意转换为前缀表达式时是优先级较高或相同,而这里则不包括相同的情况);
(4-3) 否则,将S1栈顶的运算符弹出并压入到S2中,再次转到(4-1)与S1中新的栈顶运算符相比较;
(5) 遇到括号时:
(5-1) 如果是左括号“(”,则直接压入S1;
(5-2) 如果是右括号“)”,则依次弹出S1栈顶的运算符,并压入S2,直到遇到左括号为止,此时将这一对括号丢弃;
(6) 重复步骤(2)至(5),直到表达式的最右边;
(7) 将S1中剩余的运算符依次弹出并压入S2;
(8) 依次弹出S2中的元素并输出,结果的逆序即为中缀表达式对应的后缀表达式(转换为前缀表达式时不用逆序)。

与前缀表达式类似,只是顺序是从左至右:
从左至右扫描表达式,遇到数字时,将数字压入堆栈,遇到运算符时,弹出栈顶的两个数,用运算符对它们做相应的计算(次顶元素 op 栈顶元素),并将结果入栈;重复上述过程直到表达式最右端,最后运算得出的值即为表达式的结果。
例如后缀表达式“3 4 + 5 × 6 -”:
(1) 从左至右扫描,将3和4压入堆栈;
(2) 遇到+运算符,因此弹出4和3(4为栈顶元素,3为次顶元素,注意与前缀表达式做比较),计算出3+4的值,得7,再将7入栈;
(3) 将5入栈;
(4) 接下来是×运算符,因此弹出5和7,计算出7×5=35,将35入栈;
(5) 将6入栈;
(6) 最后是-运算符,计算出35-6的值,即29,由此得出最终结果。

二、实现过程

第一步当然是搭建计算器的页面结构,不是科学计算器,只提供了基本的运算功能,但也能即时地进行运算,显示出完整的中缀表达式,运算后保存上一条运算记录。

要先说一下:本来想实现小数点功能的,但小数点的存在让数据存储与数据显示的实现有了压力,实现过程实在脑大,索性先取消这个功能。 

1. 页面结构:

<h5>计算计算</h5>
  <!-- 计算器 -->
  <div class="calc-wrap">
    <div class="calc-in-out">
      <!-- 上一条运算记录 -->
      <p class="calc-history" title=""></p>
      <!-- 输入的数据 -->
      <p class="calc-in"></p>
      <!-- 输出的运算结果 -->
      <p class="calc-out active"></p>
    </div>
    <table class="calc-operation">
      <thead></thead>
      <tbody>
        <tr>
          <td data-ac="cls" class="cls">C</td>
          <td data-ac="del">←</td>
          <td data-ac="sq">x<sup>2</sup></td>
          <td data-ac="mul">×</td>
        </tr>
        <tr>
          <td data-val="7">7</td>
          <td data-val="8">8</td>
          <td data-val="9">9</td>
          <td data-ac="div">÷</td>
        </tr>
        <tr>
          <td data-val="4">4</td>
          <td data-val="5">5</td>
          <td data-val="6">6</td>
          <td data-ac="plus">+</td>
        </tr>
        <tr>
          <td data-val="1">1</td>
          <td data-val="2">2</td>
          <td data-val="3">3</td>
          <td data-ac="minus">-</td>
        </tr>
          <td data-ac="per">%</td>
          <td data-val="0">0</td>
          <td data-ac="dot">.</td>
          <td data-ac="eq" class="eq">=</td>
      </tbody>
    </table>
  </div>

2. 结合一点样式:

body {
  padding: 20px;
  font-family: Arial;
}

.calc-wrap {
  width: 300px;
  border: 1px solid #ddd;
  border-radius: 3px;
}


.calc-operation {
  width: 100%;
  border-collapse: collapse;
}

.calc-in-out {
  width: 100%;
  padding: 10px 20px;
  text-align: right;
  box-sizing: border-box;
  background-color: rgba(250, 250, 250, .9);
}
.calc-in-out p {
  overflow: hidden;
  margin: 5px;
  width: 100%;
}
.calc-history {
  margin-left: -20px;
  font-size: 18px;
  color: #bbb;
  border-bottom: 1px dotted #ddf;
  min-height: 23px;
}

.calc-in,
.calc-out {
  font-size: 20px;
  color: #888;
  line-height: 39px;
  min-height: 39px;
}

.calc-in {
  color: #888;
}
.calc-out {
  color: #ccc;
}

.calc-in.active,
.calc-out.active {
  font-size: 34px;
  color: #666;
}

.calc-operation td {
  padding: 10px;
  width: 25%;
  text-align: center;
  border: 1px solid #ddd;
  font-size: 26px;
  color: #888;
  cursor: pointer;
}

.calc-operation td:active {
  background-color: #ddd;
}

.calc-operation .cls {
  color: #ee8956;
}

这样静态的计算器就粗来了~~

 简易的JS计算器实现代码

3. JS逻辑

这部分就是重点了,一步步来说

首先是对计算器的监听吧,也就是这个表格,可以使用事件委托的方式,在父级节点上监听处理

// 绑定事件
    bindEvent: function() {
      var that = this;

      that.$operation.on('click', function(e) {
        e = e || window.event;
        var elem = e.target || e.srcElement,
          val,
          action;

        if (elem.tagName === 'TD') {
          val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');

监听数据,获取到的只是页面上的某个值/操作符,所以需要将数据存储起来形成中缀,再由中缀转换成后缀,最后通过后缀进行计算

// 中缀表达式
    this.infix = [];
    // 后缀表达式
    this.suffix = [];
    // 后缀表达式运算结果集
    this.result = [];

按照算法步骤,实现出来,这里没有使用到括号,如果实际需要,可在相应位置修改判断条件即可~

// 中缀表达式转后缀
    infix2Suffix: function() {
      var temp = [];
      this.suffix = [];

      for (var i = 0; i < this.infix.length; i++) {
        // 数值,直接压入
        if (!this.isOp(this.infix[i])) {
          this.suffix.push(this.infix[i]);
        }
        else {
          if (!temp.length) {
            temp.push(this.infix[i]);
          }
          else {
            var opTop = temp[temp.length - 1];
            // 循环判断运算符优先级,将运算符较高的压入后缀表达式
            if (!this.priorHigher(opTop, this.infix[i])) {
              while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
                this.suffix.push(temp.pop());
                opTop = temp[temp.length - 1];
              }
            }
              // 将当前运算符也压入后缀表达式
            temp.push(this.infix[i]);
          }
        }
      }
      // 将剩余运算符号压入
      while (temp.length) {
        this.suffix.push(temp.pop());
      }
    },
// 后缀表达式计算
    calcSuffix: function() {
      this.result = [];

      for (var i = 0; i < this.suffix.length; i++) {
        // 数值,直接压入结果集
        if (!this.isOp(this.suffix[i])) {
          this.result.push(this.suffix[i]);
        }
        // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
        else {
          this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
        }
      }
      // 此时结果集中只有一个值,即为结果
       return this.result[0];
    }

其实,在实现的时候会发现,中缀、后缀只是一个难点,更复杂的地方是整个计算器的状态变化(或者说是数据变化)

在这个简单的计算器中,就有数字(0-9)、运算符(+ - * /)、操作(清除 删除)、预运算(百分号 平方)、小数点、即时运算等数据及操作

如果是科学计算器那就更复杂了,所以理清如何控制这些东西很关键,而其中最重要的就是中缀表达式的构建与存储

 当连续点击+号时,是不符合实际操作的,所以需要一个变量 lastVal 来记录上一个值,随着操作而更新,再通过判断,防止程序出错

在点击=号之后,我们可以继续使用这个结果进行运算,或者重新开始运算

// 构建中缀表达式
    buildInfix: function(val, type) {
      // 直接的点击等于运算之后,
      if (this.calcDone) {
        this.calcDone = false;
        // 再点击数字,则进行新的运算
        if (!this.isOp(val)) {
          this.resetData();
        }
        // 再点击运算符,则使用当前的结果值继续进行运算
        else {
          var re = this.result[0];
          this.resetData();
          this.infix.push(re);
        }

      }

      var newVal;
       ...

点击删除,是删除一位数,不是直接地删除一个数,然后更新中缀表达式的值

// 删除操作
      if (type === 'del') {
        newVal = this.infix.pop();
        // 删除末尾一位数
        newVal = Math.floor(newVal / 10);
        if (newVal) {
          this.infix.push(newVal);
        }

        this.lastVal = this.infix[this.infix.length - 1];
        return this.infix;
      }

而添加操作,要考虑的就更多了,比如连续的连续运算符、连续的数字、运算符+ - 接上数字表示正负数,小数点的连接存取等

// 添加操作,首先得判断运算符是否重复
      else if (type === 'add') {
        // 两个连续的运算符
        if (this.isOp(val) && this.isOp(this.lastVal)) {
          return this.infix;
        }
        // 两个连续的数字
        else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
          newVal = this.lastVal * 10 + val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }
        // 首个数字正负数
        if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
          newVal = this.lastVal === '+' ? val : 0 - val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }


        this.infix.push(this.lastVal = val);
        return this.infix;
      }

在很多次操作的时候,计算器都需要即时地进行运算,为简化代码,可以封装成一个方法,在相应的位置调用即可

// 即时得进行运算
    calculate: function(type) {
      this.infix2Suffix();
      var suffixRe = this.calcSuffix();

      if (suffixRe) {
        this.$out.text('=' + suffixRe)
          .attr('title', suffixRe)
          .removeClass('active');

        // 如果是直接显示地进行等于运算
        if (type === 'eq') {
          this.$in.removeClass('active');
          this.$out.addClass('active');
          // 设置标记:当前已经显示地进行计算
          this.calcDone = true;
          this.lastVal = suffixRe;
          // 设置历史记录
          var history = this.infix.join('') + ' = ' + suffixRe;
          this.$history.text(history).attr('title', history);
        }

      }
    },

剩下的就是点击之后的处理过程了,也就是各种调用处理 传递数据->构建中缀处理数据->中缀转后缀->后缀运算显示

比如点击了数字

// 数字:0-9
          if (!isNaN(parseInt(val, 10))) {
            // 构建中缀表达式并显示
            var infixRe = that.buildInfix(parseInt(val, 10), 'add');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();

            return;
          }

又比如几个预运算,其实长得也差不多

// 预运算:百分比、小数点、平方
          else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
            if (!that.infix.length || that.isOp(that.lastVal)) {
              return;
            }

            if (action === 'per') {
              that.lastVal /= 100;
            } else if (action === 'sq') {
              that.lastVal *= that.lastVal;
            } else if (action === 'dot') {
              // that.curDot = true;
            }

            // 重新构建中缀表达式
            var infixRe = that.buildInfix(that.lastVal, 'change');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();
          }

以上就是这个简单计算器的实现步骤了,变化太多还不敢保证不会出错

基本逻辑如此,如果要加上小数点运算、括号运算、正余弦等科学计算器的功能,还是自己去实现吧。。脑大啊。。 

$(function() {

  function Calculator($dom) {
    this.$dom = $($dom);
    // 历史运算
    this.$history = this.$dom.find('.calc-history');
    // 输入区
    this.$in = this.$dom.find('.calc-in');
    // 输出区
    this.$out = this.$dom.find('.calc-out');
    this.$operation = this.$dom.find('.calc-operation');

    // 运算符映射
    this.op = {
      'plus': '+',
      'minus': '-',
      'mul': '*',
      'div': '/'
    };
    this.opArr = ['+', '-', '*', '/'];

    // 中缀表达式
    this.infix = [];
    // 后缀表达式
    this.suffix = [];
    // 后缀表达式运算结果集
    this.result = [];
    // 存储最近的值
    this.lastVal = 0;
    // 当前已经计算等于完成
    this.calcDone = false;
    // 当前正在进行小数点点(.)相关值的修正
    this.curDot = false;

    this.init();
  }

  Calculator.prototype = {
    constructor: Calculator,
    // 初始化
    init: function() {
      this.bindEvent();
    },
    // 绑定事件
    bindEvent: function() {
      var that = this;

      that.$operation.on('click', function(e) {
        e = e || window.event;
        var elem = e.target || e.srcElement,
          val,
          action;

        if (elem.tagName === 'TD') {
          val = elem.getAttribute('data-val') || elem.getAttribute('data-ac');
          // 数字:0-9
          if (!isNaN(parseInt(val, 10))) {
            // 构建中缀表达式并显示
            var infixRe = that.buildInfix(parseInt(val, 10), 'add');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();

            return;
          }

          action = val;

          // 操作:清除、删除、计算等于
          if (['cls', 'del', 'eq'].indexOf(action) !== -1) {
            if (!that.infix.length) {
              return;
            }

            // 清空数据
            if (action === 'cls' || (action === 'del' && that.calcDone)) {
              that.$in.text('');
              that.$out.text('');

              that.resetData();
            }
            // 清除
            else if (action === 'del') {
              // 重新构建中缀表达式
              var infixRe = that.buildInfix(that.op[action], 'del');
              that.$in.text(infixRe.join('')).addClass('active');

              that.calculate();

            }
            // 等于
            else if (action === 'eq') {
              that.calculate('eq');

            }
          }
          // 预运算:百分比、小数点、平方
          else if (['per', 'dot', 'sq'].indexOf(action) !== -1) {
            if (!that.infix.length || that.isOp(that.lastVal)) {
              return;
            }

            if (action === 'per') {
              that.lastVal /= 100;
            } else if (action === 'sq') {
              that.lastVal *= that.lastVal;
            } else if (action === 'dot') {
              // that.curDot = true;
            }

            // 重新构建中缀表达式
            var infixRe = that.buildInfix(that.lastVal, 'change');
            that.$in.text(infixRe.join('')).addClass('active');

            that.calculate();
          }
          // 运算符:+ - * /
          else if (that.isOp(that.op[action])) {
            if (!that.infix.length && (that.op[action] === '*' || that.op[action] === '/')) {
              return;
            }

            var infixRe = that.buildInfix(that.op[action], 'add');
            that.$in.text(infixRe.join('')).addClass('active');
          }
        }
      });
    },

    resetData: function() {
      this.infix = [];
      this.suffix = [];
      this.result = [];
      this.lastVal = 0;
      this.curDot = false;
    },

    // 构建中缀表达式
    buildInfix: function(val, type) {
      // 直接的点击等于运算之后,
      if (this.calcDone) {
        this.calcDone = false;
        // 再点击数字,则进行新的运算
        if (!this.isOp(val)) {
          this.resetData();
        }
        // 再点击运算符,则使用当前的结果值继续进行运算
        else {
          var re = this.result[0];
          this.resetData();
          this.infix.push(re);
        }

      }

      var newVal;

      // 删除操作
      if (type === 'del') {
        newVal = this.infix.pop();
        // 删除末尾一位数
        newVal = Math.floor(newVal / 10);
        if (newVal) {
          this.infix.push(newVal);
        }

        this.lastVal = this.infix[this.infix.length - 1];
        return this.infix;
      }
      // 添加操作,首先得判断运算符是否重复
      else if (type === 'add') {
        // 两个连续的运算符
        if (this.isOp(val) && this.isOp(this.lastVal)) {
          return this.infix;
        }
        // 两个连续的数字
        else if (!this.isOp(val) && !this.isOp(this.lastVal)) {
          newVal = this.lastVal * 10 + val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }
        // 首个数字正负数
        if (!this.isOp(val) && this.infix.length === 1 && (this.lastVal === '+' || this.lastVal === '-')) {
          newVal = this.lastVal === '+' ? val : 0 - val;
          this.infix.pop();
          this.infix.push(this.lastVal = newVal);

          return this.infix;
        }

      // TODO: 小数点运算
      //   if (this.isOp(val)) {
      //     this.curDot = false;
      //   }

      //   // 小数点
      //   if (this.curDot) {
      //     var dotLen = 0;
      //     newVal = this.infix.pop();
      //     dotLen = newVal.toString().split('.');
      //     dotLen = dotLen[1] ? dotLen[1].length : 0;

      //     newVal += val / Math.pow(10, dotLen + 1);
      //     // 修正小数点运算精确值
      //     newVal = parseFloat(newVal.toFixed(dotLen + 1));

      //     this.infix.push(this.lastVal = newVal);
      //     return this.infix;
      //   }

        this.infix.push(this.lastVal = val);
        return this.infix;
      }

      // 更改操作,比如%的预运算
      else if (type === 'change') {
        this.infix.pop();
        this.infix.push(this.lastVal = val);

        return this.infix;
      }

    },
    // 判断是否为运算符
    isOp: function(op) {
      return op && this.opArr.indexOf(op) !== -1;
    },
    // 判断运算符优先级
    priorHigher: function(a, b) {
      return (a === '+' || a === '-') && (b === '*' || b === '/');
    },
    // 进行运算符的运算
    opCalc: function(b, op, a) {
      return op === '+'
        ? a + b
        : op === '-'
        ? a - b
        : op === '*'
        ? a * b
        : op === '/'
        ? a / b
        : 0;
    },
    // 即时得进行运算
    calculate: function(type) {
      this.infix2Suffix();
      var suffixRe = this.calcSuffix();

      if (suffixRe) {
        this.$out.text('=' + suffixRe)
          .attr('title', suffixRe)
          .removeClass('active');

        // 如果是直接显示地进行等于运算
        if (type === 'eq') {
          this.$in.removeClass('active');
          this.$out.addClass('active');
          // 设置标记:当前已经显示地进行计算
          this.calcDone = true;
          this.lastVal = suffixRe;
          // 设置历史记录
          var history = this.infix.join('') + ' = ' + suffixRe;
          this.$history.text(history).attr('title', history);
        }

      }
    },

    // 中缀表达式转后缀
    infix2Suffix: function() {
      var temp = [];
      this.suffix = [];

      for (var i = 0; i < this.infix.length; i++) {
        // 数值,直接压入
        if (!this.isOp(this.infix[i])) {
          this.suffix.push(this.infix[i]);
        }
        else {
          if (!temp.length) {
            temp.push(this.infix[i]);
          }
          else {
            var opTop = temp[temp.length - 1];
            // 循环判断运算符优先级,将运算符较高的压入后缀表达式
            if (!this.priorHigher(opTop, this.infix[i])) {
              while (temp.length && !this.priorHigher(opTop, this.infix[i])) {
                this.suffix.push(temp.pop());
                opTop = temp[temp.length - 1];
              }
            }
              // 将当前运算符也压入后缀表达式
            temp.push(this.infix[i]);
          }
        }
      }
      // 将剩余运算符号压入
      while (temp.length) {
        this.suffix.push(temp.pop());
      }
    },

    // 后缀表达式计算
    calcSuffix: function() {
      this.result = [];

      for (var i = 0; i < this.suffix.length; i++) {
        // 数值,直接压入结果集
        if (!this.isOp(this.suffix[i])) {
          this.result.push(this.suffix[i]);
        }
        // 运算符,从结果集中取出两项进行运算,并将运算结果置入结果集合
        else {
          this.result.push(this.opCalc(this.result.pop(), this.suffix[i], this.result.pop()));
        }
      }
      // 此时结果集中只有一个值,即为结果
       return this.result[0];
    }
  };

  new Calculator('.calc-wrap');
});

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js防止表单重复提交实现代码
Sep 05 Javascript
javascript常用的方法整理
Aug 20 Javascript
jQuery-1.9.1源码分析系列(十一)DOM操作续之克隆节点
Dec 01 Javascript
JavaScript弹出对话框的三种方式
Mar 23 Javascript
基于BootStrap与jQuery.validate实现表单提交校验功能
Dec 22 Javascript
JS基于正则截取替换特定字符之间字符串操作示例
Feb 03 Javascript
基于vue.js 2.x的虚拟滚动条的示例代码
Jan 23 Javascript
Angular 实现输入框中显示文章标签的实例代码
Nov 07 Javascript
jQuery实现购物车的总价计算和总价传值功能
Nov 28 jQuery
小程序数据通信方法大全(推荐)
Apr 15 Javascript
微信小程序开发之转发分享功能
Oct 22 Javascript
react antd表格中渲染一张或多张图片的实例
Oct 28 Javascript
用自定义图片代替原生checkbox实现全选,删除以及提交的方法
Oct 18 #Javascript
jquery中用jsonp实现搜索框功能
Oct 18 #Javascript
JavaScript排序算法动画演示效果的实现方法
Oct 18 #Javascript
浅谈js的异步执行
Oct 18 #Javascript
Jquery AJAX POST与GET之间的区别详细介绍
Oct 17 #Javascript
微信小程序 教程之模块化
Oct 17 #Javascript
微信小程序 教程之注册页面
Oct 17 #Javascript
You might like
调频问题解答
2021/03/01 无线电
php 注释规范
2012/03/29 PHP
Yii实现MySQL多数据库和读写分离实例分析
2014/12/03 PHP
php给一组指定关键词添加span标签的方法
2015/03/31 PHP
解析 thinkphp 框架中的部分方法
2017/05/07 PHP
PHP 实现公历日期与农历日期的互转换
2017/09/13 PHP
PHP isset()及empty()用法区别详解
2020/08/29 PHP
jquery checkbox全选、取消全选实现代码
2010/03/05 Javascript
基于jquery实现图片广告轮换效果代码
2011/07/07 Javascript
js open() 与showModalDialog()方法使用介绍
2013/09/10 Javascript
完美实现bootstrap分页查询
2015/12/09 Javascript
js事件驱动机制 浏览器兼容处理方法
2016/07/23 Javascript
jQuery实现简单的抽奖游戏
2017/05/05 jQuery
基于jQuery封装的分页组件
2017/06/26 jQuery
Angular将填入表单的数据渲染到表格的方法
2017/09/22 Javascript
JS声明对象时属性名加引号与不加引号的问题及解决方法
2018/02/16 Javascript
Bootstrap4如何定制自己的颜色和风格
2018/02/26 Javascript
js数组去重的N种方法(小结)
2018/06/07 Javascript
JS实现可视化文件上传
2018/09/08 Javascript
three.js利用gpu选取物体并计算交点位置的方法示例
2019/11/25 Javascript
vue-model实现简易计算器
2020/08/17 Javascript
[01:00]DOTA2 store: Collection of Artisan's Wonders
2015/08/12 DOTA
Perl中著名的Schwartzian转换问题解决实现
2015/06/02 Python
python爬取淘宝商品详情页数据
2018/02/23 Python
使用Python的toolz库开始函数式编程的方法
2018/11/15 Python
python之cv2与图像的载入、显示和保存实例
2018/12/05 Python
Python3显示当前时间、计算时间差及时间加减法示例代码
2019/09/07 Python
在echarts中图例legend和坐标系grid实现左右布局实例
2020/05/16 Python
python如何进行矩阵运算
2020/06/05 Python
英国现代家具和装饰网站:PN Home
2018/08/16 全球购物
Viking Direct爱尔兰:办公用品和家具
2019/11/21 全球购物
仪器仪表检测毕业生自荐信
2013/10/31 职场文书
共产党员公开承诺书
2014/03/25 职场文书
给公司的建议书范文
2014/05/13 职场文书
2019预备党员转正申请书模板2篇!
2019/08/07 职场文书
python中的class_static的@classmethod的巧妙用法
2021/06/22 Python