菜鸟代码,python学习日常(三)python类与装饰器与简单计算函数

最近在学习类的一些知识,类顾名思义就是将一大堆函数进行封装,将其整理供外部调用,而在类中函数进行调用的过程中需要实例化对象,就是像这种操作:

def __init__(self):
	self.abc = abc

你后续所有有关于这个实例对象的变量都需要写一遍这个。在你封装几个函数过程中,可能会出现需要修改的变量过多,短时间无从下手,后面我发现有个装饰器@staticmethod,这个装饰器在每个类方法上面调用后,可以将函数定义为静态方法,可以直接在类中调用而不需要实例化对象。我就我最近写的一个计算器函数进行解析,其中包括了计算器的一些实现过程的分析,在这里记录一下。
计算器主要是想像eval()函数一样处理简单的算式,下面是我计算器的简单实现的一个构思:
1、创建一个计算容器包含加减乘除幂求余;
2、利用正则化方法提取字符串中的数字于符号形成一个列表;
3、建立计算优先级,幂 > 乘、除、取余 > 加、减;
4、通过递归计算出算式答案;
这里用到了两个python相关的库

import operator
import re

首先是计算的容器:

# 二元操作符映射表
operators = {
    '+': operator.add,
    '-': operator.sub,
    '*': operator.mul,
    '/': operator.truediv,
    '%': operator.mod,
    '**': operator.pow
}

然后是利用正则方法re.findall找到字符串中的数字于运算符。特别的:求幂的“**”这种运算符在使用转义字符划分时不能单独列出来,所以要使用[]先将普通运算符提出来再加上转义字符于求幂的第二个“*”即:

tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)

这个代码会将我们的字符串转换成一个列表 [‘a’, ‘+’, ‘b’] ,接下来就对目标列表进行判断,计算前提判断运算顺序
(幂 > 乘、除、取余 > 加、减):

    def find_operator(tokens):
    	priority1_ops = ['**']
    	priority2_ops = ['*', '/', '%']
    	priority3_ops = ['+', '-']
        for i in range(len(tokens)):
            if tokens[i] in priority1_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in priority2_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in priority3_ops:
                return i
        raise ValueError("无效的表达式")

最后就是运算步骤,通过递归计算到最后一个数停止进行:

def calculate_expression(tokens):
    if len(tokens) == 1:
        # 已经到达最底层,返回结果
        return float(tokens[0])
    elif len(tokens) == 3:
        # 处理简单的表达式
        op, num1, num2 = tokens
        return operators[op](float(num1), float(num2))
    else:
        # 处理复合表达式
        op_idx = find_operator(tokens)
        op = tokens[op_idx]
        num1 = tokens[op_idx-1]
        num2 = tokens[op_idx+1]
        result = operators[op](float(num1), float(num2))
        # 递归计算剩余的表达式
        tokens[op_idx-1:op_idx+2] = [str(result)]
        return calculate_expression(tokens)

直接输入我们需要进行运算的字符串式子:result = evaluate_expression(‘5+12/2+2*3-11%3+3**3’)
可以得到:result = 42.0

我们下面将这写方法封装成类,因为有方法中有很多变量需要调用,比如计算容器,以及优先级符号等。所以要对这些进行变量实例化创建,在__init__函数中:

class PrimaryCalculatorV2:
    operators = {
        '+': operator.add,
        '-': operator.sub,
        '*': operator.mul,
        '/': operator.truediv,
        '%': operator.mod,
        '**': operator.pow
    }

    priority1_ops = ['**']
    priority2_ops = ['*', '/', '%']
    priority3_ops = ['+', '-']

    def __init__(self):
        self.operators = PrimaryCalculatorV2.operators
        self.priority1_ops = PrimaryCalculatorV2.priority1_ops
        self.priority2_ops = PrimaryCalculatorV2.priority2_ops
        self.priority3_ops = PrimaryCalculatorV2.priority3_ops

    def find_operator(self, tokens):
        for i in range(len(tokens)):
            if tokens[i] in self.priority1_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in self.priority2_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in self.priority3_ops:
                return i
        raise ValueError("无效的表达式")

    def calculate_expression(self, tokens):
        if len(tokens) == 1:
            return tokens[0] if tokens[0].isdigit() else float(tokens[0])
        elif len(tokens) == 3:
            num1, op, num2 = tokens
            return self.operators[op](float(num1), float(num2))
        else:
            op_idx = self.find_operator(tokens)
            op = tokens[op_idx]
            num1 = tokens[op_idx - 1]
            num2 = tokens[op_idx + 1]
            result = self.operators[op](float(num1), float(num2))
            tokens[op_idx - 1:op_idx + 2] = [str(result)]
            return self.calculate_expression(tokens)

    def evaluate_expression(self, expression):
        tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)
        result = self.calculate_expression(tokens)
        return result

而我们如果使用装饰器@staticmethod,将我们的方法申明为静态的,我们就可以不在__init__中进行实例化变量创建了,少写了几行代码,不过注意的是,在类中调用的有关容器于运算优先级变量的过程中,需要直接调用我们的类名。静态写法如下:

class PrimaryCalculatorV1:
    operators = {
        '+': operator.add,
        '-': operator.sub,
        '*': operator.mul,
        '/': operator.truediv,
        '%': operator.mod,
        '**': operator.pow
    }
    priority1_ops = ['**']
    priority2_ops = ['*', '/', '%']
    priority3_ops = ['+', '-']

    def __init__(self):
        pass
    @staticmethod
    def __find_operator(tokens):
        for i in range(len(tokens)):
            if tokens[i] in PrimaryCalculatorV1.priority1_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in PrimaryCalculatorV1.priority2_ops:
                return i
        for i in range(len(tokens)):
            if tokens[i] in PrimaryCalculatorV1.priority3_ops:
                return i
        raise ValueError("无效的表达式")
    @staticmethod
    def __calculate_expression(tokens):
        if len(tokens) == 1:
            return tokens[0] if tokens[0].isdigit() else float(tokens[0])
        elif len(tokens) == 3:
            num1, op, num2 = tokens
            return PrimaryCalculatorV1.operators[op](float(num1), float(num2))
        else:
            op_idx = PrimaryCalculatorV1.__find_operator(tokens)
            op = tokens[op_idx]
            num1 = tokens[op_idx - 1]
            num2 = tokens[op_idx + 1]
            result = PrimaryCalculatorV1.operators[op](float(num1), float(num2))
            tokens[op_idx - 1:op_idx + 2] = [str(result)]
            return PrimaryCalculatorV1.__calculate_expression(tokens)

    def evaluate_expression(self, expression):
        tokens = re.findall(r'\d+|[-+*/]\*|\*|\+|\-|\*|\/|\%', expression)
        result = self.__calculate_expression(tokens)
        return result

以上就是本菜鸟所掌握的一些类有关知识了,如果有错误还有问题点,或者代码有问题的地方,欢迎各位大佬提出讨论,非常感谢🤣🤣🤣🤣🤣

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值